[perl-cairo] Add example file for PDF outline support bindings



commit 0a666e39220ce9a31d54ce32e4c90f03d9cc9fec
Author: Raymond S Brand <rsbx acm org>
Date:   Thu Nov 5 15:06:38 2020 -0500

    Add example file for PDF outline support bindings

 examples/pdf-tagged-text.pl | 345 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 345 insertions(+)
---
diff --git a/examples/pdf-tagged-text.pl b/examples/pdf-tagged-text.pl
new file mode 100755
index 0000000..5bf64a1
--- /dev/null
+++ b/examples/pdf-tagged-text.pl
@@ -0,0 +1,345 @@
+#! /usr/bin/perl
+
+# Adapted and translated to Perl from the file test/pdf-tagged-test.c in the
+# Cairo (version 1.17.3) source repository by Adrian Johnson <ajohnson redneon com>.
+
+
+use strict;
+use warnings;
+use Cairo;
+
+use feature 'say';
+
+
+# This test checks PDF with
+# - tagged text
+# - hyperlinks
+# - document outline
+# - metadata
+# - thumbnails
+# - page labels
+
+
+use constant
+       {
+       FILENAME                => 'pdf-tagged-text.pl.pdf',
+
+       PAGE_WIDTH              => 595,
+       PAGE_HEIGHT             => 842,
+
+       HEADING1_SIZE           => 16,
+       HEADING2_SIZE           => 14,
+       HEADING3_SIZE           => 12,
+       TEXT_SIZE               => 12,
+       HEADING_HEIGHT          => 50,
+       MARGIN                  => 50,
+
+       CAIRO_TAG_DEST          => 'cairo.dest',
+       CAIRO_TAG_LINK          => 'Link',
+
+       CAIRO_PDF_OUTLINE_ROOT  => 0,
+       };
+
+
+my @contents =
+       (
+       [ 0, "Chapter 1",     1 ],
+       [ 1, "Section 1.1",   4 ],
+       [ 2, "Section 1.1.1", 3 ],
+       [ 1, "Section 1.2",   2 ],
+       [ 2, "Section 1.2.1", 4 ],
+       [ 2, "Section 1.2.2", 4 ],
+       [ 1, "Section 1.3",   2 ],
+       [ 0, "Chapter 2",     1 ],
+       [ 1, "Section 2.1",   4 ],
+       [ 2, "Section 2.1.1", 3 ],
+       [ 1, "Section 2.2",   2 ],
+       [ 2, "Section 2.2.1", 4 ],
+       [ 2, "Section 2.2.2", 4 ],
+       [ 1, "Section 2.3",   2 ],
+       [ 0, "Chapter 3",     1 ],
+       [ 1, "Section 3.1",   4 ],
+       [ 2, "Section 3.1.1", 3 ],
+       [ 1, "Section 3.2",   2 ],
+       [ 2, "Section 3.2.1", 4 ],
+       [ 2, "Section 3.2.2", 4 ],
+       [ 1, "Section 3.3",   2 ],
+       );
+
+my @level_data =
+       (
+       [HEADING1_SIZE, 'H1', ['bold', 'open'],],
+       [HEADING2_SIZE, 'H2', [],],
+       [HEADING3_SIZE, 'H3', ['italic'],],
+       );
+
+my @ipsum_lorem = split(' ', "Lorem ipsum dolor sit amet, consectetur adipiscing"
+       . " elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
+       . " Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi"
+       . " ut aliquip ex ea commodo consequat. Duis aute irure dolor in"
+       . " reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla"
+       . " pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa"
+       . " qui officia deserunt mollit anim id est laborum.");
+
+my @roman_numerals = ( "i", "ii", "iii", "iv", "v", );
+
+
+my @paragraph_text;
+my $paragraph_height = 0;
+my $line_height = 0;
+my $y_pos = 0;
+my @outline_parents;
+my $page_num = 0;
+
+
+sub layout_paragraph
+       {
+       my ($cr) = @_;
+
+       $cr->select_font_face('Serif', 'normal', 'normal');
+       $cr->set_font_size(TEXT_SIZE);
+
+       my $font_extents = $cr->font_extents();
+       $line_height = $$font_extents{height};
+
+       my $curr = $ipsum_lorem[0];
+       foreach (@ipsum_lorem[1..$#ipsum_lorem])
+               {
+               my $next = join(' ', $curr, $_);
+               my $text_extents = $cr->text_extents($next);
+               if ($$text_extents{width} + 2*MARGIN > PAGE_WIDTH)
+                       {
+                       push @paragraph_text, $curr;
+                       $next = $_;
+                       }
+               $curr = $next;
+               }
+       if ($curr ne '')
+               {
+               push @paragraph_text, $curr;
+               }
+
+       $paragraph_height = $line_height * (scalar @paragraph_text + 1);
+       }
+
+
+sub draw_paragraph
+       {
+       my ($cr) = @_;
+
+       $cr->select_font_face('Serif', 'normal', 'normal');
+       $cr->set_font_size(TEXT_SIZE);
+
+       $cr->tag_begin('P', '');
+       foreach (@paragraph_text)
+               {
+               $cr->move_to(MARGIN, $y_pos);
+               $cr->show_text($_);
+               $y_pos += $line_height;
+               }
+       $cr->tag_end('P');
+
+       $y_pos += $line_height;
+       }
+
+
+sub draw_page_num
+       {
+       my ($cr, $prefix, $num) = @_;
+
+       my $buf = ''
+               . (defined $prefix) ? $prefix : ''
+               . ($num) ? $num : '';
+
+       $cr->save();
+
+       $cr->select_font_face('Sans', 'normal', 'normal');
+       $cr->set_font_size(12);
+
+       $cr->move_to(PAGE_WIDTH/2, PAGE_HEIGHT - MARGIN);
+       $cr->show_text($buf);
+
+       $cr->restore();
+
+       $cr->get_target()->set_page_label($buf);
+       }
+
+
+sub draw_contents
+       {
+       my ($cr, $section) = @_;
+
+       if ($y_pos + HEADING_HEIGHT + MARGIN > PAGE_HEIGHT)
+               {
+               $cr->show_page();
+               draw_page_num($cr, $roman_numerals[$page_num++], 0);
+               $y_pos = MARGIN;
+               }
+
+       $cr->move_to(MARGIN, $y_pos);
+
+       $cr->select_font_face('Sans', 'normal', 'normal');
+       $cr->set_font_size($level_data[$$section[0]]->[0]);
+
+       $cr->save();
+       $cr->set_source_rgb(0, 0, 1);
+
+       $cr->tag_begin('TOCI', '');
+       $cr->tag_begin('Reference', '');
+       $cr->tag_begin(CAIRO_TAG_LINK, "dest='".$$section[1]."'");
+       $cr->show_text($$section[1]);
+       $cr->tag_end(CAIRO_TAG_LINK);
+       $cr->tag_end('Reference');
+       $cr->tag_end('TOCI');
+
+       $cr->restore();
+
+       $y_pos += HEADING_HEIGHT;
+       }
+
+
+sub draw_section
+       {
+       my ($cr, $section) = @_;
+
+       my $parent;
+
+       if ($$section[0] == 0)
+               {
+               $cr->show_page();
+               draw_page_num($cr, undef, $page_num++);
+               $y_pos = MARGIN;
+
+               $parent = CAIRO_PDF_OUTLINE_ROOT;
+               }
+       else
+               {
+               if ($y_pos + HEADING_HEIGHT + $paragraph_height + MARGIN > PAGE_HEIGHT)
+                       {
+                       $cr->show_page();
+                       draw_page_num($cr, undef, $page_num++);
+                       $y_pos = MARGIN;
+                       }
+
+               $parent = $outline_parents[$$section[0]-1];
+               }
+
+       $cr->tag_begin('Sect', '');
+
+       $cr->select_font_face('Sans', 'normal', 'bold');
+       $cr->set_font_size($level_data[$$section[0]]->[0]);
+
+       $cr->move_to(MARGIN, $y_pos);
+
+       $cr->tag_begin($level_data[$$section[0]]->[1], '');
+       $cr->tag_begin(CAIRO_TAG_DEST, "name='".$$section[1]."'");
+       $cr->show_text($$section[1]);
+       $cr->tag_end(CAIRO_TAG_DEST);
+       $cr->tag_end($level_data[$$section[0]]->[1]);
+
+       $y_pos += HEADING_HEIGHT;
+       $outline_parents[$$section[0]] = $cr->get_target()->add_outline($parent, $$section[1], 
"dest='".$$section[1]."'", $level_data[$$section[0]]->[2]);
+
+       for (my $i=0; $i<$$section[2]; $i++)
+               {
+               if ($y_pos + $paragraph_height + MARGIN > PAGE_HEIGHT)
+                       {
+                       $cr->show_page();
+                       draw_page_num($cr, undef, $page_num++);
+                       $y_pos = MARGIN;
+                       }
+               draw_paragraph($cr);
+               }
+
+       $cr->tag_end('Sect');
+       }
+
+
+sub draw_cover
+       {
+       my ($cr) = @_;
+
+       $cr->select_font_face("Sans", 'normal', 'bold');
+       $cr->set_font_size(16);
+
+       $cr->move_to(PAGE_WIDTH/3, PAGE_HEIGHT/2);
+
+       $cr->tag_begin("Span", '');
+       $cr->show_text("PDF Features Test");
+       $cr->tag_end("Span");
+
+       draw_page_num($cr, "cover", 0);
+       }
+
+
+sub create_document
+       {
+       my ($surface, $cr) = @_;
+
+       layout_paragraph($cr);
+
+       $surface->set_thumbnail_size(PAGE_WIDTH/10, PAGE_HEIGHT/10);
+
+       $surface->set_metadata('title', "PDF Features Test");
+       $surface->set_metadata('author', "cairo test suite");
+       $surface->set_metadata('subject', "cairo test");
+       $surface->set_metadata('keywords', "tags, links, outline, page labels, metadata, thumbnails");
+       $surface->set_metadata('creator', "pdf-features");
+       $surface->set_metadata('create-date', "2016-01-01T12:34:56+10:30");
+       $surface->set_metadata('mod-date', "2016-06-21T05:43:21Z");
+
+       $cr->tag_begin("Document", '');
+
+       draw_cover($cr);
+       $surface->add_outline(CAIRO_PDF_OUTLINE_ROOT, 'Cover', 'page=1', ['bold']);
+       $cr->show_page();
+
+       $page_num = 0;
+       draw_page_num($cr, $roman_numerals[$page_num++], 0);
+       $y_pos = MARGIN;
+
+       $surface->add_outline(CAIRO_PDF_OUTLINE_ROOT, "Contents", "dest='TOC'", ['bold']);
+
+       $cr->tag_begin(CAIRO_TAG_DEST, "name='TOC' internal");
+       $cr->tag_begin("TOC", '');
+
+       foreach (@contents)
+               {
+               draw_contents($cr, $_);
+               }
+
+       $cr->tag_end("TOC");
+       $cr->tag_end(CAIRO_TAG_DEST);
+
+       $page_num = 1;
+       foreach (@contents)
+               {
+               draw_section($cr, $_);
+               }
+
+       $cr->tag_end("Document");
+       }
+
+
+my $surface = Cairo::PdfSurface->create(FILENAME, PAGE_WIDTH, PAGE_HEIGHT);
+
+my $cr = Cairo::Context->create($surface);
+create_document($surface, $cr);
+
+my $status = $cr->status();
+$cr = undef;
+$surface->finish();
+my $status2 = $surface->status();
+if ($status ne 'success')
+       {
+       $status = $status2;
+       }
+
+$surface = undef;
+if ($status ne 'success')
+       {
+       say "Failed to create pdf surface: $status";
+       die;
+       }
+
+0;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]