Class: Prawn::Accessibility::StructureTree Private
- Inherits:
-
Object
- Object
- Prawn::Accessibility::StructureTree
- Includes:
- MarkedContent
- Defined in:
- lib/prawn/accessibility/structure_tree.rb
Overview
This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.
Manages the PDF structure tree for tagged/accessible PDFs.
The structure tree provides the logical structure of a document, mapping marked content sequences in page content streams to structure elements (headings, paragraphs, tables, etc.).
It talks to the document exclusively through the public renderer API
(ref!, deref, add_content, state), so it requires no patches to
any pdf-core class.
PDF spec references: Section 14.7 (Logical Structure)
Instance Attribute Summary collapse
-
#document_elem_ref ⇒ PDF::Core::Reference
readonly
private
Document-level structure element.
-
#element_stack ⇒ Array<PDF::Core::Reference>
readonly
private
Stack of open structure elements.
-
#elements ⇒ Array<Hash>
readonly
private
All structure elements created.
-
#next_mcid ⇒ Integer
readonly
private
Next available MCID for the current page.
-
#parent_tree_map ⇒ Hash{Integer => Array}
readonly
private
Page StructParents index => array of structure element refs for marked content on that page.
-
#renderer ⇒ PDF::Core::Renderer
readonly
private
Owning renderer.
-
#root_ref ⇒ PDF::Core::Reference
readonly
private
StructTreeRoot indirect object.
Instance Method Summary collapse
-
#add_element(tag, attributes = {}) ⇒ PDF::Core::Reference
private
Add a structure element as a child of the current open element (or the document element if none is open).
-
#allocate_mcid ⇒ Integer
private
Allocate the next MCID for the current page and track it.
-
#begin_element(tag, attributes = {}) ⇒ PDF::Core::Reference
private
Begin a structure element scope.
-
#end_element ⇒ PDF::Core::Reference
private
End the current structure element scope.
-
#finalize! ⇒ void
private
Finalize the structure tree before rendering.
-
#initialize(renderer) ⇒ StructureTree
constructor
private
A new instance of StructureTree.
-
#mark_artifact(artifact_type: nil) { ... } ⇒ void
private
Mark content as an artifact (decorative, not read by screen readers).
-
#mark_content(tag, struct_elem_ref: nil) { ... } ⇒ void
private
Add marked content to the current structure element.
Methods included from MarkedContent
#begin_marked_content, #begin_marked_content_with_properties, #end_marked_content, #marked_content_sequence, #marked_content_sequence_with_properties
Constructor Details
#initialize(renderer) ⇒ StructureTree
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns a new instance of StructureTree.
46 47 48 49 50 51 52 53 54 55 |
# File 'lib/prawn/accessibility/structure_tree.rb', line 46 def initialize(renderer) @renderer = renderer @elements = [] @parent_tree_map = {} @next_mcid = 0 @element_stack = [] @page_mcid_map = {} # page_ref_id => next mcid for that page @root_ref = nil @document_elem_ref = nil end |
Instance Attribute Details
#document_elem_ref ⇒ PDF::Core::Reference (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns Document-level structure element.
30 31 32 |
# File 'lib/prawn/accessibility/structure_tree.rb', line 30 def document_elem_ref @document_elem_ref end |
#element_stack ⇒ Array<PDF::Core::Reference> (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns stack of open structure elements.
43 44 45 |
# File 'lib/prawn/accessibility/structure_tree.rb', line 43 def element_stack @element_stack end |
#elements ⇒ Array<Hash> (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns all structure elements created.
33 34 35 |
# File 'lib/prawn/accessibility/structure_tree.rb', line 33 def elements @elements end |
#next_mcid ⇒ Integer (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns next available MCID for the current page.
40 41 42 |
# File 'lib/prawn/accessibility/structure_tree.rb', line 40 def next_mcid @next_mcid end |
#parent_tree_map ⇒ Hash{Integer => Array} (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns page StructParents index => array of structure element refs for marked content on that page.
37 38 39 |
# File 'lib/prawn/accessibility/structure_tree.rb', line 37 def parent_tree_map @parent_tree_map end |
#renderer ⇒ PDF::Core::Renderer (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns owning renderer.
24 25 26 |
# File 'lib/prawn/accessibility/structure_tree.rb', line 24 def renderer @renderer end |
#root_ref ⇒ PDF::Core::Reference (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns StructTreeRoot indirect object.
27 28 29 |
# File 'lib/prawn/accessibility/structure_tree.rb', line 27 def root_ref @root_ref end |
Instance Method Details
#add_element(tag, attributes = {}) ⇒ PDF::Core::Reference
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Add a structure element as a child of the current open element (or the document element if none is open).
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/prawn/accessibility/structure_tree.rb', line 82 def add_element(tag, attributes = {}) parent_ref = current_element || document_element elem_data = { Type: :StructElem, S: tag, P: parent_ref, K: [], } elem_data[:Alt] = attributes[:Alt] if attributes[:Alt] elem_data[:ActualText] = attributes[:ActualText] if attributes[:ActualText] elem_data[:Lang] = attributes[:Lang] if attributes[:Lang] if attributes[:Scope] elem_data[:A] = { O: :Table, Scope: attributes[:Scope], } end elem_ref = renderer.ref!(elem_data) @elements << elem_ref # Add as child of parent parent_data = renderer.deref(parent_ref) parent_data[:K] << elem_ref elem_ref end |
#allocate_mcid ⇒ Integer
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Allocate the next MCID for the current page and track it.
60 61 62 63 64 65 66 67 68 69 |
# File 'lib/prawn/accessibility/structure_tree.rb', line 60 def allocate_mcid page = renderer.state.page page_id = page.dictionary.identifier @page_mcid_map[page_id] ||= 0 mcid = @page_mcid_map[page_id] @page_mcid_map[page_id] += 1 mcid end |
#begin_element(tag, attributes = {}) ⇒ PDF::Core::Reference
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Begin a structure element scope. Content rendered inside will be children of this element.
119 120 121 122 123 |
# File 'lib/prawn/accessibility/structure_tree.rb', line 119 def begin_element(tag, attributes = {}) elem_ref = add_element(tag, attributes) @element_stack.push(elem_ref) elem_ref end |
#end_element ⇒ PDF::Core::Reference
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
End the current structure element scope.
128 129 130 |
# File 'lib/prawn/accessibility/structure_tree.rb', line 128 def end_element @element_stack.pop end |
#finalize! ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Finalize the structure tree before rendering. Called via before_render callback.
Builds the StructTreeRoot, ParentTree, and wires everything into the Catalog.
188 189 190 191 192 193 194 195 |
# File 'lib/prawn/accessibility/structure_tree.rb', line 188 def finalize! return if @elements.empty? && @parent_tree_map.empty? build_root build_parent_tree assign_struct_parents_to_pages attach_to_catalog end |
#mark_artifact(artifact_type: nil) { ... } ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Mark content as an artifact (decorative, not read by screen readers).
171 172 173 174 175 176 177 178 179 |
# File 'lib/prawn/accessibility/structure_tree.rb', line 171 def mark_artifact(artifact_type: nil) if artifact_type begin_marked_content_with_properties(:Artifact, { Type: artifact_type }) else begin_marked_content(:Artifact) end yield if block_given? end_marked_content end |
#mark_content(tag, struct_elem_ref: nil) { ... } ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Add marked content to the current structure element. This allocates an MCID, records the mapping, and emits BDC/EMC operators around the yielded block.
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/prawn/accessibility/structure_tree.rb', line 141 def mark_content(tag, struct_elem_ref: nil) elem_ref = struct_elem_ref || current_element || document_element mcid = allocate_mcid page = renderer.state.page page_ref = page.dictionary # Record in parent tree map page_struct_parents = page_struct_parents_index(page_ref) @parent_tree_map[page_struct_parents] ||= [] # Add marked content reference to the structure element's K array mcr = { Type: :MCR, MCID: mcid, Pg: page_ref } elem_data = renderer.deref(elem_ref) elem_data[:K] << mcr # Track which struct element owns this MCID on this page @parent_tree_map[page_struct_parents][mcid] = elem_ref # Emit BDC/EMC in content stream (via the MarkedContent mixin) begin_marked_content_with_properties(tag, { MCID: mcid }) yield if block_given? end_marked_content end |