diff --git a/src/core/xfa/template.js b/src/core/xfa/template.js index e9ac5ac7135b56..899674ae480a48 100644 --- a/src/core/xfa/template.js +++ b/src/core/xfa/template.js @@ -2829,11 +2829,38 @@ class Image extends StringObject { if (this.transferEncoding === "base64") { const buffer = stringToBytes(atob(this[$content])); const blob = new Blob([buffer], { type: this.contentType }); + let style; + switch (this.aspect) { + case "fit": + case "actual": + // TODO: check what to do with actual. + // Normally we should return {auto, auto} for it but + // it implies some wrong rendering (see xfa_bug1716816.pdf). + break; + case "height": + style = { + width: "auto", + height: "100%", + }; + break; + case "none": + style = { + width: "100%", + height: "100%", + }; + break; + case "width": + style = { + width: "100%", + height: "auto", + }; + break; + } return HTMLResult.success({ name: "img", attributes: { class: ["xfaImage"], - style: {}, + style, src: URL.createObjectURL(blob), }, }); diff --git a/test/driver.js b/test/driver.js index f4c7bde42807d4..1d9a59a763e464 100644 --- a/test/driver.js +++ b/test/driver.js @@ -66,6 +66,51 @@ function writeSVG(svgElement, ctx, resolve, reject) { }; } +function inlineImages(images) { + const imagePromises = []; + for (let i = 0, ii = images.length; i < ii; i++) { + const imagePromise = new Promise(function (resolve, reject) { + const xhr = new XMLHttpRequest(); + xhr.responseType = "blob"; + xhr.onload = function () { + const reader = new FileReader(); + reader.onloadend = function () { + resolve(reader.result); + }; + reader.readAsDataURL(xhr.response); + }; + xhr.onerror = function (e) { + reject(new Error("Error fetching inline image " + e)); + }; + xhr.open("GET", images[i].src); + xhr.send(); + }); + imagePromises.push(imagePromise); + } + return imagePromises; +} + +async function resolveImages(node) { + const images = node.getElementsByTagName("img"); + const imagePromises = inlineImages(images); + + await Promise.all(imagePromises).then(function (data) { + const loadedPromises = []; + for (let i = 0, ii = data.length; i < ii; i++) { + images[i].src = data[i]; + loadedPromises.push( + new Promise(function (resolveImage, rejectImage) { + images[i].onload = resolveImage; + images[i].onerror = function (e) { + rejectImage(new Error("Error loading image " + e)); + }; + }) + ); + } + return loadedPromises; + }); +} + /** * @class */ @@ -164,30 +209,6 @@ var rasterizeAnnotationLayer = (function rasterizeAnnotationLayerClosure() { return loadStyles(styles); } - function inlineAnnotationImages(images) { - var imagePromises = []; - for (var i = 0, ii = images.length; i < ii; i++) { - var imagePromise = new Promise(function (resolve, reject) { - var xhr = new XMLHttpRequest(); - xhr.responseType = "blob"; - xhr.onload = function () { - var reader = new FileReader(); - reader.onloadend = function () { - resolve(reader.result); - }; - reader.readAsDataURL(xhr.response); - }; - xhr.onerror = function (e) { - reject(new Error("Error fetching inline annotation image " + e)); - }; - xhr.open("GET", images[i].src); - xhr.send(); - }); - imagePromises.push(imagePromise); - } - return imagePromises; - } - // eslint-disable-next-line no-shadow function rasterizeAnnotationLayer( ctx, @@ -233,25 +254,7 @@ var rasterizeAnnotationLayer = (function rasterizeAnnotationLayerClosure() { pdfjsLib.AnnotationLayer.render(parameters); // Inline SVG images from text annotations. - var images = div.getElementsByTagName("img"); - var imagePromises = inlineAnnotationImages(images); - - await Promise.all(imagePromises).then(function (data) { - var loadedPromises = []; - for (var i = 0, ii = data.length; i < ii; i++) { - images[i].src = data[i]; - loadedPromises.push( - new Promise(function (resolveImage, rejectImage) { - images[i].onload = resolveImage; - images[i].onerror = function (e) { - rejectImage(new Error("Error loading image " + e)); - }; - }) - ); - } - return loadedPromises; - }); - + await resolveImages(div); foreignObject.appendChild(div); svg.appendChild(foreignObject); @@ -312,6 +315,7 @@ var rasterizeXfaLayer = (function rasterizeXfaLayerClosure() { viewport: viewport.clone({ dontFlip: true }), }); + await resolveImages(div); svg.appendChild(foreignObject); writeSVG(svg, ctx, resolve, reject); diff --git a/test/pdfs/xfa_issue13634.pdf.link b/test/pdfs/xfa_issue13634.pdf.link new file mode 100644 index 00000000000000..443d33c4061659 --- /dev/null +++ b/test/pdfs/xfa_issue13634.pdf.link @@ -0,0 +1 @@ +https://web.archive.org/web/20210510183636/https://guichet.public.lu/dam-assets/catalogue-formulaires/tva/tva-option-aic-pers-morales/tva-option-aic-pers-morale-DE.pdf diff --git a/test/test_manifest.json b/test/test_manifest.json index 97e6d2ff36d953..afb23915603089 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -1026,6 +1026,14 @@ "enableXfa": true, "type": "eq" }, + { "id": "xfa_issue13634", + "file": "pdfs/xfa_issue13634.pdf", + "md5": "459a04045470811cbab6671772929d3d", + "link": true, + "rounds": 1, + "enableXfa": true, + "type": "eq" + }, { "id": "xfa_issue13556", "file": "pdfs/xfa_issue13556.pdf", "md5": "197e93a010763c3b6f9845595ee66c70", diff --git a/web/xfa_layer_builder.css b/web/xfa_layer_builder.css index fd3703d14f91c7..c364289d1fd7d2 100644 --- a/web/xfa_layer_builder.css +++ b/web/xfa_layer_builder.css @@ -188,6 +188,8 @@ } .xfaImage { + object-position: left top; + object-fit: contain; width: 100%; height: 100%; }