From b000cf4de54de52548d143971ed720d7d3cd2bfd Mon Sep 17 00:00:00 2001 From: Owen Leong Date: Sun, 3 Oct 2021 00:47:50 +0800 Subject: [PATCH 1/5] Implement justifying for unicode fonts --- src/jspdf.js | 67 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 19 deletions(-) diff --git a/src/jspdf.js b/src/jspdf.js index 4a973423e..ec7eb9688 100644 --- a/src/jspdf.js +++ b/src/jspdf.js @@ -3786,23 +3786,23 @@ function jsPDF(options) { flags = Object.assign({ autoencode: true, noBOM: true }, options.flags); var wordSpacingPerLine = []; - + var findWidth = function(v) { + return ( + (scope.getStringUnitWidth(v, { + font: activeFont, + charSpace: charSpace, + fontSize: activeFontSize, + doKerning: false + }) * + activeFontSize) / + scaleFactor + ); + }; if (Object.prototype.toString.call(text) === "[object Array]") { da = transformTextToSpecialArray(text); var newY; if (align !== "left") { - lineWidths = da.map(function(v) { - return ( - (scope.getStringUnitWidth(v, { - font: activeFont, - charSpace: charSpace, - fontSize: activeFontSize, - doKerning: false - }) * - activeFontSize) / - scaleFactor - ); - }); + lineWidths = da.map(findWidth); } //The first line uses the "main" Td setting, //and the subsequent lines are offset by the @@ -3849,21 +3849,50 @@ function jsPDF(options) { for (var h = 0; h < len; h++) { text.push(da[h]); } + } else if (align === "justify" && activeFont.metadata.Unicode) { + // when using unicode fonts, wordSpacePerLine does not apply + text = []; + len = da.length; + maxWidth = maxWidth !== 0 ? maxWidth : pageWidth; + let backToStartX = 0 + for (var l = 0; l < len; l++) { + newY = l === 0 ? getVerticalCoordinate(y) : -leading; + newX = l === 0 ? getHorizontalCoordinate(x) : backToStartX; + if (l < len - 1) { + let spacing = scale( + (maxWidth - lineWidths[l]) / (da[l].split(" ").length - 1) + ); + let words = da[l].split(" "); + text.push([words[0] + " ", newX, newY]); + wordSpacingPerLine.push(spacing); + backToStartX = 0; // distance to reset back to the left + for (let i = 1; i < words.length; i++) { + let shiftAmount = (findWidth(words[i-1] + " " + words[i]) - + findWidth(words[i])) * scaleFactor + spacing; + if (i == words.length - 1) + text.push([words[i], shiftAmount, 0]); + else + text.push([words[i] + " ", shiftAmount, 0]); + wordSpacingPerLine.push(spacing); + backToStartX -= shiftAmount; + } + } else { + wordSpacingPerLine.push(0); // last line + text.push([da[l], newX, newY]); + } + } + text.push(["", backToStartX, -leading]); + wordSpacingPerLine.push(0); } else if (align === "justify") { text = []; len = da.length; maxWidth = maxWidth !== 0 ? maxWidth : pageWidth; - for (var l = 0; l < len; l++) { newY = l === 0 ? getVerticalCoordinate(y) : -leading; newX = l === 0 ? getHorizontalCoordinate(x) : 0; if (l < len - 1) { wordSpacingPerLine.push( - hpf( - scale( - (maxWidth - lineWidths[l]) / (da[l].split(" ").length - 1) - ) - ) + scale((maxWidth - lineWidths[l]) / (da[l].split(" ").length - 1)) ); } else { wordSpacingPerLine.push(0); From 00cd1323a70af558e9ac944fc82fbeb9394e2619 Mon Sep 17 00:00:00 2001 From: Owen Leong Date: Sun, 3 Oct 2021 00:58:04 +0800 Subject: [PATCH 2/5] Run prettier and revert dropping hpf --- src/jspdf.js | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/jspdf.js b/src/jspdf.js index ec7eb9688..43c9c2432 100644 --- a/src/jspdf.js +++ b/src/jspdf.js @@ -3854,7 +3854,7 @@ function jsPDF(options) { text = []; len = da.length; maxWidth = maxWidth !== 0 ? maxWidth : pageWidth; - let backToStartX = 0 + let backToStartX = 0; for (var l = 0; l < len; l++) { newY = l === 0 ? getVerticalCoordinate(y) : -leading; newX = l === 0 ? getHorizontalCoordinate(x) : backToStartX; @@ -3867,12 +3867,13 @@ function jsPDF(options) { wordSpacingPerLine.push(spacing); backToStartX = 0; // distance to reset back to the left for (let i = 1; i < words.length; i++) { - let shiftAmount = (findWidth(words[i-1] + " " + words[i]) - - findWidth(words[i])) * scaleFactor + spacing; - if (i == words.length - 1) - text.push([words[i], shiftAmount, 0]); - else - text.push([words[i] + " ", shiftAmount, 0]); + let shiftAmount = + (findWidth(words[i - 1] + " " + words[i]) - + findWidth(words[i])) * + scaleFactor + + spacing; + if (i == words.length - 1) text.push([words[i], shiftAmount, 0]); + else text.push([words[i] + " ", shiftAmount, 0]); wordSpacingPerLine.push(spacing); backToStartX -= shiftAmount; } @@ -3892,7 +3893,11 @@ function jsPDF(options) { newX = l === 0 ? getHorizontalCoordinate(x) : 0; if (l < len - 1) { wordSpacingPerLine.push( - scale((maxWidth - lineWidths[l]) / (da[l].split(" ").length - 1)) + hpf( + scale( + (maxWidth - lineWidths[l]) / (da[l].split(" ").length - 1) + ) + ) ); } else { wordSpacingPerLine.push(0); From 78c23294179505c94a855d146ce3189d69373de8 Mon Sep 17 00:00:00 2001 From: Owen Leong Date: Mon, 4 Oct 2021 01:31:51 +0800 Subject: [PATCH 3/5] Only use special case for Identity-H fonts --- src/jspdf.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/jspdf.js b/src/jspdf.js index 43c9c2432..c6bcc4a8e 100644 --- a/src/jspdf.js +++ b/src/jspdf.js @@ -3849,8 +3849,9 @@ function jsPDF(options) { for (var h = 0; h < len; h++) { text.push(da[h]); } - } else if (align === "justify" && activeFont.metadata.Unicode) { + } else if (align === "justify" && activeFont.encoding === "Identity-H") { // when using unicode fonts, wordSpacePerLine does not apply + console.log(activeFont); text = []; len = da.length; maxWidth = maxWidth !== 0 ? maxWidth : pageWidth; From 71de842e72b867408900c1afdf9841318dec6e80 Mon Sep 17 00:00:00 2001 From: Owen Leong Date: Mon, 4 Oct 2021 01:59:27 +0800 Subject: [PATCH 4/5] Add reference test --- src/jspdf.js | 1 - test/reference/justify-custom-font.pdf | Bin 0 -> 48919 bytes test/specs/text.spec.js | 19 +++++++++++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 test/reference/justify-custom-font.pdf diff --git a/src/jspdf.js b/src/jspdf.js index c6bcc4a8e..fbeea8ccc 100644 --- a/src/jspdf.js +++ b/src/jspdf.js @@ -3851,7 +3851,6 @@ function jsPDF(options) { } } else if (align === "justify" && activeFont.encoding === "Identity-H") { // when using unicode fonts, wordSpacePerLine does not apply - console.log(activeFont); text = []; len = da.length; maxWidth = maxWidth !== 0 ? maxWidth : pageWidth; diff --git a/test/reference/justify-custom-font.pdf b/test/reference/justify-custom-font.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2f4b8f0b7439af5a3b57ea208108e9fe48935d69 GIT binary patch literal 48919 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 UPmXG>4A%z30pE%hO|8xU4>_(9>;M1& literal 0 HcmV?d00001 diff --git a/test/specs/text.spec.js b/test/specs/text.spec.js index f5044db01..126ec5725 100644 --- a/test/specs/text.spec.js +++ b/test/specs/text.spec.js @@ -175,6 +175,25 @@ break` comparePdf(doc.output(), "alignment.pdf", "text"); }); + it("should justify custom font", () => { + const doc = jsPDF({ floatPrecision: 2 }); + var PTSans; + if (typeof global === "object" && global.isNode === true) { + PTSans = doc.loadFile("./test/reference/PTSans.ttf"); + } else { + PTSans = doc.loadFile("base/test/reference/PTSans.ttf"); + } + doc.addFileToVFS("PTSans.ttf", PTSans); + doc.addFont("PTSans.ttf", "PTSans", "normal"); + doc.setFont("PTSans"); + doc.setFontSize(10); + doc.text("А ну чики брики и в дамки! А ну чики брики и в дамки! А ну чики брики и в дамки! А ну чики брики и в дамки! А ну чики брики и в дамки! А ну чики брики и в дамки! А ну чики брики и в дамки! А ну чики брики и в дамки! А ну чики брики и в дамки! ", 10, 10, { + align: "justify", + maxWidth: 100, + }); + comparePdf(doc.output(), "justify-custom-font.pdf", "text"); + }); + it("should throw an error if not a string", () => { expect(() => { const doc = jsPDF({ floatPrecision: 2 }); From 3f8b2b5ae7dea3fd7624fc87735682cab0b8836a Mon Sep 17 00:00:00 2001 From: Owen Leong Date: Mon, 4 Oct 2021 02:22:06 +0800 Subject: [PATCH 5/5] Fix IE tests --- src/jspdf.js | 6 +----- test/reference/justify-custom-font.pdf | Bin 48919 -> 47504 bytes 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/jspdf.js b/src/jspdf.js index fbeea8ccc..b7f744449 100644 --- a/src/jspdf.js +++ b/src/jspdf.js @@ -3864,7 +3864,6 @@ function jsPDF(options) { ); let words = da[l].split(" "); text.push([words[0] + " ", newX, newY]); - wordSpacingPerLine.push(spacing); backToStartX = 0; // distance to reset back to the left for (let i = 1; i < words.length; i++) { let shiftAmount = @@ -3874,16 +3873,13 @@ function jsPDF(options) { spacing; if (i == words.length - 1) text.push([words[i], shiftAmount, 0]); else text.push([words[i] + " ", shiftAmount, 0]); - wordSpacingPerLine.push(spacing); backToStartX -= shiftAmount; } } else { - wordSpacingPerLine.push(0); // last line text.push([da[l], newX, newY]); } } - text.push(["", backToStartX, -leading]); - wordSpacingPerLine.push(0); + text.push(["", backToStartX, 0]); } else if (align === "justify") { text = []; len = da.length; diff --git a/test/reference/justify-custom-font.pdf b/test/reference/justify-custom-font.pdf index 2f4b8f0b7439af5a3b57ea208108e9fe48935d69..ae496b092432bef923856816aa78b708ece93343 100644 GIT binary patch delta 794 zcmb7AJxc>Y5GBdw!fi}M!I&H-T*MR}+_|^2yLSgF2GLd!+x!7R(NYnDm7OMzU?b=s z(8g8-e?e*+1$%9*74K4*a0`A+^_Y2Y-kUl9On2VXofD0DBIqLRKGv|1s$nzLz=M>X z0qSB?FKMC6L)_ITB0w2l>9g2MoBv^I6`a>>{K(q4pqsd*SMWl2@HxVxxf(9#rtm3i z{4lTMer^tz3=?;Z3SJrxzC?JORI?t$nR@v;9uoTxj0aM}H&Vsvyo0YJW+reYj-^ao zFEsGDU}LXfo)#;=k7u++Yhx2z#WHc202hQs-P@yL@utiGxJBc#wk^^JT!Jt0`YvcQ z2))FRGT}+3C%M}5{ZQeBsun0HJn&=?Y1_l8C_t34AMiUV1rCZa2${Tyf>aNIfT{aJ z0RxZNKPpZ|^sl%E#@rLh&v4-ZOYpexX?)4BmWv=v?&FeiMJp$zavhgGW4L#JMr6Pw KX*5>WR=)sGShvCe delta 2255 zcmds(O^OsT6vyf6nl3vVH@1#lI@YFbWFWre<>dp!g`gm`$Uq;!g)0|s2i)`p1g9s0 z8;>BvfD82i?u5C4cmqMVDyFJirmaf$jBaKVebL^2@agv9*>zr=zIA53}6_dC(gt z$Sg~dMUN*mZ+c~%oJp5Q<3BYJN(k(>uYOD7T zA1MQ;#z@SXqw