/* See if a dictionary is a structure element. We identify it by the S and P elements, which are required, and by making sure that the Type element, if present, has a value of "StructElem". */ private boolean isStructElem(PdfDictionary elem) throws PdfException { try { PdfObject typ = elem.get("Type"); if (typ != null) { if (!"StructElem".equals(((PdfSimpleObject) typ).getStringValue())) { return false; } } PdfObject s = _module.resolveIndirectObject(elem.get("S")); // The structure type is supposed to be one of // a list of known structure types, or else is // mapped to one through the role map dictionary. // For the moment, just make sure it's a name. if (!(s instanceof PdfSimpleObject)) { return false; } Token tok = ((PdfSimpleObject) s).getToken(); if (!(tok instanceof Name)) { return false; } // It appears that there really isn't a requirement // to have structure types belong to the standard types. // Conditionalize this code out, pending more info. boolean checkStandardTypes = false; String st = ((Name) tok).getValue(); st = _tree.dereferenceStructType(st); if (!StdStructTypes.includes(st)) { if (checkStandardTypes) { throw new PdfInvalidException("Non-standard structure type name"); } } else { // The structure type is a standard one. } // The parent reference must be an indirect reference. // The documentation says it must refer to another // structure element dictionary, but it seems that it // must also be able to refer to the structure tree root. // I'll allow both. PdfObject pref = elem.get("P"); if (!(pref instanceof PdfIndirectObj)) { return false; } // Make sure it refers to a dictionary (at least). PdfDictionary p = (PdfDictionary) _module.resolveIndirectObject(pref); PdfSimpleObject ptype = (PdfSimpleObject) p.get("Type"); if (ptype != null) { String typename = ptype.getStringValue(); if (!"StructTreeRoot".equals(typename) && !"StructElem".equals(typename)) { return false; } } // Passed all tests. return true; } catch (Exception e) { // Some assumption was violated return false; } }
/** * Constructor. * * @param dict A PdfDictionary corresponding to a structure element * @param tree The root StructureTree object */ public StructureElement(PdfDictionary dict, StructureTree tree) throws PdfException { _tree = tree; _dict = dict; _module = tree.getModule(); _structType = null; // If this element has a standard structure type, find it. try { PdfObject s = _module.resolveIndirectObject(dict.get("S")); Token tok = ((PdfSimpleObject) s).getToken(); String st = ((Name) tok).getValue(); st = _tree.dereferenceStructType(st); if (StdStructTypes.includes(st)) { _structType = st; } } catch (IOException e) { } }
/** * Determine if the attributes of this element are valid. If errors are detected, throws a * PdfInvalidException. */ public void checkAttributes() throws PdfException { final String badattr = "Invalid structure attribute"; PdfObject attr; // Use the variables _structIsInline and _attrIsBlock to // note when we've got a block-level-only attribute in // an inline structure element. We initially set // _structIsInline based on the structure type, but this // may be overridden by the Placement attribute. // Figure elements occupy an ambiguous position, so we // don't mark them as ILSE's. Also, TR, TH and TD are // defined to be neither BLSE's nor ILSE's. _attrIsBlock = false; _structIsInline = !_structType.equals("Figure") && !_structType.equals("TH") && !_structType.equals("TD") && !_structType.equals("TR") && !StdStructTypes.isBlockLevel(_structType); try { attr = _module.resolveIndirectObject(_dict.get("A")); } catch (Exception e) { throw new PdfInvalidException("Invalid structure attribute reference"); } if (attr == null) { // no attributes is fine return; } if (attr instanceof PdfArray) { // If we have an array, it may contain elements and // revision numbers. A revision number may follow // an element, but there doesn't have to be one. Vector attrVec = ((PdfArray) attr).getContent(); for (int i = 0; i < attrVec.size(); i++) { PdfObject attrElem; try { attrElem = _module.resolveIndirectObject((PdfObject) attrVec.elementAt(i)); } catch (IOException e) { throw new PdfInvalidException(badattr); } if (attrElem instanceof PdfDictionary) { checkAttribute((PdfDictionary) attrElem); } else if (attrElem instanceof PdfSimpleObject) { try { Numeric revnum = (Numeric) ((PdfSimpleObject) attrElem).getToken(); } catch (Exception e) { throw new PdfInvalidException(badattr); } } else { throw new PdfInvalidException(badattr); } } } else if (attr instanceof PdfDictionary) { checkAttribute((PdfDictionary) attr); } else { throw new PdfInvalidException("Structure attribute has illegal type"); } if (_structIsInline && _attrIsBlock) { throw new PdfInvalidException("Block-level attributes in inline structure element"); } }