@@ -632,7 +632,7 @@ var jsPDF = (function (global) {
632632 return documentProperties [ key ] = value ;
633633 } ;
634634
635- var objectNumber = 2 ; // 'n' Current object number
635+ var objectNumber = 0 ; // 'n' Current object number
636636 var offsets = [ ] ; // List of offsets. Activated and reset by buildDocument(). Pupulated by various calls buildDocument makes.
637637 var fonts = { } ; // collection of font objects, where key is fontKey - a dynamically created label for a given font.
638638 var fontmap = { } ; // mapping structure fontName > fontStyle > font key - performance layer. See addFont()
@@ -643,6 +643,45 @@ var jsPDF = (function (global) {
643643 var additionalObjects = [ ] ;
644644 var events = new PubSub ( API ) ;
645645 var hotfixes = options . hotfixes || [ ] ;
646+ var newObject = API . __private__ . newObject = function ( ) {
647+ var oid = newObjectDeferred ( ) ;
648+ newObjectDeferredBegin ( oid , true ) ;
649+ return oid ;
650+ } ;
651+
652+ // Does not output the object. The caller must call newObjectDeferredBegin(oid) before outputing any data
653+ var newObjectDeferred = API . __private__ . newObjectDeferred = function ( ) {
654+ objectNumber ++ ;
655+ offsets [ objectNumber ] = function ( ) {
656+ return content_length ;
657+ } ;
658+ return objectNumber ;
659+ } ;
660+
661+ var newObjectDeferredBegin = function ( oid , doOutput ) {
662+ doOutput = typeof ( doOutput ) === 'boolean' ? doOutput : false ;
663+ offsets [ oid ] = content_length ;
664+ if ( doOutput ) {
665+ out ( oid + ' 0 obj' ) ;
666+ }
667+ return oid ;
668+ } ;
669+ // Does not output the object until after the pages have been output.
670+ // Returns an object containing the objectId and content.
671+ // All pages have been added so the object ID can be estimated to start right after.
672+ // This does not modify the current objectNumber; It must be updated after the newObjects are output.
673+ var newAdditionalObject = API . __private__ . newAdditionalObject = function ( ) {
674+ var objId = newObjectDeferred ( ) ;
675+ var obj = {
676+ objId : objId ,
677+ content : ''
678+ } ;
679+ additionalObjects . push ( obj ) ;
680+ return obj ;
681+ } ;
682+
683+ var rootDictionaryObjId = newObjectDeferred ( ) ;
684+ var resourceDictionaryObjId = newObjectDeferred ( ) ;
646685
647686 /////////////////////
648687 // Private functions
@@ -754,41 +793,7 @@ var jsPDF = (function (global) {
754793 var getFilters = API . __private__ . getFilters = function ( ) {
755794 return filters ;
756795 } ;
757-
758- var newObject = API . __private__ . newObject = function ( ) {
759- // Begin a new object
760- objectNumber ++ ;
761- offsets [ objectNumber ] = content_length ;
762- out ( objectNumber + ' 0 obj' ) ;
763- return objectNumber ;
764- } ;
765- // Does not output the object until after the pages have been output.
766- // Returns an object containing the objectId and content.
767- // All pages have been added so the object ID can be estimated to start right after.
768- // This does not modify the current objectNumber; It must be updated after the newObjects are output.
769- var newAdditionalObject = API . __private__ . newAdditionalObject = function ( ) {
770- var objId = pages . length * 2 + 1 ;
771- objId += additionalObjects . length ;
772- var obj = {
773- objId : objId ,
774- content : ''
775- } ;
776- additionalObjects . push ( obj ) ;
777- return obj ;
778- } ;
779- // Does not output the object. The caller must call newObjectDeferredBegin(oid) before outputing any data
780- var newObjectDeferred = API . __private__ . newObjectDeferred = function ( ) {
781- objectNumber ++ ;
782- offsets [ objectNumber ] = function ( ) {
783- return content_length ;
784- } ;
785- return objectNumber ;
786- } ;
787-
788- var newObjectDeferredBegin = function ( oid ) {
789- offsets [ oid ] = content_length ;
790- } ;
791-
796+
792797 var putStream = API . __private__ . putStream = function ( options ) {
793798 options = options || { } ;
794799 var data = options . data || '' ;
@@ -849,24 +854,29 @@ var jsPDF = (function (global) {
849854 var dimensions = page . dimensions ;
850855 var pageNumber = page . number ;
851856 var data = page . data ;
857+ var pageObjectNumber = page . objId ;
858+ var pageContentsObjId = page . contentsObjId ;
852859
853- var pageObjectNumber = newObject ( ) ;
860+ newObjectDeferredBegin ( pageObjectNumber , true ) ;
854861 var wPt = dimensions . width * k ;
855862 var hPt = dimensions . height * k ;
856863 out ( '<</Type /Page' ) ;
857- out ( '/Parent 1 0 R' ) ;
858- out ( '/Resources 2 0 R' ) ;
864+ out ( '/Parent ' + page . rootDictionaryObjId + ' 0 R') ;
865+ out ( '/Resources ' + page . resourceDictionaryObjId + ' 0 R') ;
859866 out ( '/MediaBox [0 0 ' + f2 ( wPt ) + ' ' + f2 ( hPt ) + ']' ) ;
867+
860868 events . publish ( 'putPage' , {
869+ objId : pageObjectNumber ,
870+ pageContext : pagesContext [ pageNumber ] ,
861871 pageNumber : pageNumber ,
862872 page : data
863873 } ) ;
864- out ( '/Contents ' + ( objectNumber + 1 ) + ' 0 R' ) ;
874+ out ( '/Contents ' + pageContentsObjId + ' 0 R' ) ;
865875 out ( '>>' ) ;
866876 out ( 'endobj' ) ;
867877 // Page content
868878 var pageContent = data . join ( '\n' ) ;
869- newObject ( ) ;
879+ newObjectDeferredBegin ( pageContentsObjId , true ) ;
870880 putStream ( {
871881 data : pageContent ,
872882 filters : getFilters ( )
@@ -876,16 +886,25 @@ var jsPDF = (function (global) {
876886 }
877887 var putPages = API . __private__ . putPages = function ( ) {
878888 var n , p , i , pageObjectNumbers = [ ] ;
889+
890+
891+ for ( n = 1 ; n <= page ; n ++ ) {
892+ pagesContext [ n ] . objId = newObjectDeferred ( ) ;
893+ pagesContext [ n ] . contentsObjId = newObjectDeferred ( ) ;
894+ }
879895
880896 for ( n = 1 ; n <= page ; n ++ ) {
881897 pageObjectNumbers . push ( putPage ( {
882898 number : n ,
883899 data : pages [ n ] ,
884- dimensions : pagesContext [ n ] . dimensions
900+ objId : pagesContext [ n ] . objId ,
901+ contentsObjId : pagesContext [ n ] . contentsObjId ,
902+ dimensions : pagesContext [ n ] . dimensions ,
903+ rootDictionaryObjId : rootDictionaryObjId ,
904+ resourceDictionaryObjId : resourceDictionaryObjId
885905 } ) ) ;
886906 }
887- offsets [ 1 ] = content_length ;
888- out ( '1 0 obj' ) ;
907+ newObjectDeferredBegin ( rootDictionaryObjId , true ) ;
889908 out ( '<</Type /Pages' ) ;
890909 var kids = '/Kids [' ;
891910 for ( i = 0 ; i < page ; i ++ ) {
@@ -948,9 +967,7 @@ var jsPDF = (function (global) {
948967 var putResources = function ( ) {
949968 putFonts ( ) ;
950969 events . publish ( 'putResources' ) ;
951- // Resource dictionary
952- offsets [ 2 ] = content_length ;
953- out ( '2 0 obj' ) ;
970+ newObjectDeferredBegin ( resourceDictionaryObjId , true ) ;
954971 out ( '<<' ) ;
955972 putResourceDictionary ( ) ;
956973 out ( '>>' ) ;
@@ -962,12 +979,10 @@ var jsPDF = (function (global) {
962979 events . publish ( 'putAdditionalObjects' ) ;
963980 for ( var i = 0 ; i < additionalObjects . length ; i ++ ) {
964981 var obj = additionalObjects [ i ] ;
965- offsets [ obj . objId ] = content_length ;
966- out ( obj . objId + ' 0 obj' ) ;
967- out ( obj . content ) ; ;
982+ newObjectDeferredBegin ( obj . objId , true ) ;
983+ out ( obj . content ) ;
968984 out ( 'endobj' ) ;
969985 }
970- objectNumber += additionalObjects . length ;
971986 events . publish ( 'postPutAdditionalObjects' ) ;
972987 } ;
973988
@@ -1235,6 +1250,8 @@ var jsPDF = (function (global) {
12351250 outToPages = true ;
12361251 pages [ ++ page ] = [ ] ;
12371252 pagesContext [ page ] = {
1253+ objId : 0 ,
1254+ contentsObjId : 0 ,
12381255 dimensions : {
12391256 width : Number ( width ) ,
12401257 height : Number ( height ) ,
@@ -1340,11 +1357,13 @@ var jsPDF = (function (global) {
13401357 out ( 'endobj' ) ;
13411358 } ;
13421359
1343- var putCatalog = API . __private__ . putCatalog = function ( ) {
1360+ var putCatalog = API . __private__ . putCatalog = function ( options ) {
1361+ options = options || { } ;
1362+ var tmpRootDictionaryObjId = options . rootDictionaryObjId || rootDictionaryObjId ;
13441363 newObject ( ) ;
13451364 out ( '<<' ) ;
13461365 out ( '/Type /Catalog' ) ;
1347- out ( '/Pages 1 0 R' ) ;
1366+ out ( '/Pages ' + tmpRootDictionaryObjId + ' 0 R') ;
13481367 // PDF13ref Section 7.2.1
13491368 if ( ! zoomMode ) zoomMode = 'fullwidth' ;
13501369 switch ( zoomMode ) {
@@ -1438,11 +1457,14 @@ var jsPDF = (function (global) {
14381457 var buildDocument = API . __private__ . buildDocument = function ( ) {
14391458 outToPages = false ; // switches out() to content
14401459
1441- objectNumber = 2 ;
1460+ //reset fields relevant for objectNumber generation and xref.
1461+ objectNumber = 0 ;
14421462 content_length = 0 ;
14431463 content = [ ] ;
14441464 offsets = [ ] ;
14451465 additionalObjects = [ ] ;
1466+ rootDictionaryObjId = newObjectDeferred ( ) ;
1467+ resourceDictionaryObjId = newObjectDeferred ( ) ;
14461468
14471469 events . publish ( 'buildDocument' ) ;
14481470
@@ -1588,18 +1610,31 @@ var jsPDF = (function (global) {
15881610 if ( isNaN ( pageNumberOneBased ) || ( pageNumberOneBased % 1 !== 0 ) ) {
15891611 throw new Error ( 'Invalid argument passed to jsPDF.getPageInfo' ) ;
15901612 }
1591- var objId = ( pageNumberOneBased - 1 ) * 2 + 3 ;
1613+ var objId = pagesContext [ pageNumberOneBased ] . objId ;
15921614 return {
15931615 objId : objId ,
15941616 pageNumber : pageNumberOneBased ,
15951617 pageContext : pagesContext [ pageNumberOneBased ]
15961618 } ;
15971619 } ;
1620+
1621+ var getPageInfoByObjId = API . __private__ . getPageInfoByObjId = function ( objId ) {
1622+ var pageNumberWithObjId ;
1623+ for ( var pageNumber in pagesContext ) {
1624+ if ( pagesContext [ pageNumber ] . objId === objId ) {
1625+ pageNumberWithObjId = pageNumber ;
1626+ break ;
1627+ }
1628+ }
1629+ if ( isNaN ( objId ) || ( objId % 1 !== 0 ) ) {
1630+ throw new Error ( 'Invalid argument passed to jsPDF.getPageInfoByObjId' ) ;
1631+ }
1632+ return getPageInfo ( pageNumber ) ;
1633+ } ;
15981634
15991635 var getCurrentPageInfo = API . __private__ . getCurrentPageInfo = function ( ) {
1600- var objId = ( currentPage - 1 ) * 2 + 3 ;
16011636 return {
1602- objId : objId ,
1637+ objId : pagesContext [ currentPage ] . objId ,
16031638 pageNumber : currentPage ,
16041639 pageContext : pagesContext [ currentPage ]
16051640 } ;
@@ -1769,10 +1804,10 @@ var jsPDF = (function (global) {
17691804 align : align
17701805 } ;
17711806 }
1772-
1773- flags = flags || { } ;
1774- flags . noBOM = flags . noBOM || true ;
1775- flags . autoencode = flags . autoencode || true ;
1807+
1808+ flags = flags || { } ;
1809+ flags . noBOM = flags . noBOM || true ;
1810+ flags . autoencode = flags . autoencode || true ;
17761811
17771812 if ( isNaN ( x ) || isNaN ( y ) || typeof text === "undefined" ) {
17781813 throw new Error ( 'Invalid arguments passed to jsPDF.text' ) ;
@@ -3158,6 +3193,7 @@ var jsPDF = (function (global) {
31583193 'out' : out ,
31593194 'f2' : f2 ,
31603195 'getPageInfo' : getPageInfo ,
3196+ 'getPageInfoByObjId' : getPageInfoByObjId ,
31613197 'getCurrentPageInfo' : getCurrentPageInfo ,
31623198 'getPDFVersion' : getPdfVersion ,
31633199 'hasHotfix' : hasHotfix //Expose the hasHotfix check so plugins can also check them.
0 commit comments