@@ -34,6 +34,7 @@ import { ColorSpace } from "./colorspace.js";
34
34
import { getInheritableProperty } from "./core_utils.js" ;
35
35
import { OperatorList } from "./operator_list.js" ;
36
36
import { StringStream } from "./stream.js" ;
37
+ import { writeDict } from "./writer.js" ;
37
38
38
39
class AnnotationFactory {
39
40
/**
@@ -68,6 +69,7 @@ class AnnotationFactory {
68
69
if ( ! isDict ( dict ) ) {
69
70
return undefined ;
70
71
}
72
+
71
73
const id = isRef ( ref ) ? ref . toString ( ) : `annot_${ idFactory . createObjId ( ) } ` ;
72
74
73
75
// Determine the annotation's subtype.
@@ -77,6 +79,7 @@ class AnnotationFactory {
77
79
// Return the right annotation object based on the subtype and field type.
78
80
const parameters = {
79
81
xref,
82
+ ref,
80
83
dict,
81
84
subtype,
82
85
id,
@@ -792,6 +795,8 @@ class WidgetAnnotation extends Annotation {
792
795
793
796
const dict = params . dict ;
794
797
const data = this . data ;
798
+ this . dict = dict ;
799
+ this . ref = params . ref ;
795
800
796
801
data . annotationType = AnnotationType . WIDGET ;
797
802
data . fieldName = this . _constructFieldName ( dict ) ;
@@ -954,6 +959,70 @@ class WidgetAnnotation extends Annotation {
954
959
) ;
955
960
}
956
961
962
+ async save ( evaluator , task , annotationStorage ) {
963
+ if ( this . data . fieldValue === annotationStorage [ this . data . id ] ) {
964
+ return null ;
965
+ }
966
+
967
+ let appearance = await this . getAppearance (
968
+ evaluator ,
969
+ task ,
970
+ annotationStorage
971
+ ) ;
972
+ if ( appearance !== null ) {
973
+ const bbox = [
974
+ 0 ,
975
+ 0 ,
976
+ this . data . rect [ 2 ] - this . data . rect [ 0 ] ,
977
+ this . data . rect [ 3 ] - this . data . rect [ 1 ] ,
978
+ ] ;
979
+ const newRef = evaluator . xref . getNewRef ( ) ;
980
+ const AP = new Dict ( null ) ;
981
+ AP . set ( "N" , newRef ) ;
982
+
983
+ let annotationString = annotationStorage [ this . data . id ] ;
984
+ const encrypt = evaluator . xref . encrypt ;
985
+ if ( encrypt ) {
986
+ const transf = encrypt . createCipherTransform (
987
+ this . ref . num ,
988
+ this . ref . gen
989
+ ) ;
990
+ annotationString = transf . encryptString ( annotationString ) ;
991
+ const da = this . dict . get ( "DA" ) || null ;
992
+ if ( da !== null ) {
993
+ this . dict . set ( "DA" , transf . encryptString ( da ) ) ;
994
+ }
995
+ appearance = encrypt
996
+ . createCipherTransform ( newRef . num , newRef . gen )
997
+ . encryptString ( appearance ) ;
998
+ }
999
+
1000
+ this . dict . set ( "V" , annotationString ) ;
1001
+ this . dict . set ( "AP" , AP ) ;
1002
+
1003
+ const appearanceDict = new Dict ( null ) ;
1004
+ appearanceDict . set ( "Length" , appearance . length ) ;
1005
+ appearanceDict . set ( "Subtype" , { name : "Form" } ) ;
1006
+ appearanceDict . set ( "Resources" , this . fieldResources ) ;
1007
+ appearanceDict . set ( "BBox" , bbox ) ;
1008
+
1009
+ let bufferOriginal = `${ this . ref . num } 0 obj\n` ;
1010
+ bufferOriginal = writeDict ( this . dict , bufferOriginal ) ;
1011
+ bufferOriginal += "\nendobj\n" ;
1012
+
1013
+ let bufferNew = `${ newRef . num } ${ newRef . gen } obj\n` ;
1014
+ bufferNew = writeDict ( appearanceDict , bufferNew ) ;
1015
+ bufferNew += ` stream\n${ appearance } ` ;
1016
+ bufferNew += "\nendstream\nendobj\n" ;
1017
+
1018
+ return [
1019
+ { ref : this . ref . num , data : bufferOriginal } ,
1020
+ { ref : newRef . num , data : bufferNew } ,
1021
+ ] ;
1022
+ }
1023
+ return null ;
1024
+ }
1025
+
957
1026
async getAppearance ( evaluator , task , annotationStorage ) {
958
1027
// If it's a password textfield then no rendering to avoid to leak it.
959
1028
// see 12.7.4.3, table 228
@@ -1288,6 +1357,24 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
1288
1357
) ;
1289
1358
}
1290
1359
1360
+ async save ( evaluator , task , annotationStorage ) {
1361
+ const defaultValue = this . data . fieldValue && this . data . fieldValue !== "Off" ;
1362
+ const isChecked = annotationStorage [ this . data . id ] ;
1363
+ if ( defaultValue === isChecked ) {
1364
+ return null ;
1365
+ }
1366
+
1367
+ const value = isChecked ? this . data . exportValue : "Off" ;
1368
+ this . dict . set ( "V" , { name : value } ) ;
1369
+ this . dict . set ( "AS" , { name : value } ) ;
1370
+
1371
+ let buffer = `${ this . ref . num } 0 obj\n` ;
1372
+ buffer = writeDict ( this . dict , buffer ) ;
1373
+ buffer += "\nendobj\n" ;
1374
+
1375
+ return [ { ref : this . ref . num , data : buffer } ] ;
1376
+ }
1377
+
1291
1378
_processCheckBox ( params ) {
1292
1379
if ( isName ( this . data . fieldValue ) ) {
1293
1380
this . data . fieldValue = this . data . fieldValue . name ;
0 commit comments