From 53fc54462b3b9abc75b6042454d217f2d58f5b4a Mon Sep 17 00:00:00 2001 From: David Warring Date: Wed, 2 Oct 2024 12:35:30 +1300 Subject: [PATCH] General documentation --- README.md | 14 +-- lib/PDF/Tags.rakumod | 199 +++++++++++++++---------------- lib/PDF/Tags/Node/Parent.rakumod | 1 - 3 files changed, 105 insertions(+), 109 deletions(-) diff --git a/README.md b/README.md index a8a151c..477271f 100644 --- a/README.md +++ b/README.md @@ -248,13 +248,13 @@ tagged internal link to a PDF. As a rule, all content doesn't have to form part of the structure tree, but should be tagged to meet accessibility guidelines. -This sometimes requires tagging of incidental graphics. `PDF::Content` has a `tag()` method for this. The content is be tagged, but does not appear in the content stream. +This sometimes requires tagging of incidental graphics. `PDF::Content` has a `tag()` method for this. The content is tagged, but does not appear in the structure tree. Some of the commonly used content tags are: #### Artifact -Artifact content forms part of the visual display, but does not belong in the Structure Tree and is tagged using the `PDF::Content` `tag` method. +Artifact content forms part of the visual display, but does not belong in the structure Tree. For example: ```raku @@ -295,7 +295,7 @@ text is being inserted as a paragraph in the structure tree. #### Span -This tag may be used in the structure tree, or at the content level to defined attributes of a graphics sequence. Its usage is similar to the XHTML `span` tag. +This tag may be used either in the structure tree, or at the content level to defined attributes of a graphics sequence. Its usage is similar to the XHTML `span` tag. ```raku $gfx.tag: Span: :Lang, { @@ -303,8 +303,6 @@ $gfx.tag: Span: :Lang, { } ``` -It can be used almost anywhere in the structure tree, or at the content level, as above. - ### Role Maps The PDF standard allows user defined tags, which are mapped to @@ -319,8 +317,8 @@ use PDF::Tags::Elem; use PDF::Class; use PDF::Page; -enum RoleMap ( :Body
, :Footnote, :Book ); -constant %role-map = RoleMap.enums.Hash; +enum Roles ( :Book, :FootNote ); +constant %role-map = Roles.enums.Hash; my PDF::Class $pdf .= new; my PDF::Tags $tags .= create: :$pdf, :%role-map; @@ -334,7 +332,7 @@ $page.graphics: -> $gfx { .say: 'Some body text¹', :position[50, 150]; }; - $doc.Footnote: $gfx, { + $doc.FootNote: $gfx, { .say: '¹With a foot-note', :position[50, 20]; }; diff --git a/lib/PDF/Tags.rakumod b/lib/PDF/Tags.rakumod index 3222f92..931aa84 100644 --- a/lib/PDF/Tags.rakumod +++ b/lib/PDF/Tags.rakumod @@ -1,124 +1,123 @@ #| Tagged PDF root node -class PDF::Tags:ver<0.1.17> { - - use PDF::Tags::Node::Parent :&att-owner; - also is PDF::Tags::Node::Parent; - - use PDF::Tags::Node::Root; - also does PDF::Tags::Node::Root; - - use PDF::Class:ver<0.4.10+>; - use PDF::NumberTree :NumberTree; - use PDF::StructElem; - use PDF::StructTreeRoot; - - has Hash $.class-map is built; - has Hash $.role-map is built; - has NumberTree $.parent-tree is built; - has $.styler; - has Lock $!lock handles .= new; - method root { self } - method marks { True } - - submethod TWEAK(PDF::StructTreeRoot :$cos!, :%role-map) { - $!class-map = $_ with $cos.ClassMap; - $!role-map = $_ with $cos.RoleMap; - self.set-role(.key, .value) for %role-map.pairs; - $!parent-tree = .number-tree - given $cos.ParentTree //= { :Nums[] }; - } +unit class PDF::Tags:ver<0.1.17>; + +use PDF::Tags::Node::Parent :&att-owner; +also is PDF::Tags::Node::Parent; + +use PDF::Tags::Node::Root; +also does PDF::Tags::Node::Root; + +use PDF::Class:ver<0.4.10+>; +use PDF::NumberTree :NumberTree; +use PDF::StructElem; +use PDF::StructTreeRoot; + +has Hash $.class-map is built; +has Hash $.role-map is built; +has NumberTree $.parent-tree is built; +has $.styler; +has Lock $!lock handles .= new; +method root { self } +method marks { True } + +submethod TWEAK(PDF::StructTreeRoot :$cos!, :%role-map) { + $!class-map = $_ with $cos.ClassMap; + $!role-map = $_ with $cos.RoleMap; + self.set-role(.key, .value) for %role-map.pairs; + $!parent-tree = .number-tree + given $cos.ParentTree //= { :Nums[] }; +} - method read(|c) { - my constant Reader = 'PDF::Tags::Reader'; - CATCH { - when X::CompUnit::UnsatisfiedDependency { - fail "{Reader.raku} needs to be installed to read tagged PDF files"; - } +method read(|c) { + my constant Reader = 'PDF::Tags::Reader'; + CATCH { + when X::CompUnit::UnsatisfiedDependency { + fail "{Reader.raku} needs to be installed to read tagged PDF files"; } - require ::(Reader); - ::(Reader).read(|c); } + require ::(Reader); + ::(Reader).read(|c); +} - method set-role(Str:D $role, Str:D $base) { - $!role-map //= {}; - with $!role-map{$role} { - warn "role mapping $role => $base conflicts with $role => $_" - unless $base eq $_; - } - else { - $_ = $base; - } +method set-role(Str:D $role, Str:D $base) { + $!role-map //= {}; + with $!role-map{$role} { + warn "role mapping $role => $base conflicts with $role => $_" + unless $base eq $_; } + else { + $_ = $base; + } +} - sub build-class-map($cos, %class-map) { - for %class-map { - my $class = .key; - my %attributes = .value; - my Hash %atts-by-owner; - for %attributes { - #Raku 2022.06+ my :($owner, $key) := att-owner(.key); - my ($owner, $key) = att-owner(.key); - %atts-by-owner{$owner}{$key} = .value; - } - my PDF::Attributes() @atts = %atts-by-owner.keys.sort.map: -> $owner { - my %atts = %atts-by-owner{$owner}; - %atts = $owner; - %atts; - } - - if @atts { - $cos.ClassMap //= %(); - if @atts == 1 { - $cos.ClassMap{$class} = @atts[0]; - } - else { - $cos.ClassMap{$class} = @atts; - } - } +sub build-class-map($cos, %class-map) { + for %class-map { + my $class = .key; + my %attributes = .value; + my Hash %atts-by-owner; + for %attributes { + #Raku 2022.06+ my :($owner, $key) := att-owner(.key); + my ($owner, $key) = att-owner(.key); + %atts-by-owner{$owner}{$key} = .value; + } + my PDF::Attributes() @atts = %atts-by-owner.keys.sort.map: -> $owner { + my %atts = %atts-by-owner{$owner}; + %atts = $owner; + %atts; } - } - method create( - PDF::Class:D :$pdf!, - PDF::StructTreeRoot() :$cos = { :Type( :name )}, - :%role-map, - :%class-map, - |c - --> PDF::Tags:D - ) { - $cos.RoleMap = %role-map if %role-map; - build-class-map($cos, %class-map) - if %class-map; - $cos.check; - - given $pdf { - with .catalog.StructTreeRoot { - fail "document already contains marked content"; + if @atts { + $cos.ClassMap //= %(); + if @atts == 1 { + $cos.ClassMap{$class} = @atts[0]; } else { - $_ = $cos; + $cos.ClassMap{$class} = @atts; } - . = True - given .Root //= {}; - .creator.push: "{self.^name}-{self.^ver}"; } - self.new: :$cos, :root(self.WHAT), :marks, |c } +} - # Set the page to a given index. - # To create identical PDF files. Mostly for thread-testing purposes. - method set-page-index(PDF::Page:D $Pg, UInt:D $idx) { - self.protect: { - $Pg.StructParents = $idx; - $!parent-tree[$idx] //= []; +method create( + PDF::Class:D :$pdf!, + PDF::StructTreeRoot() :$cos = { :Type( :name )}, + :%role-map, + :%class-map, + |c + --> PDF::Tags:D +) { + $cos.RoleMap = %role-map if %role-map; + build-class-map($cos, %class-map) + if %class-map; + $cos.check; + + given $pdf { + with .catalog.StructTreeRoot { + fail "document already contains marked content"; } + else { + $_ = $cos; + } + . = True + given .Root //= {}; + .creator.push: "{self.^name}-{self.^ver}"; } + self.new: :$cos, :root(self.WHAT), :marks, |c +} - method canvas-tags(|) { - fail "PDF::Tags::Reader is required to read PDF tags"; +# Set the page to a given index. +# To create identical PDF files. Mostly for thread-testing purposes. +method set-page-index(PDF::Page:D $Pg, UInt:D $idx) { + self.protect: { + $Pg.StructParents = $idx; + $!parent-tree[$idx] //= []; } } +method canvas-tags(|) { + fail "PDF::Tags::Reader is required to read PDF tags"; +} + =begin pod =head2 Synopsis diff --git a/lib/PDF/Tags/Node/Parent.rakumod b/lib/PDF/Tags/Node/Parent.rakumod index 77f85bb..5cfa2e4 100644 --- a/lib/PDF/Tags/Node/Parent.rakumod +++ b/lib/PDF/Tags/Node/Parent.rakumod @@ -112,7 +112,6 @@ multi method fragment(Str:D :$name!, *%o --> PDF::Tags::Node:D) { multi method fragment(Str:D $name = 'DocumentFragment', *%o) { self.fragment(:$name, |%o); } - multi method FALLBACK(Str:D $name where $_ ∈ TagSet, |c) { self.add-kid(:$name, |c) }