@@ -431,6 +431,7 @@ var calculateFontSpace = function(text, formObject, fontSize) {
431431var acroformPluginTemplate = {
432432 fields : [ ] ,
433433 xForms : [ ] ,
434+ xfaStreams : [ ] ,
434435 /**
435436 * acroFormDictionaryRoot contains information about the AcroForm
436437 * Dictionary 0: The Event-Token, the AcroFormDictionaryCallback has
@@ -444,7 +445,8 @@ var acroformPluginTemplate = {
444445 */
445446 printedOut : false ,
446447 internal : null ,
447- isInitialized : false
448+ isInitialized : false ,
449+ needRendering : false
448450} ;
449451
450452var annotReferenceCallback = function ( scope ) {
@@ -464,6 +466,12 @@ var annotReferenceCallback = function(scope) {
464466 }
465467 }
466468 }
469+ var xfaStreams = scope . internal . acroformPlugin . xfaStreams || [ ] ;
470+ for ( var j = 0 ; j < xfaStreams . length ; j ++ ) {
471+ if ( xfaStreams [ j ] ) {
472+ xfaStreams [ j ] . objId = undefined ;
473+ }
474+ }
467475} ;
468476
469477var putForm = function ( formObject ) {
@@ -513,6 +521,9 @@ var putCatalogCallback = function(scope) {
513521 0 +
514522 " R"
515523 ) ;
524+ if ( scope . internal . acroformPlugin . needRendering === true ) {
525+ scope . internal . write ( "/NeedRendering true" ) ;
526+ }
516527 } else {
517528 throw new Error ( "putCatalogCallback: Root missing." ) ;
518529 }
@@ -651,6 +662,7 @@ var createFieldCallback = function(fieldArray, scope) {
651662 }
652663 if ( standardFields ) {
653664 createXFormObjectCallback ( scope . internal . acroformPlugin . xForms , scope ) ;
665+ createXFAPacketCallback ( scope ) ;
654666 }
655667} ;
656668
@@ -673,8 +685,87 @@ var createXFormObjectCallback = function(fieldArray, scope) {
673685 }
674686} ;
675687
688+ var ARRAY_APPLY_BATCH = 8192 ;
689+
690+ var isArrayBufferLike = function ( value ) {
691+ if ( typeof ArrayBuffer === "undefined" ) {
692+ return false ;
693+ }
694+ if ( value instanceof ArrayBuffer ) {
695+ return true ;
696+ }
697+ if ( typeof ArrayBuffer . isView === "function" && ArrayBuffer . isView ( value ) ) {
698+ return true ;
699+ }
700+ return (
701+ value && typeof value === "object" && value . buffer instanceof ArrayBuffer
702+ ) ;
703+ } ;
704+
705+ var getUint8View = function ( value ) {
706+ if ( typeof Uint8Array === "undefined" ) {
707+ return null ;
708+ }
709+ if ( value instanceof ArrayBuffer ) {
710+ return new Uint8Array ( value ) ;
711+ }
712+ if ( typeof ArrayBuffer . isView === "function" && ArrayBuffer . isView ( value ) ) {
713+ return new Uint8Array ( value . buffer , value . byteOffset , value . byteLength ) ;
714+ }
715+ if (
716+ value &&
717+ typeof value === "object" &&
718+ value . buffer instanceof ArrayBuffer
719+ ) {
720+ var byteOffset = value . byteOffset || 0 ;
721+ var byteLength =
722+ typeof value . byteLength === "number"
723+ ? value . byteLength
724+ : value . buffer . byteLength - byteOffset ;
725+ return new Uint8Array ( value . buffer , byteOffset , byteLength ) ;
726+ }
727+ return null ;
728+ } ;
729+
730+ var arrayBufferToBinaryString = function ( buffer ) {
731+ var view = getUint8View ( buffer ) ;
732+ if ( ! view ) {
733+ throw new Error ( "Invalid XFA packet stream provided." ) ;
734+ }
735+ var out = "" ;
736+ for ( var i = 0 ; i < view . length ; i += ARRAY_APPLY_BATCH ) {
737+ out += String . fromCharCode . apply (
738+ null ,
739+ view . subarray ( i , i + ARRAY_APPLY_BATCH )
740+ ) ;
741+ }
742+ return out ;
743+ } ;
744+
745+ var normalizeXFAPacketStream = function ( stream ) {
746+ if ( typeof stream === "string" || stream instanceof String ) {
747+ return stream . toString ( ) ;
748+ }
749+ if ( isArrayBufferLike ( stream ) ) {
750+ return arrayBufferToBinaryString ( stream ) ;
751+ }
752+ throw new Error ( "Invalid XFA packet stream provided." ) ;
753+ } ;
754+
755+ var normalizeXFAPacketName = function ( name ) {
756+ if ( typeof name === "string" || name instanceof String ) {
757+ return name . toString ( ) ;
758+ }
759+ if ( name !== null && typeof name !== "undefined" ) {
760+ return String ( name ) ;
761+ }
762+ throw new Error ( "XFA packet name must be defined." ) ;
763+ } ;
764+
676765var initializeAcroForm = function ( scope , formObject ) {
677- formObject . scope = scope ;
766+ if ( formObject ) {
767+ formObject . scope = scope ;
768+ }
678769 if (
679770 scope . internal !== undefined &&
680771 ( scope . internal . acroformPlugin === undefined ||
@@ -941,6 +1032,25 @@ var AcroFormXObject = function() {
9411032
9421033inherit ( AcroFormXObject , AcroFormPDFObject ) ;
9431034
1035+ var AcroFormXFAPacket = function ( stream ) {
1036+ AcroFormPDFObject . call ( this ) ;
1037+
1038+ var _stream = typeof stream === "string" ? stream : "" ;
1039+
1040+ Object . defineProperty ( this , "stream" , {
1041+ enumerable : false ,
1042+ configurable : true ,
1043+ get : function ( ) {
1044+ return _stream ;
1045+ } ,
1046+ set : function ( value ) {
1047+ _stream = typeof value === "string" ? value : "" ;
1048+ }
1049+ } ) ;
1050+ } ;
1051+
1052+ inherit ( AcroFormXFAPacket , AcroFormPDFObject ) ;
1053+
9441054var AcroFormDictionary = function ( ) {
9451055 AcroFormPDFObject . call ( this ) ;
9461056
@@ -984,10 +1094,102 @@ var AcroFormDictionary = function() {
9841094 _DA = value ;
9851095 }
9861096 } ) ;
1097+
1098+ var _XFA ;
1099+ Object . defineProperty ( this , "XFA" , {
1100+ enumerable : false ,
1101+ configurable : false ,
1102+ get : function ( ) {
1103+ return _XFA ;
1104+ } ,
1105+ set : function ( value ) {
1106+ if ( value === null || typeof value === "undefined" ) {
1107+ _XFA = undefined ;
1108+ } else {
1109+ _XFA = value ;
1110+ }
1111+ }
1112+ } ) ;
9871113} ;
9881114
9891115inherit ( AcroFormDictionary , AcroFormPDFObject ) ;
9901116
1117+ var createXFAPacket = function ( scope , stream ) {
1118+ var plugin = scope . internal . acroformPlugin ;
1119+ if ( ! plugin . xfaStreams ) {
1120+ plugin . xfaStreams = [ ] ;
1121+ }
1122+ var packet = new AcroFormXFAPacket ( normalizeXFAPacketStream ( stream ) ) ;
1123+ packet . scope = scope ;
1124+ plugin . xfaStreams . push ( packet ) ;
1125+ return packet ;
1126+ } ;
1127+
1128+ var setXFAPayload = function ( scope , payload ) {
1129+ if ( payload === null || typeof payload === "undefined" ) {
1130+ throw new Error ( "Invalid XFA payload provided." ) ;
1131+ }
1132+
1133+ var plugin = scope . internal . acroformPlugin ;
1134+ if ( ! plugin . xfaStreams ) {
1135+ plugin . xfaStreams = [ ] ;
1136+ } else {
1137+ plugin . xfaStreams . length = 0 ;
1138+ }
1139+
1140+ var dictionary = plugin . acroFormDictionaryRoot ;
1141+ if ( Array . isArray ( payload ) ) {
1142+ if ( payload . length === 0 ) {
1143+ throw new Error ( "XFA payload array must contain at least one packet." ) ;
1144+ }
1145+ var xfaArray = [ ] ;
1146+ if ( Array . isArray ( payload [ 0 ] ) ) {
1147+ for ( var pairIndex = 0 ; pairIndex < payload . length ; pairIndex ++ ) {
1148+ var pair = payload [ pairIndex ] ;
1149+ if ( ! Array . isArray ( pair ) || pair . length !== 2 ) {
1150+ throw new Error ( "XFA payload pairs must be [name, stream] tuples." ) ;
1151+ }
1152+ var tupleName = normalizeXFAPacketName ( pair [ 0 ] ) ;
1153+ var tupleStream = pair [ 1 ] ;
1154+ xfaArray . push ( tupleName ) ;
1155+ xfaArray . push ( createXFAPacket ( scope , tupleStream ) ) ;
1156+ }
1157+ } else {
1158+ if ( payload . length % 2 !== 0 ) {
1159+ throw new Error (
1160+ "XFA payload array must contain an even number of entries."
1161+ ) ;
1162+ }
1163+ for ( var i = 0 ; i < payload . length ; i += 2 ) {
1164+ var name = normalizeXFAPacketName ( payload [ i ] ) ;
1165+ var data = payload [ i + 1 ] ;
1166+ xfaArray . push ( name ) ;
1167+ xfaArray . push ( createXFAPacket ( scope , data ) ) ;
1168+ }
1169+ }
1170+ dictionary . XFA = xfaArray ;
1171+ } else {
1172+ dictionary . XFA = createXFAPacket ( scope , payload ) ;
1173+ }
1174+ } ;
1175+
1176+ var createXFAPacketCallback = function ( scope ) {
1177+ var packets = scope . internal . acroformPlugin . xfaStreams ;
1178+ if ( ! Array . isArray ( packets ) || packets . length === 0 ) {
1179+ return ;
1180+ }
1181+ for ( var i = 0 ; i < packets . length ; i ++ ) {
1182+ var packet = packets [ i ] ;
1183+ if ( ! packet ) {
1184+ continue ;
1185+ }
1186+ packet . scope = scope ;
1187+ scope . internal . newObjectDeferredBegin ( packet . objId , true ) ;
1188+ packet . putStream ( ) ;
1189+ }
1190+ packets . length = 0 ;
1191+ } ;
1192+
9911193/**
9921194 * The Field Object contains the Variables, that every Field needs
9931195 *
@@ -3107,6 +3309,15 @@ AcroFormAppearance.internal.getHeight = function(formObject) {
31073309 * @param {Object } fieldObject
31083310 * @returns {jsPDF }
31093311 */
3312+ var addXFA = ( jsPDFAPI . addXFA = function ( payload , needsRendering ) {
3313+ initializeAcroForm ( this ) ;
3314+ setXFAPayload ( this , payload ) ;
3315+ if ( typeof needsRendering !== "undefined" ) {
3316+ this . internal . acroformPlugin . needRendering = Boolean ( needsRendering ) ;
3317+ }
3318+ return this ;
3319+ } ) ;
3320+
31103321var addField = ( jsPDFAPI . addField = function ( fieldObject ) {
31113322 initializeAcroForm ( this , fieldObject ) ;
31123323
0 commit comments