From 5f482abba3331eed80d71c89f7c32140d55de360 Mon Sep 17 00:00:00 2001
From: Kenneth Glassey
Date: Sun, 23 Nov 2014 19:38:53 -0800
Subject: [PATCH 1/4] Refactored API.text() for text alignment support closes
#383
---
jspdf.js | 68 +++++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 60 insertions(+), 8 deletions(-)
diff --git a/jspdf.js b/jspdf.js
index 29d391232..be1be0c63 100644
--- a/jspdf.js
+++ b/jspdf.js
@@ -979,7 +979,7 @@ var jsPDF = (function(global) {
* @methodOf jsPDF#
* @name text
*/
- API.text = function(text, x, y, flags, angle) {
+ API.text = function(text, x, y, flags, angle, align) {
/**
* Inserts something like this into PDF
* BT
@@ -1013,8 +1013,22 @@ var jsPDF = (function(global) {
// the user wanted to print multiple lines, so break the
// text up into an array. If the text is already an array,
// we assume the user knows what they are doing.
- if (typeof text === 'string' && text.match(/[\n\r]/)) {
- text = text.split(/\r\n|\r|\n/g);
+ // Convert text into an array anyway to simplify
+ // later code.
+ if (typeof text === 'string') {
+ if(text.match(/[\n\r]/)) {
+ text = text.split( /\r\n|\r|\n/g);
+ } else {
+ text = [text];
+ }
+ }
+ if (typeof angle === 'string') {
+ align = angle;
+ angle = null;
+ }
+ if (typeof flags === 'string') {
+ align = flags;
+ flags = null;
}
if (typeof flags === 'number') {
angle = flags;
@@ -1034,11 +1048,9 @@ var jsPDF = (function(global) {
if (!('autoencode' in flags))
flags.autoencode = true;
- if (typeof text === 'string') {
- text = ESC(text);
- } else if (text instanceof Array) {
+ if (text instanceof Array) {
// we don't want to destroy original text array, so cloning it
- var sa = text.concat(), da = [], len = sa.length;
+ var sa = text.concat(), da = [], i, len = sa.length;
// we do array.join('text that must not be PDFescaped")
// thus, pdfEscape each component separately
while (len--) {
@@ -1048,7 +1060,47 @@ var jsPDF = (function(global) {
if (0 <= linesLeft && linesLeft < da.length + 1) {
todo = da.splice(linesLeft-1);
}
- text = da.join(") Tj\nT* (");
+
+ if( align ) {
+ var left,
+ prevX,
+ maxLineLength,
+ leading = activeFontSize * lineHeightProportion,
+ lineWidths = text.map( function( v ) {
+ return this.getStringUnitWidth( v ) * activeFontSize / k;
+ }, this );
+ maxLineLength = Math.max.apply( Math, lineWidths );
+ // The first line uses the "main" Td setting,
+ // and the subsequent lines are offset by the
+ // previous line's x coordinate.
+ if( align === "center" ) {
+ // The passed in x coordinate defines
+ // the center point.
+ left = x - maxLineLength / 2;
+ x -= lineWidths[0] / 2;
+ } else if ( align === "right" ) {
+ // The passed in x coordinate defines the
+ // rightmost point of the text.
+ left = x - maxLineLength;
+ x -= lineWidths[0];
+ } else {
+ throw new Error('Unrecognized alignment option, use "center" or "right".');
+ }
+ prevX = x;
+ text = da[0] + ") Tj\n";
+ for ( i = 1, len = da.length ; i < len; i++ ) {
+ var delta = maxLineLength - lineWidths[i];
+ if( align === "center" ) delta /= 2;
+ // T* = x-offset leading Td ( text )
+ text += ( ( left - prevX ) + delta ) + " -" + leading + " Td (" + da[i];
+ prevX = left + delta;
+ if( i < len - 1 ) {
+ text += ") Tj\n";
+ }
+ }
+ } else {
+ text = da.join(") Tj\nT* (");
+ }
} else {
throw new Error('Type of text must be string or Array. "' + text + '" is not recognized.');
}
From 725e49e243063bc943e9736884880caa8dd46170 Mon Sep 17 00:00:00 2001
From: Kenneth Glassey
Date: Sun, 23 Nov 2014 19:40:15 -0800
Subject: [PATCH 2/4] Added demo functions to basic.js
To demo text alignment and angling.
---
examples/js/basic.js | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/examples/js/basic.js b/examples/js/basic.js
index e22f1789e..55a3635fb 100644
--- a/examples/js/basic.js
+++ b/examples/js/basic.js
@@ -351,3 +351,28 @@ function demoFromHTML() {
margins
)
}
+
+function demoTextAngles() {
+ var pdf = new jsPDF('p', 'pt', 'letter');
+
+ pdf.text( 'This text is at angle 0', 150, 50, 0 );
+ pdf.text( 'This text is at angle 45', 150, 300, 45 );
+ pdf.text( 'This text is at angle 90', 150, 600, 90 );
+ pdf.save('Test.pdf');
+}
+
+function demoTextAlign() {
+ var pdf = new jsPDF('p', 'pt', 'letter');
+
+ pdf.text( 'This text is centered\raround\rthis point.', 150, 50, 'center' );
+ pdf.text( 'This text is centered\raround\rthis point.', 150, 300, 45, 'center' );
+ pdf.text( 'This text is\raligned to the\rright.', 150, 400, 'right' );
+ pdf.text( 'This text is\raligned to the\rright.', 150, 550, 45, 'right' );
+
+ pdf.text( 'This text is centered\raround\rthis point.', 400, 50, 'center' );
+ pdf.text( 'This text is centered\raround\rthis point.', 400, 150, -85, 'center' );
+ pdf.text( 'This text is\raligned to the\rright.', 400, 400, 'right' );
+ pdf.text( 'This text is\raligned to the\rright.', 400, 550, -85, 'right' );
+
+ pdf.save('Test.pdf');
+}
\ No newline at end of file
From de9aa8255e8bf94a8683b6c62827d670600f9f13 Mon Sep 17 00:00:00 2001
From: Kenneth Glassey
Date: Sun, 23 Nov 2014 19:43:43 -0800
Subject: [PATCH 3/4] Demo function and html for text alignment
Removed text angling demo since that was not really relevant to my
additions.
---
examples/basic.html | 17 +++++++++++++++++
examples/js/basic.js | 9 ---------
2 files changed, 17 insertions(+), 9 deletions(-)
diff --git a/examples/basic.html b/examples/basic.html
index c769a636c..be5235613 100644
--- a/examples/basic.html
+++ b/examples/basic.html
@@ -342,6 +342,23 @@
diff --git a/examples/js/basic.js b/examples/js/basic.js
index 6230ae03f..f9ee87295 100644
--- a/examples/js/basic.js
+++ b/examples/js/basic.js
@@ -355,15 +355,28 @@ function demoFromHTML() {
function demoTextAlign() {
var pdf = new jsPDF('p', 'pt', 'letter');
- pdf.text( 'This text is centered\raround\rthis point.', 150, 50, 'center' );
- pdf.text( 'This text is centered\raround\rthis point.', 150, 300, 45, 'center' );
- pdf.text( 'This text is\raligned to the\rright.', 150, 400, 'right' );
- pdf.text( 'This text is\raligned to the\rright.', 150, 550, 45, 'right' );
-
- pdf.text( 'This text is centered\raround\rthis point.', 400, 50, 'center' );
- pdf.text( 'This text is centered\raround\rthis point.', 400, 150, -85, 'center' );
- pdf.text( 'This text is\raligned to the\rright.', 400, 400, 'right' );
- pdf.text( 'This text is\raligned to the\rright.', 400, 550, -85, 'right' );
+ pdf.setFillColor(0);
+ pdf.circle( 140, 50, 2, "F" );
+ pdf.text( 'This text is normally\raligned.', 140, 50 );
+
+ pdf.circle( 140, 120, 2, "F" );
+ pdf.text( 'This text is centered\raround\rthis point.', 140, 120, 'center' );
+
+ pdf.circle( 140, 300, 2, "F" );
+ pdf.text( 'This text is rotated\rand centered around\rthis point.', 140, 300, 45, 'center' );
+
+ pdf.circle( 140, 400, 2, "F" );
+ pdf.text( 'This text is\raligned to the\rright.', 140, 400, 'right' );
+
+ pdf.circle( 140, 550, 2, "F" );
+ pdf.text( 'This text is\raligned to the\rright.', 140, 550, 45, 'right' );
+
+ pdf.circle( 460, 50, 2, "F" );
+ pdf.text( 'This single line is centered', 460, 50, 'center' );
+
+ pdf.circle( 460, 200, 2, "F" );
+ pdf.text( 'This right aligned text\r\rhas an empty line.', 460, 200, 'right' );
+
pdf.save('Test.pdf');
}
\ No newline at end of file
diff --git a/jspdf.js b/jspdf.js
index be1be0c63..dd3b75648 100644
--- a/jspdf.js
+++ b/jspdf.js
@@ -1013,12 +1013,12 @@ var jsPDF = (function(global) {
// the user wanted to print multiple lines, so break the
// text up into an array. If the text is already an array,
// we assume the user knows what they are doing.
- // Convert text into an array anyway to simplify
- // later code.
if (typeof text === 'string') {
if(text.match(/[\n\r]/)) {
text = text.split( /\r\n|\r|\n/g);
} else {
+ // Convert text into an array anyway
+ // to simplify later code.
text = [text];
}
}
@@ -1062,41 +1062,34 @@ var jsPDF = (function(global) {
}
if( align ) {
- var left,
- prevX,
- maxLineLength,
+ var prevX,
leading = activeFontSize * lineHeightProportion,
lineWidths = text.map( function( v ) {
return this.getStringUnitWidth( v ) * activeFontSize / k;
}, this );
- maxLineLength = Math.max.apply( Math, lineWidths );
// The first line uses the "main" Td setting,
// and the subsequent lines are offset by the
// previous line's x coordinate.
if( align === "center" ) {
// The passed in x coordinate defines
- // the center point.
- left = x - maxLineLength / 2;
+ // the center point.
x -= lineWidths[0] / 2;
} else if ( align === "right" ) {
// The passed in x coordinate defines the
- // rightmost point of the text.
- left = x - maxLineLength;
+ // rightmost point of the text.
x -= lineWidths[0];
} else {
throw new Error('Unrecognized alignment option, use "center" or "right".');
}
prevX = x;
- text = da[0] + ") Tj\n";
+ text = da[0];
for ( i = 1, len = da.length ; i < len; i++ ) {
- var delta = maxLineLength - lineWidths[i];
+ var delta = lineWidths[i-1] - lineWidths[i];
if( align === "center" ) delta /= 2;
// T* = x-offset leading Td ( text )
- text += ( ( left - prevX ) + delta ) + " -" + leading + " Td (" + da[i];
- prevX = left + delta;
- if( i < len - 1 ) {
- text += ") Tj\n";
- }
+ // PDF Spec 1.3 p.288
+ text += ") Tj\n" + delta + " -" + leading + " Td (" + da[i];
+ prevX += delta;
}
} else {
text = da.join(") Tj\nT* (");