UNPKG

@syncfusion/ej2-pdf

Version:

Feature-rich JavaScript PDF library with built-in support for loading and manipulating PDF document.

612 lines (611 loc) 18.8 kB
import { _escapePdfName } from './../utils'; import { _PdfColorSpace } from '../enumerator'; /** * Low level PDF content writer that emits PDF operators and operands into * a content stream. Provides helpers for graphics state, paths, text, color, * and resource execution. * * @private */ var _PdfStreamWriter = /** @class */ (function () { /** * Creates a new stream writer bound to the given content stream. * * @param {_PdfContentStream} stream The target content stream to write to. * * @private */ function _PdfStreamWriter(stream) { /** * Newline delimiter used when writing PDF operators. * * @private */ this._newLine = '\r\n'; /** * Single whitespace used when separating PDF operator tokens. * * @private */ this._whiteSpace = ' '; this._stream = stream; } /** * Writes a raw PDF operator string followed by EOL. * * @param {string} value The operator string to write. * @returns {void} nothing. * * @private */ _PdfStreamWriter.prototype._writeOperator = function (value) { this._stream.write(value); this._stream.write(this._newLine); }; /** * Saves the current graphics state `q`. * * @private * @returns {void} nothing. */ _PdfStreamWriter.prototype._saveGraphicsState = function () { this._writeOperator('q'); }; /** * Restores the previous graphics state `Q`. * * @private * @returns {void} nothing. */ _PdfStreamWriter.prototype._restoreGraphicsState = function () { this._writeOperator('Q'); }; /** * Writes a PDF comment line when non-empty. * * @param {string} comment The comment text (no EOL needed). * @returns {void} nothing. * * @private */ _PdfStreamWriter.prototype._writeComment = function (comment) { if (comment && comment.length > 0) { this._writeOperator('% ' + comment); } }; /** * Sets the extended graphics state. * * @param {_PdfName} value The ExtGState resource name. * @returns {void} nothing. * * @private */ _PdfStreamWriter.prototype._setGraphicsState = function (value) { this._stream.write("/" + _escapePdfName(value.name) + " "); this._writeOperator('gs'); }; /** * Concatenates matrix with the current transformation matrix `cm`. * * @param {_PdfTransformationMatrix} matrix The transformation to apply. * @returns {void} nothing. * * @private */ _PdfStreamWriter.prototype._modifyCtm = function (matrix) { this._stream.write(matrix._toString() + " "); this._writeOperator('cm'); }; /** * Sets the text matrix and text line matrix `Tm`. * * @param {_PdfTransformationMatrix} matrix The text matrix to set. * @returns {void} nothing. * * @private */ _PdfStreamWriter.prototype._modifyTM = function (matrix) { this._stream.write(matrix._toString() + " "); this._writeOperator('Tm'); }; _PdfStreamWriter.prototype._setColorSpace = function (value, arg2, arg3) { if (typeof value === 'string' && typeof arg2 === 'boolean') { this._stream.write("/" + value + " "); this._writeOperator(arg2 ? 'CS' : 'cs'); } else if (Array.isArray(value) && typeof arg2 === 'number' && typeof arg3 === 'boolean') { var colorSpaceName = void 0; switch (arg2) { case _PdfColorSpace.rgb: colorSpaceName = 'DeviceRGB'; break; case _PdfColorSpace.cmyk: colorSpaceName = 'DeviceCMYK'; break; case _PdfColorSpace.grayScale: colorSpaceName = 'DeviceGray'; break; default: colorSpaceName = 'DeviceRGB'; break; } this._stream.write("/" + colorSpaceName + " "); this._writeOperator(arg3 ? 'CS' : 'cs'); this._setColor(value, arg3); } }; /** * Sets the current color for DeviceRGB using 0..255 components. * * @param {number[]} color The RGB array `[r,g,b]` (0..255). * @param {boolean} forStroking True for stroking color (`RG`), false for non-stroking (`rg`). * @returns {void} nothing. * * @private */ _PdfStreamWriter.prototype._setColor = function (color, forStroking) { this._stream.write((color[0] / 255).toFixed(3) + " " + (color[1] / 255).toFixed(3) + " " + (color[2] / 255).toFixed(3) + " "); this._writeOperator(forStroking ? 'RG' : 'rg'); }; /** * Appends a rectangle to the current path, using the current CTM. * * @param {number} x Left. * @param {number} y Top. * @param {number} width Width. * @param {number} height Height. * @returns {void} nothing. * * @private */ _PdfStreamWriter.prototype._appendRectangle = function (x, y, width, height) { this._writePoint(x, y); this._writePoint(width, height); this._writeOperator('re'); }; /** * Writes a point as two operands, auto flipping Y to PDF coordinates. * * @param {number} x X coordinate. * @param {number} y Y coordinate. * @returns {void} nothing. * * @private */ _PdfStreamWriter.prototype._writePoint = function (x, y) { this._stream.write(x.toFixed(3) + " " + (-y).toFixed(3) + " "); }; /** * Applies the current path as a clipping path and ends path. * * @param {boolean} isEvenOdd True for evenodd rule, false for nonzero. * @returns {void} nothing. * * @private */ _PdfStreamWriter.prototype._clipPath = function (isEvenOdd) { this._stream.write((isEvenOdd ? 'W*' : 'W') + " n" + this._newLine); }; /** * Fills the current path and ends the path. * * @param {boolean} isEvenOdd True for evenodd rule, false for nonzero. * @returns {void} nothing. * * @private */ _PdfStreamWriter.prototype._fillPath = function (isEvenOdd) { this._writeOperator(isEvenOdd ? 'f*' : 'f'); }; /** * Closes the current subpath then fill. * * @param {boolean} isEvenOdd True for evenodd rule, false for nonzero. * @returns {void} nothing. * * @private */ _PdfStreamWriter.prototype._closeFillPath = function (isEvenOdd) { this._writeOperator('h'); this._fillPath(isEvenOdd); }; /** * Strokes the current path `S` and ends the path. * * @private * @returns {void} nothing. */ _PdfStreamWriter.prototype._strokePath = function () { this._writeOperator('S'); }; /** * Closes and strokes the current path `s` and ends the path. * * @private * @returns {void} nothing. */ _PdfStreamWriter.prototype._closeStrokePath = function () { this._writeOperator('s'); }; /** * Fills and strokes the current path and ends the path. * * @param {boolean} isEvenOdd True for evenodd rule, false for nonzero. * @returns {void} nothing. * * @private */ _PdfStreamWriter.prototype._fillStrokePath = function (isEvenOdd) { this._writeOperator(isEvenOdd ? 'B*' : 'B'); }; /** * Closes, fills, and strokes the current path and ends the path. * * @param {boolean} isEvenOdd True for evenodd rule, false for nonzero. * @returns {void} nothing. * * @private */ _PdfStreamWriter.prototype._closeFillStrokePath = function (isEvenOdd) { this._writeOperator(isEvenOdd ? 'b*' : 'b'); }; /** * Ends the current path without filling or stroking `n`. * * @private * @returns {void} nothing. */ _PdfStreamWriter.prototype._endPath = function () { this._writeOperator('n'); }; /** * Sets the current font and size. * * @param {string} name The font resource name. * @param {number} size The font size in user units. * @returns {void} nothing. * * @private */ _PdfStreamWriter.prototype._setFont = function (name, size) { this._stream.write("/" + name + " " + size.toFixed(3) + " "); this._writeOperator('Tf'); }; /** * Sets horizontal text scaling in percent. * * @param {number} textScaling The scaling factor in percent. * @returns {void} nothing. * * @private */ _PdfStreamWriter.prototype._setTextScaling = function (textScaling) { this._stream.write(textScaling.toFixed(3) + " "); this._writeOperator('Tz'); }; /** * Closes the current subpath (`h`). Usually used before fill/stroke. * * @private * @returns {void} nothing. */ _PdfStreamWriter.prototype._closePath = function () { this._writeOperator('h'); }; _PdfStreamWriter.prototype._startNextLine = function (x, y) { if (typeof x === 'undefined') { this._writeOperator('T*'); } else { this._writePoint(x, y); this._writeOperator('Td'); } }; /** * Sets text leading `TL`, the vertical distance between baselines. * * @param {number} leading The leading in user units. * @returns {void} nothing. * * @private */ _PdfStreamWriter.prototype._setLeading = function (leading) { this._write(leading.toFixed(3) + " "); this._write(this._whiteSpace); this._writeOperator('TL'); }; /** * Shows text using the literal string form. The text is escaped as needed. * * @param {string} text The literal text content. * @returns {void} nothing. * * @private */ _PdfStreamWriter.prototype._showText = function (text) { this._writeText(text); this._writeOperator('Tj'); }; /** * Writes a raw string + CRLF, then as an operator. Internal helper. * * @param {string} string The string to write. * @returns {void} nothing. * * @private */ _PdfStreamWriter.prototype._write = function (string) { var builder = ''; builder += string; builder += '\r\n'; this._writeOperator(builder); }; /** * Writes a literal string operand with necessary escaping and parentheses wrapping. * * @param {string} text The unescaped text content. * @returns {void} nothing. * * @private */ _PdfStreamWriter.prototype._writeText = function (text) { var result = ''; var data = this._escapeSymbols(text); for (var i = 0; i < data.length; i++) { result += String.fromCharCode(data[i]); // eslint-disable-line } result = '(' + result + ')'; this._stream.write(result); }; /** * Begins a text object. * * @private * @returns {void} nothing. */ _PdfStreamWriter.prototype._beginText = function () { this._writeOperator('BT'); }; /** * Ends a text object. * * @private * @returns {void} nothing. */ _PdfStreamWriter.prototype._endText = function () { this._writeOperator('ET'); }; /** * Begins a new subpath at the specified point. * * @param {number} x X coordinate. * @param {number} y Y coordinate. * @returns {void} nothing. * * @private */ _PdfStreamWriter.prototype._beginPath = function (x, y) { this._writePoint(x, y); this._writeOperator('m'); }; /** * Appends a line segment to the specified point. * * @param {number} x X coordinate. * @param {number} y Y coordinate. * @returns {void} nothing. * * @private */ _PdfStreamWriter.prototype._appendLineSegment = function (x, y) { this._writePoint(x, y); this._writeOperator('l'); }; /** * Appends a cubic Bezier curve segment with two control points and an endpoint. * * @param {number} x1 First control point X. * @param {number} y1 First control point Y. * @param {number} x2 Second control point X. * @param {number} y2 Second control point Y. * @param {number} x3 End point X. * @param {number} y3 End point Y. * @returns {void} nothing. * * @private */ _PdfStreamWriter.prototype._appendBezierSegment = function (x1, y1, x2, y2, x3, y3) { this._writePoint(x1, y1); this._writePoint(x2, y2); this._writePoint(x3, y3); this._writeOperator('c'); }; /** * Sets the text rendering mode, combining fill/stroke/clip flags. * * @private * @param {number} renderingMode The rendering mode integer. * @returns {void} nothing. */ _PdfStreamWriter.prototype._setTextRenderingMode = function (renderingMode) { this._stream.write(renderingMode.toString() + " "); this._writeOperator('Tr'); }; /** * Sets character spacing in user units. * * @private * @param {number} charSpacing The character spacing. * @returns {void} nothing. */ _PdfStreamWriter.prototype._setCharacterSpacing = function (charSpacing) { this._stream.write(charSpacing.toFixed(3) + " "); this._writeOperator('Tc'); }; /** * Sets word spacing in user units. * * @private * @param {number} wordSpacing The word spacing. * @returns {void} nothing. */ _PdfStreamWriter.prototype._setWordSpacing = function (wordSpacing) { this._stream.write(wordSpacing.toFixed(3) + " "); this._writeOperator('Tw'); }; _PdfStreamWriter.prototype._showNextLineText = function (text, unicode) { if (unicode !== null && typeof unicode !== 'undefined' && unicode) { this._writeText(text); this._writeOperator('\''); } else { this._stream.write(text); this._writeOperator('\''); } }; /** * Sets the line dash pattern. Pattern elements are lengths in user units. * * @private * @param {number[]} pattern The dash/gap pattern array. * @param {number} patternOffset The dash phase offset. * @returns {void} nothing. */ _PdfStreamWriter.prototype._setLineDashPattern = function (pattern, patternOffset) { var tempPattern = '['; if (pattern.length >= 1) { for (var index = 0; index < pattern.length; index++) { if (index === pattern.length - 1) { tempPattern += pattern[index].toString(); // eslint-disable-line } else { tempPattern += pattern[index].toString() + ' '; // eslint-disable-line } } } tempPattern += '] '; tempPattern += patternOffset.toString(); tempPattern += ' d'; this._writeOperator(tempPattern); }; /** * Sets the miter limit. * * @private * @param {number} miterLimit The miter limit value. * @returns {void} nothing. */ _PdfStreamWriter.prototype._setMiterLimit = function (miterLimit) { this._stream.write(miterLimit.toFixed(3) + " "); this._writeOperator('M'); }; /** * Sets the line width (`w`). * * @private * @param {number} width The stroke width in user units. * @returns {void} nothing. */ _PdfStreamWriter.prototype._setLineWidth = function (width) { this._stream.write(width.toFixed(3) + " "); this._writeOperator('w'); }; /** * Sets the line cap style. * * @private * @param {number} lineCapStyle The line cap style (0=butt, 1=round, 2=square). * @returns {void} nothing. */ _PdfStreamWriter.prototype._setLineCap = function (lineCapStyle) { this._stream.write(lineCapStyle + " "); this._writeOperator('J'); }; /** * Sets the line join style. * * @private * @param {number} lineJoinStyle The join style (0=miter, 1=round, 2=bevel). * @returns {void} nothing. */ _PdfStreamWriter.prototype._setLineJoin = function (lineJoinStyle) { this._stream.write(lineJoinStyle + " "); this._writeOperator('j'); }; /** * Executes a named XObject or other resource. * * @private * @param {_PdfName} name The resource name to execute. * @returns {void} nothing. */ _PdfStreamWriter.prototype._executeObject = function (name) { this._stream.write("/" + name.name + " "); this._writeOperator('Do'); }; /** * Begins a markedcontent sequence. * * @private * @param {string} name The markedcontent tag name. * @returns {void} nothing. */ _PdfStreamWriter.prototype._beginMarkupSequence = function (name) { this._stream.write("/" + name + " "); this._writeOperator('BMC'); }; /** * Ends a markedcontent sequence. * * @private * @returns {void} nothing. */ _PdfStreamWriter.prototype._endMarkupSequence = function () { this._writeOperator('EMC'); }; /** * Clears the underlying content stream buffer. * * @private * @returns {void} nothing. */ _PdfStreamWriter.prototype._clear = function () { this._stream._bytes = []; }; /** * Escapes special characters for PDF literal strings. * * @param {string} value The unescaped text. * @returns {number[]} The escaped byte values. * * @private */ _PdfStreamWriter.prototype._escapeSymbols = function (value) { var data = []; for (var i = 0; i < value.length; i++) { var currentData = value.charCodeAt(i); switch (currentData) { case 40: case 41: data.push(92); data.push(currentData); break; case 13: data.push(92); data.push(114); break; case 92: data.push(92); data.push(currentData); break; default: data.push(currentData); break; } } return data; }; return _PdfStreamWriter; }()); export { _PdfStreamWriter };