Obtain the export values for choice widgets from the normal appearance
The down appearance (`D`) is optional and not available in the document from #12233, so the checkboxes are never saved/printed as checked because the checked appearance is based on the export value that is missing because the `D` entry is not available. Instead, we should use the normal appearance (`N`) since that one is required and therefore always available. Finally, the /Off appearance is optional according to section 12.7.4.2.3 of the specification, so that needs to be taken into account to match the specification and to fix reference test failures for the `annotation-button-widget-print` test. That is a file that doesn't specify an /Off appearance in the normal appearance dictionary.
This commit is contained in:
parent
1b82ad8fff
commit
a8efc0296b
@ -1531,25 +1531,23 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
|
||||
return;
|
||||
}
|
||||
|
||||
const exportValueOptionsDict = customAppearance.get("D");
|
||||
if (!isDict(exportValueOptionsDict)) {
|
||||
const normalAppearance = customAppearance.get("N");
|
||||
if (!isDict(normalAppearance)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const exportValues = exportValueOptionsDict.getKeys();
|
||||
const hasCorrectOptionCount = exportValues.length === 2;
|
||||
if (!hasCorrectOptionCount) {
|
||||
const exportValues = normalAppearance.getKeys();
|
||||
if (!exportValues.includes("Off")) {
|
||||
// The /Off appearance is optional.
|
||||
exportValues.push("Off");
|
||||
}
|
||||
if (exportValues.length !== 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.data.exportValue =
|
||||
exportValues[0] === "Off" ? exportValues[1] : exportValues[0];
|
||||
|
||||
const normalAppearance = customAppearance.get("N");
|
||||
if (!isDict(normalAppearance)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.checkedAppearance = normalAppearance.get(this.data.exportValue);
|
||||
this.uncheckedAppearance = normalAppearance.get("Off") || null;
|
||||
}
|
||||
|
@ -1882,11 +1882,11 @@ describe("annotation", function () {
|
||||
buttonWidgetDict.set("V", Name.get("1"));
|
||||
|
||||
const appearanceStatesDict = new Dict();
|
||||
const exportValueOptionsDict = new Dict();
|
||||
const normalAppearanceDict = new Dict();
|
||||
|
||||
exportValueOptionsDict.set("Off", 0);
|
||||
exportValueOptionsDict.set("Checked", 1);
|
||||
appearanceStatesDict.set("D", exportValueOptionsDict);
|
||||
normalAppearanceDict.set("Off", 0);
|
||||
normalAppearanceDict.set("Checked", 1);
|
||||
appearanceStatesDict.set("N", normalAppearanceDict);
|
||||
buttonWidgetDict.set("AP", appearanceStatesDict);
|
||||
|
||||
const buttonWidgetRef = Ref.get(124, 0);
|
||||
@ -1931,9 +1931,38 @@ describe("annotation", function () {
|
||||
}, done.fail);
|
||||
});
|
||||
|
||||
it("should handle checkboxes without /Off appearance", function (done) {
|
||||
buttonWidgetDict.set("V", Name.get("1"));
|
||||
|
||||
const appearanceStatesDict = new Dict();
|
||||
const normalAppearanceDict = new Dict();
|
||||
|
||||
normalAppearanceDict.set("Checked", 1);
|
||||
appearanceStatesDict.set("N", normalAppearanceDict);
|
||||
buttonWidgetDict.set("AP", appearanceStatesDict);
|
||||
|
||||
const buttonWidgetRef = Ref.get(124, 0);
|
||||
const xref = new XRefMock([
|
||||
{ ref: buttonWidgetRef, data: buttonWidgetDict },
|
||||
]);
|
||||
|
||||
AnnotationFactory.create(
|
||||
xref,
|
||||
buttonWidgetRef,
|
||||
pdfManagerMock,
|
||||
idFactoryMock
|
||||
).then(({ data }) => {
|
||||
expect(data.annotationType).toEqual(AnnotationType.WIDGET);
|
||||
expect(data.checkBox).toEqual(true);
|
||||
expect(data.fieldValue).toEqual("1");
|
||||
expect(data.radioButton).toEqual(false);
|
||||
expect(data.exportValue).toEqual("Checked");
|
||||
done();
|
||||
}, done.fail);
|
||||
});
|
||||
|
||||
it("should render checkboxes for printing", function (done) {
|
||||
const appearanceStatesDict = new Dict();
|
||||
const exportValueOptionsDict = new Dict();
|
||||
const normalAppearanceDict = new Dict();
|
||||
const checkedAppearanceDict = new Dict();
|
||||
const uncheckedAppearanceDict = new Dict();
|
||||
@ -1949,9 +1978,6 @@ describe("annotation", function () {
|
||||
checkedAppearanceDict.set("Matrix", [1, 0, 0, 1, 0, 0]);
|
||||
normalAppearanceDict.set("Checked", checkedStream);
|
||||
normalAppearanceDict.set("Off", uncheckedStream);
|
||||
exportValueOptionsDict.set("Off", 0);
|
||||
exportValueOptionsDict.set("Checked", 1);
|
||||
appearanceStatesDict.set("D", exportValueOptionsDict);
|
||||
appearanceStatesDict.set("N", normalAppearanceDict);
|
||||
|
||||
buttonWidgetDict.set("AP", appearanceStatesDict);
|
||||
@ -2019,14 +2045,10 @@ describe("annotation", function () {
|
||||
|
||||
it("should save checkboxes", function (done) {
|
||||
const appearanceStatesDict = new Dict();
|
||||
const exportValueOptionsDict = new Dict();
|
||||
const normalAppearanceDict = new Dict();
|
||||
|
||||
normalAppearanceDict.set("Checked", Ref.get(314, 0));
|
||||
normalAppearanceDict.set("Off", Ref.get(271, 0));
|
||||
exportValueOptionsDict.set("Off", 0);
|
||||
exportValueOptionsDict.set("Checked", 1);
|
||||
appearanceStatesDict.set("D", exportValueOptionsDict);
|
||||
appearanceStatesDict.set("N", normalAppearanceDict);
|
||||
|
||||
buttonWidgetDict.set("AP", appearanceStatesDict);
|
||||
@ -2059,8 +2081,7 @@ describe("annotation", function () {
|
||||
expect(oldData.data).toEqual(
|
||||
"123 0 obj\n" +
|
||||
"<< /Type /Annot /Subtype /Widget /FT /Btn " +
|
||||
"/AP << /D << /Off 0 /Checked 1>> " +
|
||||
"/N << /Checked 314 0 R /Off 271 0 R>>>> " +
|
||||
"/AP << /N << /Checked 314 0 R /Off 271 0 R>>>> " +
|
||||
"/V /Checked /AS /Checked /M (date)>>\nendobj\n"
|
||||
);
|
||||
return annotation;
|
||||
@ -2142,7 +2163,6 @@ describe("annotation", function () {
|
||||
|
||||
it("should render radio buttons for printing", function (done) {
|
||||
const appearanceStatesDict = new Dict();
|
||||
const exportValueOptionsDict = new Dict();
|
||||
const normalAppearanceDict = new Dict();
|
||||
const checkedAppearanceDict = new Dict();
|
||||
const uncheckedAppearanceDict = new Dict();
|
||||
@ -2158,9 +2178,6 @@ describe("annotation", function () {
|
||||
checkedAppearanceDict.set("Matrix", [1, 0, 0, 1, 0, 0]);
|
||||
normalAppearanceDict.set("Checked", checkedStream);
|
||||
normalAppearanceDict.set("Off", uncheckedStream);
|
||||
exportValueOptionsDict.set("Off", 0);
|
||||
exportValueOptionsDict.set("Checked", 1);
|
||||
appearanceStatesDict.set("D", exportValueOptionsDict);
|
||||
appearanceStatesDict.set("N", normalAppearanceDict);
|
||||
|
||||
buttonWidgetDict.set("Ff", AnnotationFieldFlag.RADIO);
|
||||
@ -2229,14 +2246,10 @@ describe("annotation", function () {
|
||||
|
||||
it("should save radio buttons", function (done) {
|
||||
const appearanceStatesDict = new Dict();
|
||||
const exportValueOptionsDict = new Dict();
|
||||
const normalAppearanceDict = new Dict();
|
||||
|
||||
normalAppearanceDict.set("Checked", Ref.get(314, 0));
|
||||
normalAppearanceDict.set("Off", Ref.get(271, 0));
|
||||
exportValueOptionsDict.set("Off", 0);
|
||||
exportValueOptionsDict.set("Checked", 1);
|
||||
appearanceStatesDict.set("D", exportValueOptionsDict);
|
||||
appearanceStatesDict.set("N", normalAppearanceDict);
|
||||
|
||||
buttonWidgetDict.set("Ff", AnnotationFieldFlag.RADIO);
|
||||
@ -2282,8 +2295,7 @@ describe("annotation", function () {
|
||||
expect(radioData.data).toEqual(
|
||||
"123 0 obj\n" +
|
||||
"<< /Type /Annot /Subtype /Widget /FT /Btn /Ff 32768 " +
|
||||
"/AP << /D << /Off 0 /Checked 1>> " +
|
||||
"/N << /Checked 314 0 R /Off 271 0 R>>>> " +
|
||||
"/AP << /N << /Checked 314 0 R /Off 271 0 R>>>> " +
|
||||
"/Parent 456 0 R /AS /Checked /M (date)>>\nendobj\n"
|
||||
);
|
||||
expect(parentData.ref).toEqual(Ref.get(456, 0));
|
||||
|
Loading…
x
Reference in New Issue
Block a user