From ae5828c968482fcbac7a7fd0dcf62215bbd8c955 Mon Sep 17 00:00:00 2001 From: Calixte Denizet Date: Mon, 4 Dec 2023 20:49:15 +0100 Subject: [PATCH] [Editor] Avoid conflicts between new persistent refs and the ones created when saving (bug 1865341) When a pdf as a FreeText without appearance, we use a fake font in order to render it and that leads to create few new refs for the font. But then when we're saving, we create some new refs which start at the same number as the previous created ones. Consequently, when saving we're using some wrong objects (like a font) to check if we're able to render the newly added FreeText. In order to fix this bug, we just remove the persistent refs (which are only used when rendering/printing) during the saving. --- src/core/font_substitutions.js | 4 ++++ src/core/xref.js | 20 ++++++++++++++++++++ test/driver.js | 6 ++++++ test/pdfs/.gitignore | 1 + test/pdfs/bug1865341.pdf | Bin 0 -> 5618 bytes test/test_manifest.json | 21 +++++++++++++++++++++ 6 files changed, 52 insertions(+) create mode 100755 test/pdfs/bug1865341.pdf diff --git a/src/core/font_substitutions.js b/src/core/font_substitutions.js index 9ad26b707..c22976ba2 100644 --- a/src/core/font_substitutions.js +++ b/src/core/font_substitutions.js @@ -419,6 +419,10 @@ function getFontSubstitution( baseFontName, standardFontName ) { + if (baseFontName.startsWith("InvalidPDFjsFont_")) { + return null; + } + // It's possible to have a font name with spaces, commas or dashes, hence we // just replace them by a dash. baseFontName = normalizeFontName(baseFontName); diff --git a/src/core/xref.js b/src/core/xref.js index 6c32f6ee4..313f18a71 100644 --- a/src/core/xref.js +++ b/src/core/xref.js @@ -44,6 +44,7 @@ class XRef { this._pendingRefs = new RefSet(); this._newPersistentRefNum = null; this._newTemporaryRefNum = null; + this._persistentRefsCache = null; } getNewPersistentRef(obj) { @@ -63,6 +64,19 @@ class XRef { // stream. if (this._newTemporaryRefNum === null) { this._newTemporaryRefNum = this.entries.length || 1; + if (this._newPersistentRefNum) { + this._persistentRefsCache = new Map(); + for ( + let i = this._newTemporaryRefNum; + i < this._newPersistentRefNum; + i++ + ) { + // We *temporarily* clear the cache, see `resetNewTemporaryRef` below, + // to avoid any conflict with the refs created during saving. + this._persistentRefsCache.set(i, this._cacheMap.get(i)); + this._cacheMap.delete(i); + } + } } return Ref.get(this._newTemporaryRefNum++, 0); } @@ -70,6 +84,12 @@ class XRef { resetNewTemporaryRef() { // Called once saving is finished. this._newTemporaryRefNum = null; + if (this._persistentRefsCache) { + for (const [num, obj] of this._persistentRefsCache) { + this._cacheMap.set(num, obj); + } + } + this._persistentRefsCache = null; } setStartXRef(startXRef) { diff --git a/test/driver.js b/test/driver.js index 6a0fa4513..6e4ae0393 100644 --- a/test/driver.js +++ b/test/driver.js @@ -656,6 +656,12 @@ class Driver { if (!task.annotationStorage) { throw new Error("Missing `annotationStorage` entry."); } + if (task.loadAnnotations) { + for (let num = 1; num <= doc.numPages; num++) { + const page = await doc.getPage(num); + await page.getAnnotations({ intent: "display" }); + } + } doc.annotationStorage.setAll(task.annotationStorage); const data = await doc.saveDocument(); diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index d63f3d7d9..ce8b9fa1b 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -619,3 +619,4 @@ !issue17069.pdf !issue17215.pdf !bug1863910.pdf +!bug1865341.pdf diff --git a/test/pdfs/bug1865341.pdf b/test/pdfs/bug1865341.pdf new file mode 100755 index 0000000000000000000000000000000000000000..0574cbe010943930f8db5fe842a4dce584d4496f GIT binary patch literal 5618 zcmeHLe{3699lw+`6t9t5R;q%8c(~0-w%G5zyYrpTbKE-qp(ezQmw2RV6e;JsbK=&% zGv{;Th9PB$K`XJTnlwSB3QZM1HX%e>A^u>MV6aJBXt!l8RKNs?@edPHL7Eg8(DHrf zU)R=?h{X6Smhyb}-uLI{ecyAwpMh*L9iTy}f8dXAzkaRXM=2u6${+8KM)5?^G*r8| zZ0LyM2_!1Kj3*Hla03>&9Qs$(=%@K|y-Dkj2VnbNczqLL66 zrP0xJTue|=iYuvrVEow{ul`hBF| zH!zTzO!xa*I0AH`4s_ixfsJX!Ewas$D4s@wbVoq*^YgtIe!mmFv9|J&qx-^V>tD<6 zoVo8$L`ZDE`S>%!j$?^`+~BtDZuZRz$rz5RtB%UD2E-<7P6=wJiX`_n zt1iH^;y$||B|x-fEp#e`3Y~NkwpAIm>az+TBuFA*7zLgN1wlYEk%E#W&*2Odh025o ztg=6eGHIFV%web^!*rSsr;Msqvo!1k?%o9W>hAxn%i*^;ZTx`Kg z`7l(z&@eQaKR)f0z3B4OBui$<#oTIkRs7uQ#r37v@YRPNA=j6FG5lb#XZ+)Xy?_4a zfuEiG^fTL^fA7|}2b6QCo`3n|$wU259r`{xxAM}3+_Oi7)0eJ1eLnZ(%1iI&p15@7 z`h|CMnbl)oUrcDLk0tdzujD_w|B1_Qo@bS>|=b(@)Jq|(~TPBPJh^@^&UFdURO7K-MG|K;t4NcB48>8D2-4hB1*0E;E%DR5w-O~WGb0% z`h&L-|DxkmA{Z|%Ed`f^pk*&$swfI3Jm&cTNCc{H;%!3zc3cmZowKY` ztWj}s&9?HYgR-`T1|>0&FFHer7lKldCqlTHoL9|bQP&~`%Py-uT}6Dc54O$jJ+o&;3*q2%>EuY?8Kvg^_H*o90YfQw$! z4Ew)@>kgf!tte*a$8(+>Ff@=$|O(C!; z;jQZ0f@@O}!^Wg*E`R?A|{<^1kANPmQeLv_DjEBW|-(W(Wwy{Z= zbdQD?vyE_q*4zgd}hb#naC z%0zH&a(wua9fNB#r`L(Fo>?0{vz{aTuY_v?Pkuz+xV~|9@H@hbGU){a;kap9P8H2k z8B9$(;KN4gq~Sof(lXPSZqfjaNs4gF1Ujy0E+9Np zG~;Hq*qZP-U>;iz80yVnP>WMQIBgq7&ZvW1w}*oMh_z*CFd1R}B;|=n!&DOGA(pM? zKo&#{LfbFNLNFXgG{ghlgCqssM8GE*M}uwxjG4<7!2JSfCLk}?GNZv;x4C1S+B4d- zozu8w&g6>R2@psl5fHF!-LM;o6R_1n)00owlTU-wQvhW~`6+-%BSS{-G37S_1wPQbN@m3zJDEtJvyhzC25 literal 0 HcmV?d00001 diff --git a/test/test_manifest.json b/test/test_manifest.json index de05cc03e..375ef75d7 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -8381,5 +8381,26 @@ "link": true, "type": "eq", "annotations": true + }, + { + "id": "bug1865341", + "file": "pdfs/bug1865341.pdf", + "md5": "e241b6d1dc493df73e77e3eeabc71721", + "rounds": 1, + "type": "eq", + "save": true, + "print": true, + "loadAnnotations": true, + "annotationStorage": { + "pdfjs_internal_editor_0": { + "annotationType": 3, + "color": [255, 0, 0], + "fontSize": 10, + "value": "Załącznik", + "pageIndex": 0, + "rect": [ 238, 629, 287, 649], + "rotation": 0 + } + } } ]