Return the definition of an OCMD (optional content membership dictionary). Recognizes PDF dict keys /OCGs (PDF array of OCGs), /P (policy string) and /VE (visibility expression, PDF array). Via string manipulation, this info is converted to a Python dictionary with keys "xref", "ocgs",
(doc: Document, xref: int)
| 4637 | |
| 4638 | |
| 4639 | def get_ocmd(doc: Document, xref: int) -> dict: |
| 4640 | """Return the definition of an OCMD (optional content membership dictionary). |
| 4641 | |
| 4642 | Recognizes PDF dict keys /OCGs (PDF array of OCGs), /P (policy string) and |
| 4643 | /VE (visibility expression, PDF array). Via string manipulation, this |
| 4644 | info is converted to a Python dictionary with keys "xref", "ocgs", "policy" |
| 4645 | and "ve" - ready to recycle as input for 'set_ocmd()'. |
| 4646 | """ |
| 4647 | |
| 4648 | if xref not in range(doc.xref_length()): |
| 4649 | raise ValueError("bad xref") |
| 4650 | text = doc.xref_object(xref, compressed=True) |
| 4651 | if "/Type/OCMD" not in text: |
| 4652 | raise ValueError("bad object type") |
| 4653 | textlen = len(text) |
| 4654 | |
| 4655 | p0 = text.find("/OCGs[") # look for /OCGs key |
| 4656 | p1 = text.find("]", p0) |
| 4657 | if p0 < 0 or p1 < 0: # no OCGs found |
| 4658 | ocgs = None |
| 4659 | else: |
| 4660 | ocgs = text[p0 + 6 : p1].replace("0 R", " ").split() |
| 4661 | ocgs = list(map(int, ocgs)) |
| 4662 | |
| 4663 | p0 = text.find("/P/") # look for /P policy key |
| 4664 | if p0 < 0: |
| 4665 | policy = None |
| 4666 | else: |
| 4667 | p1 = text.find("ff", p0) |
| 4668 | if p1 < 0: |
| 4669 | p1 = text.find("on", p0) |
| 4670 | if p1 < 0: # some irregular syntax |
| 4671 | raise ValueError("bad object at xref") |
| 4672 | else: |
| 4673 | policy = text[p0 + 3 : p1 + 2] |
| 4674 | |
| 4675 | p0 = text.find("/VE[") # look for /VE visibility expression key |
| 4676 | if p0 < 0: # no visibility expression found |
| 4677 | ve = None |
| 4678 | else: |
| 4679 | lp = rp = 0 # find end of /VE by finding last ']'. |
| 4680 | p1 = p0 |
| 4681 | while lp < 1 or lp != rp: |
| 4682 | p1 += 1 |
| 4683 | if not p1 < textlen: # some irregular syntax |
| 4684 | raise ValueError("bad object at xref") |
| 4685 | if text[p1] == "[": |
| 4686 | lp += 1 |
| 4687 | if text[p1] == "]": |
| 4688 | rp += 1 |
| 4689 | # p1 now positioned at the last "]" |
| 4690 | ve = text[p0 + 3 : p1 + 1] # the PDF /VE array |
| 4691 | ve = ( |
| 4692 | ve.replace("/And", '"and",') |
| 4693 | .replace("/Not", '"not",') |
| 4694 | .replace("/Or", '"or",') |
| 4695 | ) |
| 4696 | ve = ve.replace(" 0 R]", "]").replace(" 0 R", ",").replace("][", "],[") |
nothing calls this directly
no test coverage detected
searching dependent graphs…