From 7f841bd03253783020a486d4424d1b0221ecc0cc Mon Sep 17 00:00:00 2001 From: Calixte Denizet Date: Mon, 30 Sep 2024 21:20:42 +0200 Subject: [PATCH] Write the display flags in F entry when saving an annotation (issue 18072) --- src/core/annotation.js | 72 +++++++++++++++++++++++++++++++++++---- src/core/document.js | 3 -- test/pdfs/.gitignore | 1 + test/pdfs/issue18072.pdf | Bin 0 -> 7199 bytes test/test_manifest.json | 54 +++++++++++++++++++++++++++++ 5 files changed, 120 insertions(+), 10 deletions(-) create mode 100644 test/pdfs/issue18072.pdf diff --git a/src/core/annotation.js b/src/core/annotation.js index 9f27194994349..44db3ab8d4bb1 100644 --- a/src/core/annotation.js +++ b/src/core/annotation.js @@ -27,6 +27,7 @@ import { getModificationDate, IDENTITY_MATRIX, info, + isArrayEqual, LINE_DESCENT_FACTOR, LINE_FACTOR, OPS, @@ -723,6 +724,38 @@ class Annotation { return !!(flags & flag); } + _buildFlags(noView, noPrint) { + let { flags } = this; + if (noView === undefined) { + if (noPrint === undefined) { + return undefined; + } + if (noPrint) { + return flags & ~AnnotationFlag.PRINT; + } + return (flags & ~AnnotationFlag.HIDDEN) | AnnotationFlag.PRINT; + } + + if (noView) { + flags |= AnnotationFlag.PRINT; + if (noPrint) { + // display === 1. + return (flags & ~AnnotationFlag.NOVIEW) | AnnotationFlag.HIDDEN; + } + // display === 3. + return (flags & ~AnnotationFlag.HIDDEN) | AnnotationFlag.NOVIEW; + } + + flags &= ~(AnnotationFlag.HIDDEN | AnnotationFlag.NOVIEW); + if (noPrint) { + // display === 2. + return flags & ~AnnotationFlag.PRINT; + } + + // display === 0. + return flags | AnnotationFlag.PRINT; + } + /** * @private */ @@ -2073,10 +2106,15 @@ class WidgetAnnotation extends Annotation { async save(evaluator, task, annotationStorage) { const storageEntry = annotationStorage?.get(this.data.id); + const flags = this._buildFlags(storageEntry?.noView, storageEntry?.noPrint); let value = storageEntry?.value, rotation = storageEntry?.rotation; if (value === this.data.fieldValue || value === undefined) { - if (!this._hasValueFromXFA && rotation === undefined) { + if ( + !this._hasValueFromXFA && + rotation === undefined && + flags === undefined + ) { return null; } value ||= this.data.fieldValue; @@ -2089,7 +2127,8 @@ class WidgetAnnotation extends Annotation { Array.isArray(value) && Array.isArray(this.data.fieldValue) && value.length === this.data.fieldValue.length && - value.every((x, i) => x === this.data.fieldValue[i]) + isArrayEqual(value, this.data.fieldValue) && + flags === undefined ) { return null; } @@ -2106,7 +2145,7 @@ class WidgetAnnotation extends Annotation { RenderingIntentFlag.SAVE, annotationStorage ); - if (appearance === null) { + if (appearance === null && flags === undefined) { // Appearance didn't change. return null; } @@ -2134,6 +2173,15 @@ class WidgetAnnotation extends Annotation { dict.set(key, originalDict.getRaw(key)); } } + if (flags !== undefined) { + dict.set("F", flags); + if (appearance === null && !needAppearances) { + const ap = originalDict.getRaw("AP"); + if (ap) { + dict.set("AP", ap); + } + } + } const xfa = { path: this.data.fieldName, @@ -3019,10 +3067,11 @@ class ButtonWidgetAnnotation extends WidgetAnnotation { return null; } const storageEntry = annotationStorage.get(this.data.id); + const flags = this._buildFlags(storageEntry?.noView, storageEntry?.noPrint); let rotation = storageEntry?.rotation, value = storageEntry?.value; - if (rotation === undefined) { + if (rotation === undefined && flags === undefined) { if (value === undefined) { return null; } @@ -3033,10 +3082,11 @@ class ButtonWidgetAnnotation extends WidgetAnnotation { } } - const dict = evaluator.xref.fetchIfRef(this.ref); + let dict = evaluator.xref.fetchIfRef(this.ref); if (!(dict instanceof Dict)) { return null; } + dict = dict.clone(); if (rotation === undefined) { rotation = this.rotation; @@ -3054,6 +3104,9 @@ class ButtonWidgetAnnotation extends WidgetAnnotation { dict.set("V", name); dict.set("AS", name); dict.set("M", `D:${getModificationDate()}`); + if (flags !== undefined) { + dict.set("F", flags); + } const maybeMK = this._getMKDict(rotation); if (maybeMK) { @@ -3071,10 +3124,11 @@ class ButtonWidgetAnnotation extends WidgetAnnotation { return null; } const storageEntry = annotationStorage.get(this.data.id); + const flags = this._buildFlags(storageEntry?.noView, storageEntry?.noPrint); let rotation = storageEntry?.rotation, value = storageEntry?.value; - if (rotation === undefined) { + if (rotation === undefined && flags === undefined) { if (value === undefined) { return null; } @@ -3085,10 +3139,11 @@ class ButtonWidgetAnnotation extends WidgetAnnotation { } } - const dict = evaluator.xref.fetchIfRef(this.ref); + let dict = evaluator.xref.fetchIfRef(this.ref); if (!(dict instanceof Dict)) { return null; } + dict = dict.clone(); if (value === undefined) { value = this.data.fieldValue === this.data.buttonValue; @@ -3121,6 +3176,9 @@ class ButtonWidgetAnnotation extends WidgetAnnotation { dict.set("AS", name); dict.set("M", `D:${getModificationDate()}`); + if (flags !== undefined) { + dict.set("F", flags); + } const maybeMK = this._getMKDict(rotation); if (maybeMK) { diff --git a/src/core/document.js b/src/core/document.js index 982033dcbc4b9..59f36f97f578f 100644 --- a/src/core/document.js +++ b/src/core/document.js @@ -378,9 +378,6 @@ class Page { return this._parsedAnnotations.then(function (annotations) { const newRefsPromises = []; for (const annotation of annotations) { - if (!annotation.mustBePrinted(annotationStorage)) { - continue; - } newRefsPromises.push( annotation .save(partialEvaluator, task, annotationStorage) diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index 187a90b761482..cda431a14c61a 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -671,3 +671,4 @@ !bug1919513.pdf !issue16038.pdf !highlight_popup.pdf +!issue18072.pdf diff --git a/test/pdfs/issue18072.pdf b/test/pdfs/issue18072.pdf new file mode 100644 index 0000000000000000000000000000000000000000..0012ff3c5fba4401769cf2454059c7e6dbedb78a GIT binary patch literal 7199 zcmeHMc~}$I76$~XF<693v1pwJL9HaSWU>koNQk0D5Gb;UGRX`OC7GBEf;@diu(&It zRz+>mx=^fjqs3aqy5LiBse<}i`>LR?R>a~`*V_8-B!R?&eg4ruUf*ZFFZu4=Ip^GS ze&=^??h+KIQu9%P*ej^{%IO9#4l0Hah}KT>3Jry0^hSy>>kB9nLg5%lg34rYEQCto zC4PtU7_%zj3jFV>hj}-i5z37C>>2wafI1m0V68u zoLqy^0^x9+nIiQ%hBiYercl6YeGWsJVRa6{P&O4fT9p=xh=d|hB!Wh$F$7nug)$`? zsa8p&Br+u;Q%h8eP&F2XMMa7w5-BRfqoffsAS{uoq(UGpQsKBF9ga4VRDK!=9F?#S znKXp54#vYVlrf9RhD0LPo2hJ|7#vU23=p)wPXN$BLLrq3BxgM=7f_4*jEG-OSX7bHcrWfKB6ciP!c1G7rh&dqb3M&Xjh3)Z3agarc z5Ke$_1WtmavS+-_$jHdb$cQIg+|GZ)tt{+2C&gdtS21s=675#(+HLc~mW?Zd{?=Cb z#R4w3-#6anO~Kwm6fx}ye|RDUy4!c9MBvuIjcA zHElLP7)!i(SVJ)cNiYN?v_8h>GC6>S7RZKp9FYauC~kdcgS zW-Jh9Q&!SOhBC6xHhra;Hbv4P^N3J@$s`ailL@3!NQj^U1QA0L(2e3)I&g{96RaR2 zKp^%jMltX!k%8ZI7*H1&ZTBgjve3C^9RfUgi@V+iZKlb{0V!Jy0mE8&D(EyJ>vHEic? ztacKmV;mfq!a<-B97F(W0DMtg28tarQydFtET?lWF#t*XeDPNf1O5L9!)Y4$D`$f( ze)|N`#cZb5n=K4GdD&}1h{?czk=Vv(K<5O;;GlE%_n(wa9DN9Rt#1GE8Q)DPSdANe z{om8`iw0AEo{Pd-WBV1KnWtWL>HDRh=5m+M?QSTuv}sN)UVU^{WZ94&ANTlhPC{7; zuXp@wW$~QR^A>J8Gw1H@!fiKy@(QRL!3}uBtcYl?njpGi*mq#(iTQg|?z#H(ZV65~ z5|uD)!^NAC524{9cY<8P?ldq+m|A*^^Be7?t)5dFe2NLo_ zvB}bY*|W!&Hm`4||FqWM{O{r`dyM1X?|*>&XP%q)wbuH&U0c&H6!%h>e|6aO z`rC0wE+3co51R09-J=g8*XU1wc$BHQ9oIatZo#-^Q&R)By*oPi>FwqM-rVXji&div zem!*V?Xu)R>t`9jDea>_|`b2$F_mMHN=iGC?Nf$A*(L#Xl_n z;p*X*S8jZHZT8iR-?+N_yHw$WB0C4>RCUh{3=_2nCYG>t#h*vl>B}_qMTA@Obl&2d z)F(?n9bL#Ptl6EseVuFSwXb`H9rZKxT)s7NK+3L(!&76%x9uz*uBv@CdTe#WmaA_^ zH(b4oMQ26J2Yfm({Z!e-wB)SUZ}q=N+(q04^TJ!0^W?;jb)ZQVcf zgSy%Yz7sfYD`)uKxU;`C^_(cRb?64|wsqC{;gz#QVTs3+)@>2h7UL5V`^3)^|GaSf zx&~f8vhe!tJ|P?3w^bh|YiHGDgvv2}%=?nBlc$8YoN_x}Au1?cumAdkH+MD`rf%7n z&};kBgP#@7nBMqpTt?;A%DwB&nBGHNny|qXoqWS2V7f z()-NaqGP)sZ;xGoPCvY_kIyh-;<}{7*Pk#2m8R8)0&7~L-=5UGeRh^O?hr2D9KNd& zlHPwZck#e|UlfHVE8z=q9>e+_SmGyP+<)lvOMG%FKZ84d)vrtD3zN=|3`h#QcdwpX ztW6)o}J;Z>wKZ3!qP zNdG~|qGj5J+J)uWjg=9Tl&7zA>%Hnvs*GcbmXx(rcy^P#h4}k(eUSx+m#kHYoASl` zZ^74}w54tRjf1$5Rlfyxt^ubhyM0;~3h|BwN3tfyM)>vxo@1g29iDF@bdxCt(o$J^ zV;HaP%l$k^PloZvi8P4Dq@=R-BMZz_Lcy3sUBP6XjN}bha6pK>0cZLBSeMAeM+oBvTRsVF)IK z5iyLSd{idKP&wEU*grf42ed-XWTre`rM8a;p2B$93}ceRa9&=XAWtZu%~>$mB*|a| zgE5Q`B>0wTMuy1e8!dr0BkgunltpLOn;1Q9gjl zMi0CI!wI`oBFJo7m*)WT8AWz)pe2|HR%RS+o}8IO=h*_b=EDY4DDYUWp-Fw_G!n3TPy~}BNGSX}Ne9$c8%nTY1Dne(Y#?$Rakk+k`8yl!{v&j&51Ofqp+g@fu%gyxd<=;h9Zc_7LBu97AQ;uFo zurz}~9ztQqD<^qt(&Z{zm&=kPTBXR%)su3Wh`@w|h~(osOv@(`T*oJHosdsRNkW1n zTA3K5tZryD&bpoKMjOH2)u^M|?P^i2Oe+=2__#1r%tvvYtjZWo6o_*igSvg1tNDfr~ju}I^CQ!zspiK|^Wo^>s=6a6-{yfSdpWB{E6JA)$Z(G9p9dY(7$*t`*p(u5p4aoQ3c0#0FeU|{KvZpU}JpY;s( z{MJ+5;_2B^?)}cAs5cfJi+U72H;CgJ^@yVmE>IV!OFTU{l|Qb1G-RdcO8@c$UM`bH z4$+LM(-*DnA71F{^5mmnUFR5_uD1RsuAMsHG)X$&FQN8x%|Ezba&Ze*FX{(CJF+^w zXqCsvTb?s_?+Y(#>K=E0)!;dGUv&@kf4a_ez`bE2xM*VGar5*X+!-Fn4HJrj`#|d* G(|-U^rrebP literal 0 HcmV?d00001 diff --git a/test/test_manifest.json b/test/test_manifest.json index b078193a42386..fa14966541542 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -10524,5 +10524,59 @@ "md5": "47262993e04689c327b7ce85396bce99", "rounds": 1, "type": "eq" + }, + { + "id": "issue18072-save-print", + "file": "pdfs/issue18072.pdf", + "md5": "231fe6f035da1f2ddf84f2a78ada20c5", + "rounds": 1, + "type": "eq", + "save": true, + "print": true, + "annotationStorage": { + "28R": { + "noView": true, + "noPrint": true + }, + "29R": { + "noView": true, + "noPrint": false + }, + "30R": { + "noView": false, + "noPrint": true + }, + "31R": { + "noView": false, + "noPrint": false + } + } + }, + { + "id": "issue18072-save-annotations", + "file": "pdfs/issue18072.pdf", + "md5": "231fe6f035da1f2ddf84f2a78ada20c5", + "rounds": 1, + "type": "eq", + "save": true, + "annotations": true, + "annotationStorage": { + "28R": { + "noView": true, + "noPrint": true + }, + "29R": { + "noView": true, + "noPrint": false + }, + "30R": { + "noView": false, + "noPrint": true + }, + "31R": { + "noView": false, + "noPrint": false + } + } } ]