XFA - Implement aspect property on image element
- it aims to fix issue #13634; - move some img-related functions in test/drivers.js in order to have images in xfa reftests.
This commit is contained in:
parent
ff3a5382ee
commit
71d17b0cc4
@ -2829,11 +2829,38 @@ class Image extends StringObject {
|
|||||||
if (this.transferEncoding === "base64") {
|
if (this.transferEncoding === "base64") {
|
||||||
const buffer = stringToBytes(atob(this[$content]));
|
const buffer = stringToBytes(atob(this[$content]));
|
||||||
const blob = new Blob([buffer], { type: this.contentType });
|
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({
|
return HTMLResult.success({
|
||||||
name: "img",
|
name: "img",
|
||||||
attributes: {
|
attributes: {
|
||||||
class: ["xfaImage"],
|
class: ["xfaImage"],
|
||||||
style: {},
|
style,
|
||||||
src: URL.createObjectURL(blob),
|
src: URL.createObjectURL(blob),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -66,6 +66,54 @@ function writeSVG(svgElement, ctx, resolve, reject) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function inlineImages(images) {
|
||||||
|
const imagePromises = [];
|
||||||
|
for (let i = 0, ii = images.length; i < ii; i++) {
|
||||||
|
imagePromises.push(
|
||||||
|
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();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Promise.all(imagePromises);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function resolveImages(node, silentErrors = false) {
|
||||||
|
const images = node.getElementsByTagName("img");
|
||||||
|
const data = await inlineImages(images);
|
||||||
|
|
||||||
|
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) {
|
||||||
|
if (silentErrors) {
|
||||||
|
resolveImage();
|
||||||
|
} else {
|
||||||
|
rejectImage(new Error("Error loading image " + e));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
await Promise.all(loadedPromises);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class
|
* @class
|
||||||
*/
|
*/
|
||||||
@ -164,30 +212,6 @@ var rasterizeAnnotationLayer = (function rasterizeAnnotationLayerClosure() {
|
|||||||
return loadStyles(styles);
|
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
|
// eslint-disable-next-line no-shadow
|
||||||
function rasterizeAnnotationLayer(
|
function rasterizeAnnotationLayer(
|
||||||
ctx,
|
ctx,
|
||||||
@ -233,25 +257,7 @@ var rasterizeAnnotationLayer = (function rasterizeAnnotationLayerClosure() {
|
|||||||
pdfjsLib.AnnotationLayer.render(parameters);
|
pdfjsLib.AnnotationLayer.render(parameters);
|
||||||
|
|
||||||
// Inline SVG images from text annotations.
|
// Inline SVG images from text annotations.
|
||||||
var images = div.getElementsByTagName("img");
|
await resolveImages(div);
|
||||||
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;
|
|
||||||
});
|
|
||||||
|
|
||||||
foreignObject.appendChild(div);
|
foreignObject.appendChild(div);
|
||||||
svg.appendChild(foreignObject);
|
svg.appendChild(foreignObject);
|
||||||
|
|
||||||
@ -312,6 +318,9 @@ var rasterizeXfaLayer = (function rasterizeXfaLayerClosure() {
|
|||||||
viewport: viewport.clone({ dontFlip: true }),
|
viewport: viewport.clone({ dontFlip: true }),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Some unsupported type of images (e.g. tiff)
|
||||||
|
// lead to errors.
|
||||||
|
await resolveImages(div, /* silentErrors = */ true);
|
||||||
svg.appendChild(foreignObject);
|
svg.appendChild(foreignObject);
|
||||||
|
|
||||||
writeSVG(svg, ctx, resolve, reject);
|
writeSVG(svg, ctx, resolve, reject);
|
||||||
|
1
test/pdfs/xfa_issue13634.pdf.link
Normal file
1
test/pdfs/xfa_issue13634.pdf.link
Normal file
@ -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
|
@ -1050,6 +1050,14 @@
|
|||||||
"enableXfa": true,
|
"enableXfa": true,
|
||||||
"type": "eq"
|
"type": "eq"
|
||||||
},
|
},
|
||||||
|
{ "id": "xfa_issue13634",
|
||||||
|
"file": "pdfs/xfa_issue13634.pdf",
|
||||||
|
"md5": "459a04045470811cbab6671772929d3d",
|
||||||
|
"link": true,
|
||||||
|
"rounds": 1,
|
||||||
|
"enableXfa": true,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
{ "id": "xfa_issue13556",
|
{ "id": "xfa_issue13556",
|
||||||
"file": "pdfs/xfa_issue13556.pdf",
|
"file": "pdfs/xfa_issue13556.pdf",
|
||||||
"md5": "197e93a010763c3b6f9845595ee66c70",
|
"md5": "197e93a010763c3b6f9845595ee66c70",
|
||||||
|
@ -188,6 +188,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.xfaImage {
|
.xfaImage {
|
||||||
|
object-position: left top;
|
||||||
|
object-fit: contain;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user