From 5eba4cee5cd14075319c264eafa21a371110f1a8 Mon Sep 17 00:00:00 2001 From: Juan Camilo Bohorquez Escalante Date: Fri, 16 Feb 2018 20:35:09 -0500 Subject: [PATCH] Add support for inline images --- src/docMeasure.js | 2 +- src/layoutBuilder.js | 2 +- src/line.js | 8 ++++---- src/printer.js | 6 +++++- src/tableProcessor.js | 5 +++-- src/textTools.js | 30 ++++++++++++++++++++---------- 6 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/docMeasure.js b/src/docMeasure.js index 292df0484..bc06db18f 100644 --- a/src/docMeasure.js +++ b/src/docMeasure.js @@ -17,7 +17,7 @@ var qrEncoder = require('./qrEnc.js'); * @private */ function DocMeasure(fontProvider, styleDictionary, defaultStyle, imageMeasure, tableLayouts, images) { - this.textTools = new TextTools(fontProvider); + this.textTools = new TextTools(fontProvider, this); this.styleStack = new StyleContextStack(styleDictionary, defaultStyle); this.imageMeasure = imageMeasure; this.tableLayouts = tableLayouts; diff --git a/src/layoutBuilder.js b/src/layoutBuilder.js index e611a9b5a..7ffa0a8f8 100644 --- a/src/layoutBuilder.js +++ b/src/layoutBuilder.js @@ -657,7 +657,7 @@ LayoutBuilder.prototype.buildNextLine = function (textNode) { while (textNode._inlines && textNode._inlines.length > 0 && line.hasEnoughSpaceForInline(textNode._inlines[0])) { var inline = textNode._inlines.shift(); - if (!inline.noWrap && inline.text.length > 1 && inline.width > line.maxWidth) { + if (!inline.noWrap && (!inline.text || inline.text.length > 1) && inline.width > line.maxWidth) { var widthPerChar = inline.width / inline.text.length; var maxChars = Math.floor(line.maxWidth / widthPerChar); if (maxChars < 1) { diff --git a/src/line.js b/src/line.js index f7fcc9ee9..b5fbe084a 100644 --- a/src/line.js +++ b/src/line.js @@ -19,7 +19,7 @@ Line.prototype.getAscenderHeight = function () { var y = 0; this.inlines.forEach(function (inline) { - y = Math.max(y, inline.font.ascender / 1000 * inline.fontSize); + y = Math.max(y, inline.font.ascender / 1000 * (inline.image ? inline._height : inline.fontSize)); }); return y; }; @@ -32,7 +32,7 @@ Line.prototype.hasEnoughSpaceForInline = function (inline) { return false; } - return this.inlineWidths + inline.width - this.leadingCut - (inline.trailingCut || 0) <= this.maxWidth; + return this.inlineWidths + (inline._width || inline.width) - this.leadingCut - (inline.trailingCut || 0) <= this.maxWidth; }; Line.prototype.addInline = function (inline) { @@ -44,7 +44,7 @@ Line.prototype.addInline = function (inline) { inline.x = this.inlineWidths - this.leadingCut; this.inlines.push(inline); - this.inlineWidths += inline.width; + this.inlineWidths += (inline._width || inline.width); if (inline.lineEnd) { this.newLineForced = true; @@ -63,7 +63,7 @@ Line.prototype.getHeight = function () { var max = 0; this.inlines.forEach(function (item) { - max = Math.max(max, item.height || 0); + max = Math.max(max, item.height || item._height || 0); }); return max; diff --git a/src/printer.js b/src/printer.js index 61eebe7d9..c1dbcb2f1 100644 --- a/src/printer.js +++ b/src/printer.js @@ -402,7 +402,11 @@ function renderLine(line, x, y, pdfKitDoc) { pdfKitDoc._font = inline.font; pdfKitDoc.fontSize(inline.fontSize); - pdfKitDoc.text(inline.text, x + inline.x, y + shiftToBaseline, options); + if (inline.image) { + pdfKitDoc.image(inline.image, x + inline.x, y, {width: inline.width}); + } else { + pdfKitDoc.text(inline.text, x + inline.x, y + shiftToBaseline, options); + } if (inline.linkToPage) { var _ref = pdfKitDoc.ref({Type: 'Action', S: 'GoTo', D: [inline.linkToPage, 0, 0]}).end(); diff --git a/src/tableProcessor.js b/src/tableProcessor.js index a82f8aee1..6a3419617 100644 --- a/src/tableProcessor.js +++ b/src/tableProcessor.js @@ -211,10 +211,11 @@ TableProcessor.prototype.drawVerticalLine = function (x, y0, y1, vLineIndex, wri if (width === 0) { return; } + var cx = x + width / 2; writer.addVector({ type: 'line', - x1: x + width / 2, - x2: x + width / 2, + x1: cx, + x2: cx, y1: y0, y2: y1, lineWidth: width, diff --git a/src/textTools.js b/src/textTools.js index de5ca6041..4e2a8a36e 100644 --- a/src/textTools.js +++ b/src/textTools.js @@ -15,8 +15,9 @@ var TRAILING = /(\s)+$/g; * @constructor * @param {FontProvider} fontProvider */ -function TextTools(fontProvider) { +function TextTools(fontProvider, docMeasure) { this.fontProvider = fontProvider; + this.docMeasure = docMeasure; } /** @@ -28,20 +29,20 @@ function TextTools(fontProvider) { * @return {Object} collection of inlines, minWidth, maxWidth */ TextTools.prototype.buildInlines = function (textArray, styleContextStack) { - var measured = measure(this.fontProvider, textArray, styleContextStack); + var measured = measure(this.fontProvider, textArray, styleContextStack, this.docMeasure); var minWidth = 0, maxWidth = 0, currentLineWidth; measured.forEach(function (inline) { - minWidth = Math.max(minWidth, inline.width - inline.leadingCut - inline.trailingCut); + minWidth = Math.max(minWidth, (inline.width || inline._width) - inline.leadingCut - inline.trailingCut); if (!currentLineWidth) { currentLineWidth = {width: 0, leadingCut: inline.leadingCut, trailingCut: 0}; } - currentLineWidth.width += inline.width; + currentLineWidth.width += inline.width || inline._width; currentLineWidth.trailingCut = inline.trailingCut; maxWidth = Math.max(maxWidth, getTrimmedWidth(currentLineWidth)); @@ -62,7 +63,7 @@ TextTools.prototype.buildInlines = function (textArray, styleContextStack) { }; function getTrimmedWidth(item) { - return Math.max(0, item.width - item.leadingCut - item.trailingCut); + return Math.max(0, (item.width || item._width) - item.leadingCut - item.trailingCut); } }; @@ -164,6 +165,11 @@ function normalizeTextArray(array, styleContextStack) { var style = null; var words; + if (item.image) { + results.push(item) + continue + } + var noWrap = getStyleProperty(item || {}, styleContextStack, 'noWrap', false); if (isObject(item)) { words = splitWords(normalizeString(item.text), noWrap); @@ -225,7 +231,7 @@ function getStyleProperty(item, styleContextStack, property, defaultValue) { } } -function measure(fontProvider, textArray, styleContextStack) { +function measure(fontProvider, textArray, styleContextStack, docMeasure) { var normalized = normalizeTextArray(textArray, styleContextStack); if (normalized.length) { @@ -257,10 +263,14 @@ function measure(fontProvider, textArray, styleContextStack) { var font = fontProvider.provideFont(fontName, bold, italics); - item.width = widthOfString(item.text, font, fontSize, characterSpacing, fontFeatures); - item.height = font.lineHeight(fontSize) * lineHeight; + if (item.image) { + docMeasure.measureImage(item) + } else { + item.width = widthOfString(item.text, font, fontSize, characterSpacing, fontFeatures); + item.height = font.lineHeight(fontSize) * lineHeight; + } - var leadingSpaces = item.text.match(LEADING); + var leadingSpaces = item.text ? item.text.match(LEADING) : [' ']; if (!item.leadingCut) { item.leadingCut = 0; @@ -270,7 +280,7 @@ function measure(fontProvider, textArray, styleContextStack) { item.leadingCut += widthOfString(leadingSpaces[0], font, fontSize, characterSpacing, fontFeatures); } - var trailingSpaces = item.text.match(TRAILING); + var trailingSpaces = item.text ? item.text.match(TRAILING) : [' ']; if (trailingSpaces) { item.trailingCut = widthOfString(trailingSpaces[0], font, fontSize, characterSpacing, fontFeatures); } else {