Bug 707999

Summary: Optional content groups logic bugs
Product: MuPDF Reporter: Giorgio Bianchini <giorgio.bianchini>
Component: mupdfAssignee: MuPDF bugs <mupdf-bugs>
Status: UNCONFIRMED ---    
Severity: normal CC: sumitp7816
Priority: P2    
Version: 1.24.9   
Hardware: PC   
OS: All   
Customer: Word Size: ---
Attachments: PDF with optional content groups

Description Giorgio Bianchini 2024-09-01 00:24:27 UTC
Created attachment 26009 [details]
PDF with optional content groups

The attached PDF uses optional content groups and displays correctly in Firefox and Adobe Reader, but not in MuPDF (which completely ignores the OCGs and draws everything).

This appears to be due to at least three separate issues:

1. The OCProperties dictionary in the PDF file specifies the default configuration in the D entry, but it does not have a Configs entry. As a result, MuPDF incorrectly reports that the document has 0 OCG configurations (pdf-layer.c, lines 752 and following). However, according to table 100 in the PDF 1.7 spec, the Configs entry is optional and specifies **alternate** optional content configuration dictionaries. Therefore, the default configuration specified by the D entry should also be taken into account when counting OCG configurations defined in the document.

2. Even after fixing the document by adding a Configs entry, the second issue is a bug in the logic that determines OCMD visibility, specifically lines 712-717 of pdf-layer.c:

	if ((combine & 1) == 0)
		hidden = !hidden;
	if (combine & 2)
		on &= hidden;
	else
		on |= hidden;

   When `combine` is 0 (AnyOn) or 3 (AllOff), this works as intended; however, if `combine` is 1 (AllOn), `on` ends up being always true (because the starting value is 1 and only OR operations are performed), and if `combine` is 2 (AnyOff) then `on` is always false (the starting value is 0 and only AND operations are performed). Replacing the lines above with the following should fix the issue:

	if (combine == 0 && !hidden) {
		on = 1;
		break;
	}
	else if (combine == 1 && hidden) {
		on = 0;
		break;
	} else if (combine == 2 && hidden) {
		on = 1;
		break;
	}
	else if (combine == 3 && !hidden) {
		on = 0;
		break;
	}

3. Finally, visibility expressions (VE entry in the OCMD dictionary) are completely ignored. Lines 679-683 in pdf-layer.c:

	obj = pdf_dict_get(ctx, ocg, PDF_NAME(VE));
	if (pdf_is_array(ctx, obj)) {
		/* FIXME: Calculate visibility from array */
		return 0;
	}
Comment 1 sumitp7816 2024-09-01 15:27:58 UTC
Are we going to commit any changes to this report?
Comment 2 Giorgio Bianchini 2024-09-14 18:04:57 UTC
I have created a pull request that fixes these issues and more: https://github.com/ArtifexSoftware/mupdf/pull/51