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 "xre
(doc: 'Document', xref: int)
| 4962 | return rc |
| 4963 | |
| 4964 | def get_ocmd(doc: 'Document', xref: int) -> dict: |
| 4965 | """Return the definition of an OCMD (optional content membership dictionary). |
| 4966 | |
| 4967 | Recognizes PDF dict keys /OCGs (PDF array of OCGs), /P (policy string) and |
| 4968 | /VE (visibility expression, PDF array). Via string manipulation, this |
| 4969 | info is converted to a Python dictionary with keys "xref", "ocgs", "policy" |
| 4970 | and "ve" - ready to recycle as input for 'set_ocmd()'. |
| 4971 | """ |
| 4972 | |
| 4973 | if xref not in range(doc.xref_length()): |
| 4974 | raise ValueError("bad xref") |
| 4975 | text = doc.xref_object(xref, compressed=True) |
| 4976 | if "/Type/OCMD" not in text: |
| 4977 | raise ValueError("bad object type") |
| 4978 | textlen = len(text) |
| 4979 | |
| 4980 | p0 = text.find("/OCGs[") # look for /OCGs key |
| 4981 | p1 = text.find("]", p0) |
| 4982 | if p0 < 0 or p1 < 0: # no OCGs found |
| 4983 | ocgs = None |
| 4984 | else: |
| 4985 | ocgs = text[p0 + 6 : p1].replace("0 R", " ").split() |
| 4986 | ocgs = list(map(int, ocgs)) |
| 4987 | |
| 4988 | p0 = text.find("/P/") # look for /P policy key |
| 4989 | if p0 < 0: |
| 4990 | policy = None |
| 4991 | else: |
| 4992 | p1 = text.find("ff", p0) |
| 4993 | if p1 < 0: |
| 4994 | p1 = text.find("on", p0) |
| 4995 | if p1 < 0: # some irregular syntax |
| 4996 | raise ValueError("bad object at xref") |
| 4997 | else: |
| 4998 | policy = text[p0 + 3 : p1 + 2] |
| 4999 | |
| 5000 | p0 = text.find("/VE[") # look for /VE visibility expression key |
| 5001 | if p0 < 0: # no visibility expression found |
| 5002 | ve = None |
| 5003 | else: |
| 5004 | lp = rp = 0 # find end of /VE by finding last ']'. |
| 5005 | p1 = p0 |
| 5006 | while lp < 1 or lp != rp: |
| 5007 | p1 += 1 |
| 5008 | if not p1 < textlen: # some irregular syntax |
| 5009 | raise ValueError("bad object at xref") |
| 5010 | if text[p1] == "[": |
| 5011 | lp += 1 |
| 5012 | if text[p1] == "]": |
| 5013 | rp += 1 |
| 5014 | # p1 now positioned at the last "]" |
| 5015 | ve = text[p0 + 3 : p1 + 1] # the PDF /VE array |
| 5016 | ve = ( |
| 5017 | ve.replace("/And", '"and",') |
| 5018 | .replace("/Not", '"not",') |
| 5019 | .replace("/Or", '"or",') |
| 5020 | ) |
| 5021 | ve = ve.replace(" 0 R]", "]").replace(" 0 R", ",").replace("][", "],[") |