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 @@

+ +

Text alignment

+

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');
+Run Code

+ diff --git a/examples/js/basic.js b/examples/js/basic.js index 55a3635fb..6230ae03f 100644 --- a/examples/js/basic.js +++ b/examples/js/basic.js @@ -352,15 +352,6 @@ function demoFromHTML() { ) } -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'); From b84c7434ab80c26d2d5e95bbd60bd244941e4a1f Mon Sep 17 00:00:00 2001 From: Kenneth Glassey Date: Mon, 24 Nov 2014 08:19:36 -0800 Subject: [PATCH 4/4] Improved API.text() code Made the align code more efficient, and improved the example code. Removed jspdf.debug.js from commit. --- examples/basic.html | 21 +++++++++++++-------- examples/js/basic.js | 31 ++++++++++++++++++++++--------- jspdf.js | 27 ++++++++++----------------- 3 files changed, 45 insertions(+), 34 deletions(-) diff --git a/examples/basic.html b/examples/basic.html index be5235613..2d5cd8a18 100644 --- a/examples/basic.html +++ b/examples/basic.html @@ -346,15 +346,20 @@

Text alignment

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 normally\raligned.', 140, 50 );
+	
+	pdf.text( 'This text is centered\raround\rthis point.', 140, 120, 'center' );
+	
+	pdf.text( 'This text is rotated\rand centered around\rthis point.', 140, 300, 45, 'center' );
+	
+	pdf.text( 'This text is\raligned to the\rright.', 140, 400, 'right' );
+	
+	pdf.text( 'This text is\raligned to the\rright.', 140, 550, 45, 'right' );
+	
+	pdf.text( 'This single line is centered', 460, 50, 'center' );
+
+	pdf.text( 'This right aligned text\r\rhas an empty line.', 460, 200, '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');
Run Code

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* (");