@syncfusion/ej2-pdfviewer
Version:
Essential JS 2 PDF viewer Component
1,000 lines • 91 kB
JavaScript
import { Size } from './../primitives/size';
import { pathSegmentCollection, getRectanglePath, processPathData } from './../utility/path-util';
// import { overFlow } from './../utility/base-util';
import { createHtmlElement } from './../utility/dom-util';
/**
* @hidden
* Canvas Renderer
*/
var CanvasRenderer = /** @class */ (function () {
function CanvasRenderer() {
/** @private */
this.imageList = {};
this.rectWidth = 0;
}
/**
* @param {HTMLCanvasElement} canvas - canvas
* @private
* @returns {CanvasRenderingContext2D} - CanvasRenderingContext2D
*/
CanvasRenderer.getContext = function (canvas) {
return canvas.getContext('2d');
};
CanvasRenderer.prototype.setStyle = function (canvas, style) {
var ctx = CanvasRenderer.getContext(canvas);
if (style.fill === 'none') {
style.fill = 'transparent';
}
if (style.stroke === 'none') {
style.stroke = 'transparent';
}
ctx.strokeStyle = style.stroke;
if (style.thickness !== undefined) {
ctx.lineWidth = style.thickness * (96 / 72);
}
else {
ctx.lineWidth = style.strokeWidth;
}
if (style.strokeWidth === 0) {
ctx.strokeStyle = 'transparent';
}
if (style.isSharpEdge) {
ctx.lineJoin = 'miter';
ctx.miterLimit = 10;
ctx.lineCap = 'butt';
}
ctx.globalAlpha = style.opacity;
var dashArray = [];
if (style.dashArray) {
dashArray = this.parseDashArray(style.dashArray);
}
ctx.setLineDash(dashArray);
ctx.fillStyle = style.fill;
};
CanvasRenderer.prototype.setStyleFreetextEJ2 = function (canvas, style) {
var ctx = CanvasRenderer.getContext(canvas);
if (style.fill === 'none') {
style.fill = 'transparent';
}
if (style.stroke === 'none') {
style.stroke = 'transparent';
}
ctx.strokeStyle = style.stroke;
if (style.thickness !== undefined) {
ctx.lineWidth = style.thickness * (96 / 72);
}
else {
ctx.lineWidth = style.strokeWidth * (96 / 72);
}
if (style.strokeWidth === 0) {
ctx.strokeStyle = 'transparent';
}
ctx.lineJoin = 'miter';
ctx.miterLimit = 10;
ctx.lineCap = 'butt';
ctx.globalAlpha = style.opacity;
var dashArray = [];
if (style.dashArray) {
dashArray = this.parseDashArray(style.dashArray);
}
ctx.setLineDash(dashArray);
ctx.fillStyle = style.fill;
};
CanvasRenderer.prototype.rotateContext = function (canvas, angle, x, y) {
var ctx = CanvasRenderer.getContext(canvas);
ctx.translate(x, y);
ctx.rotate(angle * Math.PI / 180);
ctx.translate(-x, -y);
};
CanvasRenderer.prototype.setFontStyle = function (canvas, text) {
var ctx = CanvasRenderer.getContext(canvas);
var font = '';
if (text.italic) {
font += 'italic ';
}
if (text.bold) {
font += 'bold ';
}
font += (text.fontSize) + 'px ';
font += text.fontFamily;
ctx.font = font;
};
/**
* @param {string} dashArray - dashArray
* @private
* @returns {number[]} - array of number
*/
CanvasRenderer.prototype.parseDashArray = function (dashArray) {
var dashes = [];
var separator = dashArray.indexOf(' ') !== -1 ? ' ' : ',';
var splittedDashes = dashArray.split(separator);
for (var _i = 0, splittedDashes_1 = splittedDashes; _i < splittedDashes_1.length; _i++) {
var i = splittedDashes_1[_i];
dashes.push(Number(i));
}
return dashes;
};
//Rendering Part
/**
* @param {HTMLCanvasElement} canvas - canvas
* @param {RectAttributes} options - options
* @private
* @returns {void} - void
*/
CanvasRenderer.prototype.drawRectangle = function (canvas, options) {
if (options.childNodes === undefined) {
this.rectWidth = options.width;
}
if (options.visible === true) {
if (options.cornerRadius) {
options.data = getRectanglePath(options.cornerRadius, options.height, options.width);
this.drawPath(canvas, options);
}
else {
var ctx = CanvasRenderer.getContext(canvas);
ctx.save();
ctx.beginPath();
var cornerRadius = options.cornerRadius;
var pivotX = options.x + options.width * options.pivotX;
var pivotY = options.y + options.height * options.pivotY;
this.rotateContext(canvas, options.angle, pivotX, pivotY);
this.setStyle(canvas, options);
if (options.thickness !== undefined && !options.isShapeLabel) {
var strokeWidth = ctx.lineWidth || 1;
var halfStroke = strokeWidth / 2;
var strokeX = options.x + halfStroke;
var strokeY = options.y + halfStroke;
var strokeW = Math.max(0, options.width - strokeWidth);
var strokeH = Math.max(0, options.height - strokeWidth);
if (ctx.fillStyle !== 'transparent') {
var fillX = options.x + (strokeWidth > 0 ? strokeWidth : 0);
var fillY = options.y + (strokeWidth > 0 ? strokeWidth : 0);
var fillW = Math.max(0, options.width - (strokeWidth > 0 ? 2 * strokeWidth : 0));
var fillH = Math.max(0, options.height - (strokeWidth > 0 ? 2 * strokeWidth : 0));
if (fillW > 0 && fillH > 0) {
ctx.fillRect(fillX, fillY, fillW, fillH);
}
}
if (ctx.strokeStyle !== 'transparent' && strokeW > 0 && strokeH > 0) {
ctx.rect(strokeX, strokeY, strokeW, strokeH);
ctx.stroke();
ctx.closePath();
ctx.restore();
}
}
else {
ctx.rect(options.x, options.y, options.width, options.height);
ctx.fillRect(options.x, options.y, options.width, options.height);
if (!options.isRectangle) {
ctx.fill();
}
ctx.stroke();
ctx.closePath();
ctx.restore();
}
}
}
};
/**
* @param {HTMLCanvasElement} canvas - canvas
* @param {RectAttributes} options - options
* @private
* @returns {void} - void
*/
CanvasRenderer.prototype.drawRectangleFreetextEJ2 = function (canvas, options) {
if (options.childNodes === undefined) {
this.rectWidth = options.width;
}
if (options.visible === true) {
if (options.cornerRadius) {
options.data = getRectanglePath(options.cornerRadius, options.height, options.width);
this.drawPath(canvas, options);
}
else {
var ctx = CanvasRenderer.getContext(canvas);
ctx.save();
ctx.beginPath();
var cornerRadius = options.cornerRadius;
var pivotX = options.x + options.width * options.pivotX;
var pivotY = options.y + options.height * options.pivotY;
this.rotateContext(canvas, options.angle, pivotX, pivotY);
this.setStyleFreetextEJ2(canvas, options);
ctx.beginPath();
ctx.rect(options.x, options.y, options.width, options.height);
ctx.clip();
var strokeWidth = ctx.lineWidth || 1;
var halfStroke = strokeWidth / 2;
var strokeX = options.x + halfStroke;
var strokeY = options.y + halfStroke;
var strokeW = Math.max(0, options.width - strokeWidth);
var strokeH = Math.max(0, options.height - strokeWidth);
if (strokeH <= 0) {
strokeH = 1;
}
if (ctx.fillStyle !== 'transparent') {
var fillX = options.x + (strokeWidth > 0 ? strokeWidth : 0);
var fillY = options.y + (strokeWidth > 0 ? strokeWidth : 0);
var fillW = Math.max(0, options.width - (strokeWidth > 0 ? 2 * strokeWidth : 0));
var fillH = Math.max(0, options.height - (strokeWidth > 0 ? 2 * strokeWidth : 0));
if (fillW > 0 && fillH > 0) {
ctx.fillRect(fillX, fillY, fillW, fillH);
}
}
if (ctx.strokeStyle !== 'transparent' && strokeW > 0 && strokeH > 0) {
ctx.beginPath();
ctx.rect(strokeX, strokeY, strokeW, strokeH);
ctx.stroke();
ctx.closePath();
}
ctx.restore();
}
}
};
/**
* @param {HTMLCanvasElement} canvas - canvas
* @param {PathAttributes} options - options
* @private
* @returns {void} - void
*/
CanvasRenderer.prototype.drawPath = function (canvas, options) {
var collection = [];
collection = processPathData(options.data);
collection = pathSegmentCollection(collection);
var ctx = CanvasRenderer.getContext(canvas);
ctx.save();
ctx.beginPath();
var pivotY = options.y + options.height * options.pivotY;
var pivotX = options.x + options.width * options.pivotX;
this.rotateContext(canvas, options.angle, pivotX, pivotY);
this.setStyle(canvas, options);
ctx.translate(options.x, options.y);
if (options.strokeWidth > 1 && options.opacity < 1 && collection.length > 2 && options.id !== 'diagram_helper_content' &&
(options.annotationType === 'Polygon' || options.annotationType === 'Radius' || options.annotationType === 'Ellipse')) {
this.drawPathWithMask(canvas, ctx, options, collection);
}
else {
this.renderPath(canvas, options, collection);
ctx.fill();
ctx.translate(-options.x, -options.y);
ctx.stroke();
ctx.restore();
}
};
CanvasRenderer.prototype.drawPathWithMask = function (canvas, ctx, options, collection) {
ctx.save();
ctx.beginPath();
this.renderPath(canvas, options, collection);
ctx.globalAlpha = options.opacity;
ctx.fillStyle = options.fill;
ctx.fill('evenodd');
ctx.globalCompositeOperation = 'destination-out';
ctx.globalAlpha = 1;
ctx.lineWidth = options.strokeWidth;
ctx.stroke();
ctx.globalCompositeOperation = 'source-over';
ctx.strokeStyle = options.stroke;
ctx.lineWidth = options.strokeWidth;
ctx.globalAlpha = options.opacity;
ctx.stroke();
ctx.restore();
ctx.translate(-options.x, -options.y);
};
/**
* @param {HTMLCanvasElement} canvas - canvas
* @param {PathAttributes} options - options
* @param {Object[]} collection - collection
* @private
* @returns {void} - void
*/
CanvasRenderer.prototype.renderPath = function (canvas, options, collection) {
if (options.visible === true) {
var ctx = CanvasRenderer.getContext(canvas);
var x0 = void 0;
var y0 = void 0;
var x1 = void 0;
var y1 = void 0;
var x2 = void 0;
var y2 = void 0;
var x = void 0;
var y = void 0;
var length_1;
var i = void 0;
var newSeg = void 0;
var segs = collection;
for (x = 0, y = 0, i = 0, length_1 = segs.length; i < length_1; ++i) {
var obj = segs[parseInt(i.toString(), 10)];
var seg = obj;
var char = seg.command;
if ('x1' in seg) {
x1 = seg.x1;
}
if ('x2' in seg) {
x2 = seg.x2;
}
if ('y1' in seg) {
y1 = seg.y1;
}
if ('y2' in seg) {
y2 = seg.y2;
}
if ('x' in seg) {
x = seg.x;
}
if ('y' in seg) {
y = seg.y;
}
switch (char) {
case 'M':
ctx.moveTo(x, y);
seg.x = x;
seg.y = y;
break;
case 'L':
ctx.lineTo(x, y);
seg.x = x;
seg.y = y;
break;
case 'C':
ctx.bezierCurveTo(x1, y1, x2, y2, x, y);
seg.x = x;
seg.y = y;
seg.x1 = x1;
seg.y1 = y1;
seg.x2 = x2;
seg.y2 = y2;
break;
case 'Q':
ctx.quadraticCurveTo(x1, y1, x, y);
seg.x = x;
seg.y = y;
seg.x1 = x1;
seg.y1 = y1;
break;
case 'A':
{
var curr = { x: x0, y: y0 };
var rx = seg.r1;
var ry = seg.r2;
var xAxisRotation = seg.angle * (Math.PI / 180.0);
var largeArc = seg.largeArc;
var sweep = seg.sweep;
var cp = { x: x, y: y };
var currp = {
x: Math.cos(xAxisRotation) * (curr.x - cp.x) / 2.0 + Math.sin(xAxisRotation) * (curr.y - cp.y) / 2.0,
y: -Math.sin(xAxisRotation) * (curr.x - cp.x) / 2.0 + Math.cos(xAxisRotation) * (curr.y - cp.y) / 2.0
};
var l = Math.pow(currp.x, 2) / Math.pow(rx, 2) + Math.pow(currp.y, 2) / Math.pow(ry, 2);
if (l > 1) {
rx *= Math.sqrt(l);
ry *= Math.sqrt(l);
}
var k = (Math.pow(ry, 2) * Math.pow(currp.x, 2));
var s = (largeArc === sweep ? -1 : 1) * Math.sqrt(((Math.pow(rx, 2) * Math.pow(ry, 2)) - (Math.pow(rx, 2) * Math.pow(currp.y, 2)) - k) /
(Math.pow(rx, 2) * Math.pow(currp.y, 2) + Math.pow(ry, 2) * Math.pow(currp.x, 2)));
if (isNaN(s)) {
s = 0;
}
var cpp = { x: s * rx * currp.y / ry, y: s * -ry * currp.x / rx };
var centp = {
x: (curr.x + cp.x) / 2.0 + Math.cos(xAxisRotation) * cpp.x - Math.sin(xAxisRotation) * cpp.y,
y: (curr.y + cp.y) / 2.0 + Math.sin(xAxisRotation) * cpp.x + Math.cos(xAxisRotation) * cpp.y
};
var a1 = this.a([1, 0], [(currp.x - cpp.x) / rx, (currp.y - cpp.y) / ry]);
var u = [(currp.x - cpp.x) / rx, (currp.y - cpp.y) / ry];
var v = [(-currp.x - cpp.x) / rx, (-currp.y - cpp.y) / ry];
var ad = this.a(u, v);
if (this.r(u, v) <= -1) {
ad = Math.PI;
}
if (this.r(u, v) >= 1) {
ad = 0;
}
var dir = !sweep ? -1.0 : 1.0;
var ah = a1 + dir * (ad / 2.0);
var halfWay = {
x: centp.x + rx * Math.cos(ah),
y: centp.y + ry * Math.sin(ah)
};
seg.centp = centp;
seg.xAxisRotation = xAxisRotation;
seg.rx = rx;
seg.ry = ry;
seg.a1 = a1;
seg.ad = ad;
seg.sweep = sweep;
if (ctx != null) {
var ra = rx > ry ? rx : ry;
var sx = rx > ry ? 1 : rx / ry;
var sy = rx > ry ? ry / rx : 1;
ctx.save();
ctx.translate(centp.x, centp.y);
ctx.rotate(xAxisRotation);
ctx.scale(sx, sy);
ctx.arc(0, 0, ra, a1, a1 + ad, !sweep);
ctx.scale(1 / sx, 1 / sy);
ctx.rotate(-xAxisRotation);
ctx.translate(-centp.x, -centp.y);
ctx.restore();
}
break;
}
case 'Z':
case 'z':
ctx.closePath();
x = x0;
y = y0;
break;
}
x0 = x;
y0 = y;
}
}
};
/**
* @param {HTMLCanvasElement} canvas - canvas
* @param {TextAttributes} options - options
* @param {boolean} isFreeTextAnnotation - isFreeTextAnnotation
* @param {number} rectHeight - rectHeight
* @private
* @returns {void} - void
*/
CanvasRenderer.prototype.drawTextFreetextEJ2 = function (canvas, options, isFreeTextAnnotation, rectHeight) {
if (options.content && options.visible === true) {
var ctx_1 = CanvasRenderer.getContext(canvas);
ctx_1.save();
this.setStyle(canvas, options);
this.setFontStyle(canvas, options);
var ascent = 0;
var lineHeight = 0;
if (options.thickness !== undefined) {
// Used this to get the exact text height for Freetext annotation according to the font size and font family.
var metrics = ctx_1.measureText(options.content);
ascent = metrics.actualBoundingBoxAscent;
if (ascent == null) {
ascent = options.fontSize * 0.8;
}
var descent = metrics.actualBoundingBoxDescent;
if (descent == null) {
descent = options.fontSize * 0.2;
}
lineHeight = (ascent + descent);
options.height = lineHeight * options.childNodes.length;
}
var pivotX = options.x + options.width * options.pivotX;
var pivotY = options.y + options.height * options.pivotY;
this.rotateContext(canvas, options.angle, pivotX, pivotY);
var i = 0;
var childNodes = [];
childNodes = options.childNodes;
var wrapBounds = options.wrapBounds;
ctx_1.fillStyle = options.color;
if (wrapBounds) {
var position = this.labelAlign(options, wrapBounds, childNodes, lineHeight);
var padding = 0;
var paddingY = 0;
var heightDiff = rectHeight - (options.height + options.strokeWidth * 2);
var stroke = Math.ceil(options.strokeWidth || 0);
if (isFreeTextAnnotation && heightDiff >= 3.5) {
if (options.strokeWidth <= 4 && options.childNodes.length <= 1) {
padding = stroke * 1.5 * 1.65;
paddingY = stroke * 1.5 * 3;
}
else {
padding = stroke * 1.5 * 1.65;
if (options.strokeWidth <= 3) {
paddingY = stroke * 1.5 * 2;
}
else {
paddingY = stroke * 1.5 * 1.5;
}
}
}
else if (isFreeTextAnnotation) {
if (options.strokeWidth <= 4 && options.childNodes.length <= 1) {
padding = stroke * 1.5;
paddingY = stroke * 1.5;
}
else {
padding = stroke;
paddingY = stroke / 2;
}
}
else {
padding = options.strokeWidth / 2;
paddingY = options.strokeWidth / 2;
}
for (i = 0; i < childNodes.length; i++) {
var child = childNodes[parseInt(i.toString(), 10)];
var offsetX = void 0;
var offsetY = void 0;
var isTextDecorationApplied = false;
if (options.textAlign === 'justify') {
if (child.text === '\n') {
continue;
}
var baseSpaceWidth = ctx_1.measureText(' ').width;
var targetWidth = this.rectWidth - (Math.ceil(options.strokeWidth) * 3 * 1.5);
offsetX = position.x + child.x - wrapBounds.x + padding;
offsetY = position.y + child.dy * i + ((options.fontSize) * 0.8) + paddingY;
var isLastLine = i === childNodes.length - 1;
if (!isLastLine && targetWidth > 0) {
var leftEdge = position.x + child.x - wrapBounds.x + padding;
var words = child.text.trim().split(/\s+/);
if (words.length <= 1) {
ctx_1.fillText(child.text, leftEdge, offsetY);
continue;
}
var widths = words.map(function (w) { return ctx_1.measureText(w).width; });
var wordsTotal = widths.reduce(function (a, b) { return a + b; }, 0);
var gaps = words.length - 1;
var naturalWidth = wordsTotal + baseSpaceWidth * gaps;
var extra = Math.max(0, targetWidth - naturalWidth);
var extraPerGap = extra / gaps;
var pen = leftEdge;
for (var i_1 = 0; i_1 < words.length; i_1++) {
ctx_1.fillText(words[i_1], pen, offsetY);
if (i_1 < gaps) {
pen += widths[i_1] + baseSpaceWidth + extraPerGap;
}
}
if (options.textDecoration === 'Underline'
|| options.textDecoration === 'Overline'
|| options.textDecoration === 'LineThrough') {
var startX = leftEdge;
var startY = void 0;
var endX = leftEdge + targetWidth;
var endY = void 0;
switch (options.textDecoration) {
case 'Underline':
startY = offsetY + 2;
endY = offsetY + 2;
break;
case 'Overline':
startY = (position.y + child.dy * i);
endY = (position.y + child.dy * i);
break;
case 'LineThrough':
startY = ((offsetY + position.y + child.dy * i) / 2) + 2;
endY = ((offsetY + position.y + child.dy * i) / 2) + 2;
}
ctx_1.beginPath();
ctx_1.moveTo(startX, startY);
ctx_1.lineTo(endX, endY);
ctx_1.strokeStyle = options.color;
ctx_1.lineWidth = options.fontSize * .08;
ctx_1.globalAlpha = options.opacity;
ctx_1.stroke();
isTextDecorationApplied = true;
}
}
else {
ctx_1.fillText(child.text, offsetX, offsetY);
}
}
else if (child.text !== '\n') {
if (options.textAlign === 'right') {
offsetX = position.x + child.x - wrapBounds.x - padding;
}
else if (options.textAlign === 'center') {
offsetX = position.x + child.x - wrapBounds.x;
}
else {
offsetX = position.x + child.x - wrapBounds.x + padding;
}
if (options.relativeMode === 'Point') {
if (isFreeTextAnnotation && options.childNodes.length <= 1 && options.strokeWidth >= 5 && heightDiff <= 3.5) {
offsetY = position.y + child.dy * i + ((options.fontSize) * 0.8) - paddingY;
}
else {
offsetY = position.y + child.dy * i + ((options.fontSize) * 0.8) + paddingY;
}
if (options.strokeWidth === 0) {
offsetY += 1;
}
}
else {
offsetY = position.y + child.dy * i + ((options.fontSize) * 0.8);
}
ctx_1.fillText(child.text, offsetX, offsetY);
// if (wrapBounds.width > options.width && options.textOverflow !== 'Wrap') {
// child.text = overFlow(child.text, options);
// }
//ctx.fillText(child.text, offsetX, offsetY);
}
if (child.text !== '\n') {
var decorations = [];
if (Array.isArray(options.textDecoration)) {
decorations = options.textDecoration;
}
else if (options.textDecoration.includes(' ')) {
decorations = options.textDecoration.split(/[,\s]+/).filter(Boolean);
}
else {
decorations = [options.textDecoration];
}
for (var x = 0; x < decorations.length; x++) {
var textDecoration = decorations[x];
if (textDecoration === 'Underline'
|| textDecoration === 'Overline'
|| textDecoration === 'LineThrough' && !isTextDecorationApplied) {
var startPointX = offsetX;
var startPointY = void 0;
var textlength = ctx_1.measureText(child.text).width;
var endPointX = offsetX + textlength;
var endPointY = void 0;
switch (textDecoration) {
case 'Underline':
startPointY = offsetY + 2;
endPointY = offsetY + 2;
break;
case 'Overline':
startPointY = (position.y + child.dy * i);
endPointY = (position.y + child.dy * i);
break;
case 'LineThrough':
startPointY = ((offsetY + position.y + child.dy * i) / 2) + 2;
endPointY = ((offsetY + position.y + child.dy * i) / 2) + 2;
}
ctx_1.beginPath();
ctx_1.moveTo(startPointX, startPointY);
ctx_1.lineTo(endPointX, endPointY);
ctx_1.strokeStyle = options.color;
ctx_1.lineWidth = options.fontSize * .08;
ctx_1.globalAlpha = options.opacity;
ctx_1.stroke();
}
}
}
}
}
ctx_1.restore();
}
};
/**
* @param {HTMLCanvasElement} canvas - canvas
* @param {TextAttributes} options - options
* @param {boolean} isStampAnnotation - isStampAnnotation
* @private
* @returns {void} - void
*/
CanvasRenderer.prototype.drawTextEJ2 = function (canvas, options, isStampAnnotation) {
if (options.content && options.visible === true) {
var ctx_2 = CanvasRenderer.getContext(canvas);
ctx_2.save();
this.setStyle(canvas, options);
this.setFontStyle(canvas, options);
var ascent = 0;
var lineHeight = 0;
if (options.thickness !== undefined) {
// Used this to get the exact text height for Freetext annotation according to the font size and font family.
var metrics = ctx_2.measureText(options.content);
ascent = metrics.actualBoundingBoxAscent;
if (ascent == null) {
ascent = options.fontSize * 0.8;
}
var descent = metrics.actualBoundingBoxDescent;
if (descent == null) {
descent = options.fontSize * 0.2;
}
lineHeight = (ascent + descent);
options.height = lineHeight * options.childNodes.length;
}
var pivotX = options.x + options.width * options.pivotX;
var pivotY = options.y + options.height * options.pivotY;
this.rotateContext(canvas, options.angle, pivotX, pivotY);
var i = 0;
var childNodes = [];
childNodes = options.childNodes;
var wrapBounds = options.wrapBounds;
ctx_2.fillStyle = options.color;
if (wrapBounds) {
var position = this.labelAlign(options, wrapBounds, childNodes, lineHeight);
var paddingAdjustment = void 0;
if (isStampAnnotation) {
paddingAdjustment = options.thickness !== undefined ? (options.thickness * (96 / 72)) * 2 : 0;
}
for (i = 0; i < childNodes.length; i++) {
var child = childNodes[parseInt(i.toString(), 10)];
var offsetX = void 0;
var offsetY = void 0;
var isTextDecorationApplied = false;
if (options.textAlign === 'justify') {
if (child.text === '\n') {
continue;
}
var baseSpaceWidth = ctx_2.measureText(' ').width;
var targetWidth = wrapBounds.width;
offsetX = position.x + child.x - wrapBounds.x + options.strokeWidth / 2;
offsetY = position.y + child.dy * i + ((options.fontSize) * 0.8) + options.strokeWidth / 2;
var isLastLine = i === childNodes.length - 1;
if (!isLastLine && targetWidth > 0) {
var leftEdge = position.x + child.x + options.strokeWidth / 2;
var words = child.text.trim().split(/\s+/);
if (words.length <= 1) {
ctx_2.fillText(child.text, leftEdge, offsetY);
continue;
}
var widths = words.map(function (w) { return ctx_2.measureText(w).width; });
var wordsTotal = widths.reduce(function (a, b) { return a + b; }, 0);
var gaps = words.length - 1;
var naturalWidth = wordsTotal + baseSpaceWidth * gaps;
var extra = Math.max(0, targetWidth - naturalWidth);
var extraPerGap = extra / gaps;
var pen = leftEdge;
for (var i_2 = 0; i_2 < words.length; i_2++) {
ctx_2.fillText(words[i_2], pen, offsetY);
if (i_2 < gaps) {
pen += widths[i_2] + baseSpaceWidth + extraPerGap;
}
}
if (options.textDecoration === 'Underline'
|| options.textDecoration === 'Overline'
|| options.textDecoration === 'LineThrough') {
var startX = leftEdge;
var startY = void 0;
var endX = leftEdge + targetWidth;
var endY = void 0;
switch (options.textDecoration) {
case 'Underline':
startY = offsetY + 2;
endY = offsetY + 2;
break;
case 'Overline':
startY = (position.y + child.dy * i);
endY = (position.y + child.dy * i);
break;
case 'LineThrough':
startY = ((offsetY + position.y + child.dy * i) / 2) + 2;
endY = ((offsetY + position.y + child.dy * i) / 2) + 2;
}
ctx_2.beginPath();
ctx_2.moveTo(startX, startY);
ctx_2.lineTo(endX, endY);
ctx_2.strokeStyle = options.color;
ctx_2.lineWidth = options.fontSize * .08;
ctx_2.globalAlpha = options.opacity;
ctx_2.stroke();
isTextDecorationApplied = true;
}
}
else {
ctx_2.fillText(child.text, offsetX, offsetY);
}
}
else if (child.text !== '\n') {
if (options.textAlign === 'right') {
offsetX = position.x + child.x - wrapBounds.x - options.strokeWidth / 2;
}
else if (options.textAlign === 'center') {
offsetX = position.x + child.x - wrapBounds.x;
}
else {
if (isStampAnnotation) {
offsetX = position.x + child.x - wrapBounds.x + paddingAdjustment;
}
else {
offsetX = position.x + child.x - wrapBounds.x + options.strokeWidth / 2;
}
}
if (options.relativeMode === 'Point') {
if (isStampAnnotation) {
offsetY = position.y + child.dy * i + ((options.fontSize) * 0.8) + paddingAdjustment;
}
else {
offsetY = position.y + child.dy * i + ((options.fontSize) * 0.8) + options.strokeWidth / 2;
}
}
else {
offsetY = position.y + child.dy * i + ((options.fontSize) * 0.8);
}
ctx_2.fillText(child.text, offsetX, offsetY);
// if (wrapBounds.width > options.width && options.textOverflow !== 'Wrap') {
// child.text = overFlow(child.text, options);
// }
//ctx.fillText(child.text, offsetX, offsetY);
}
if (child.text !== '\n') {
if (options.textDecoration === 'Underline'
|| options.textDecoration === 'Overline'
|| options.textDecoration === 'LineThrough' && !isTextDecorationApplied) {
var startPointX = offsetX;
var startPointY = void 0;
var textlength = ctx_2.measureText(child.text).width;
var endPointX = offsetX + textlength;
var endPointY = void 0;
switch (options.textDecoration) {
case 'Underline':
startPointY = offsetY + 2;
endPointY = offsetY + 2;
break;
case 'Overline':
startPointY = (position.y + child.dy * i);
endPointY = (position.y + child.dy * i);
break;
case 'LineThrough':
startPointY = ((offsetY + position.y + child.dy * i) / 2) + 2;
endPointY = ((offsetY + position.y + child.dy * i) / 2) + 2;
}
ctx_2.beginPath();
ctx_2.moveTo(startPointX, startPointY);
ctx_2.lineTo(endPointX, endPointY);
ctx_2.strokeStyle = options.color;
ctx_2.lineWidth = options.fontSize * .08;
ctx_2.globalAlpha = options.opacity;
ctx_2.stroke();
}
}
}
}
ctx_2.restore();
}
};
/**
* @param {HTMLCanvasElement} canvas - canvas
* @param {TextAttributes} options - options
* @param {number} maxHeight - maxHeight
* @param {boolean} isFreeTextAnnotation - isFreeTextAnnotation
* @param {number} zoomFactor - zoomFactor
* @private
* @returns {void} - void
*/
CanvasRenderer.prototype.drawFreeTextBlazor = function (canvas, options, maxHeight, isFreeTextAnnotation, zoomFactor) {
if (options.content && options.visible === true) {
var ctx_3 = CanvasRenderer.getContext(canvas);
ctx_3.save();
this.setStyle(canvas, options);
this.setFontStyle(canvas, options);
var ascent = 0;
var lineHeight = 0;
if (options.thickness !== undefined) {
// Used this to get the exact text height for Freetext annotation according to the font size and font family.
var metrics = ctx_3.measureText(options.content);
ascent = metrics.actualBoundingBoxAscent;
if (ascent == null) {
ascent = options.fontSize * 0.8;
}
var descent = metrics.actualBoundingBoxDescent;
if (descent == null) {
descent = options.fontSize * 0.2;
}
lineHeight = (ascent + descent);
options.height = lineHeight * options.childNodes.length;
}
var pivotX = options.x + options.width * options.pivotX;
var pivotY = options.y + options.height * options.pivotY;
this.rotateContext(canvas, options.angle, pivotX, pivotY);
var i = 0;
var childNodes = [];
childNodes = options.childNodes;
var wrapBounds = options.wrapBounds;
ctx_3.fillStyle = options.color;
if (wrapBounds) {
var position = this.labelAlign(options, wrapBounds, childNodes, lineHeight);
var paddingAdjustmentX = options.thickness !== undefined &&
options.thickness === 0 ? Math.floor(options.thickness * (96 / 72)) + 2 : Math.floor(options.thickness * (96 / 72)) * 1 + 2;
var paddingAdjustmentY = options.thickness !== undefined &&
options.thickness === 0 ? Math.floor(options.thickness * (96 / 72)) + 5 : Math.floor(options.thickness * (96 / 72)) * 1 + 4;
var totalTextHeightCanvas = 0;
for (var j = 0; j < childNodes.length; j++) {
var child = childNodes[j];
totalTextHeightCanvas += (child.dy ? child.dy : (lineHeight || options.fontSize * 1.2));
}
var isApplyClip = isFreeTextAnnotation && maxHeight > 0 &&
Math.ceil(totalTextHeightCanvas + paddingAdjustmentY + 4) > maxHeight;
var clipLeft = void 0;
var clipTop = void 0;
var clipWidth = void 0;
var clipHeight = void 0;
var clipActive = false;
if (isApplyClip) {
if (options.textAlign === 'right') {
clipLeft = position.x - paddingAdjustmentX;
}
else if (options.textAlign === 'center') {
clipLeft = position.x;
}
else {
clipLeft = position.x + paddingAdjustmentX;
}
clipTop = position.y - ascent - paddingAdjustmentX;
clipWidth = Math.max(0, options.freeTextSelectorWidth + paddingAdjustmentX);
clipHeight = maxHeight + ascent;
}
if (isApplyClip) {
ctx_3.save();
ctx_3.beginPath();
ctx_3.rect(clipLeft, clipTop, clipWidth, clipHeight);
ctx_3.clip();
clipActive = true;
}
var textHeight = 0;
for (i = 0; i < childNodes.length; i++) {
var child = childNodes[parseInt(i.toString(), 10)];
var offsetX = void 0;
var offsetY = void 0;
var isTextDecorationApplied = false;
if (options.textAlign === 'justify') {
if (child.text === '\n') {
continue;
}
var baseSpaceWidth = ctx_3.measureText(' ').width;
var targetWidth = wrapBounds.width;
offsetX = position.x + child.x - wrapBounds.x + paddingAdjustmentX;
offsetY = position.y + child.dy * i + ascent + paddingAdjustmentY;
var isLastLine = i === childNodes.length - 1;
if (!isLastLine && targetWidth > 0) {
var leftEdge = position.x + child.x + paddingAdjustmentX;
var words = child.text.trim().split(/\s+/);
if (words.length <= 1) {
ctx_3.fillText(child.text, leftEdge, offsetY);
continue;
}
var widths = words.map(function (w) { return ctx_3.measureText(w).width; });
var wordsTotal = widths.reduce(function (a, b) { return a + b; }, 0);
var gaps = words.length - 1;
var naturalWidth = wordsTotal + baseSpaceWidth * gaps + paddingAdjustmentX * 2;
var extra = Math.max(0, targetWidth - naturalWidth);
var extraPerGap = extra / gaps;
var pen = leftEdge;
for (var i_3 = 0; i_3 < words.length; i_3++) {
ctx_3.fillText(words[i_3], pen, offsetY);
if (i_3 < gaps) {
pen += widths[i_3] + baseSpaceWidth + extraPerGap;
}
}
if (options.textDecoration === 'Underline'
|| options.textDecoration === 'Overline'
|| options.textDecoration === 'LineThrough' || options.textDecoration === 'Underline LineThrough') {
var startX = leftEdge;
var startY = void 0;
var endX = leftEdge + targetWidth - paddingAdjustmentX * 2;
var endY = void 0;
switch (options.textDecoration) {
case 'Underline':
startY = offsetY + 2;
endY = offsetY + 2;
this.drawLine(ctx_3, startX, startY, endX, endY, options);
break;
case 'Overline':
startY = (position.y + child.dy * i);
endY = (position.y + child.dy * i);
this.drawLine(ctx_3, startX, startY, endX, endY, options);
break;
case 'LineThrough':
startY = ((offsetY + position.y + child.dy * i) / 2) + 2 + (paddingAdjustmentY / 2);
endY = ((offsetY + position.y + child.dy * i) / 2) + 2 + (paddingAdjustmentY / 2);
this.drawLine(ctx_3, startX, startY, endX, endY, options);
break;
case 'Underline LineThrough':
{
this.drawLine(ctx_3, startX, offsetY + 2, endX, offsetY + 2, options);
var midY = (offsetY + position.y + child.dy * i) / 2 + 2 + paddingAdjustmentY / 2;
this.drawLine(ctx_3, startX, midY, endX, midY, options);
break;
}
}
isTextDecorationApplied = true;
}
}
else {
ctx_3.fillText(child.text, offsetX, offsetY);
}
}
else if (child.text !== '\n') {
if (options.textAlign === 'right') {
offsetX = position.x + child.x - wrapBounds.x - paddingAdjustmentX;
}
else if (options.textAlign === 'center') {
offsetX = position.x + child.x - wrapBounds.x;
}
else {
offsetX = position.x + child.x - wrapBounds.x + paddingAdjustmentX;
}
if (options.relativeMode === 'Point') {
offsetY = position.y + child.dy * i + ascent + paddingAdjustmentY;
}
else {
offsetY = position.y + child.dy * i + ((options.fontSize) * 0.8);
}
var tabSize = 7;
var textWithTabs = child.text.replace(/\t/g