You are viewing a plain text version of this content. The canonical link for it is here.
Posted to axkit-dev@xml.apache.org by ma...@apache.org on 2002/03/22 00:24:00 UTC
cvs commit: xml-axkit/lib/Apache/AxKit/Language AxPoint.pm
matts 02/03/21 15:23:59
Modified: lib/Apache/AxKit/Language AxPoint.pm
Log:
Port to XML::Handler::AxPoint (ok now I'm really going to bed!)
Revision Changes Path
1.3 +45 -513 xml-axkit/lib/Apache/AxKit/Language/AxPoint.pm
Index: AxPoint.pm
===================================================================
RCS file: /home/cvs/xml-axkit/lib/Apache/AxKit/Language/AxPoint.pm,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- AxPoint.pm 21 Feb 2002 19:54:10 -0000 1.2
+++ AxPoint.pm 21 Mar 2002 23:23:59 -0000 1.3
@@ -1,4 +1,4 @@
-# $Id: AxPoint.pm,v 1.2 2002/02/21 19:54:10 matts Exp $
+# $Id: AxPoint.pm,v 1.3 2002/03/21 23:23:59 matts Exp $
package Apache::AxKit::Language::AxPoint;
@@ -7,12 +7,10 @@
use strict;
use Apache;
+use Apache::Constants qw(OK);
use Apache::Request;
-use Apache::AxKit::Language;
-use Apache::AxKit::Provider;
-use PDFLib 0.02;
-use XML::XPath;
-use File::Basename ();
+use XML::SAX;
+use XML::Handler::AxPoint;
my @xindent;
@@ -22,153 +20,25 @@
my $class = shift;
my ($r, $xml_provider, undef, $last_in_chain) = @_;
- my $xpath = XML::XPath->new();
+ my $output_handler = Apache::AxKit::Language::AxPoint::Output->new($r);
- my $source_tree;
-
- my $xml_parser = XML::Parser->new(
- ErrorContext => 2,
- Namespaces => $XML::XPath::VERSION < 1.07 ? 1 : 0,
- ParseParamEnt => 1,
- );
-
- my $parser = XML::XPath::XMLParser->new(parser => $xml_parser);
-
- if (my $entity_handler = $xml_provider->get_ext_ent_handler()) {
- $xml_parser->setHandlers(
- ExternEnt => $entity_handler,
- );
- }
-
- AxKit::Debug(6, "AxPoint: Getting XML Source");
-
- if (my $dom = $r->pnotes('dom_tree')) {
- # dom_tree is an XML::XPath DOM
- $source_tree = $dom;
- delete $r->pnotes()->{'dom_tree'};
- }
- elsif (my $xml = $r->pnotes('xml_string')) {
- eval {
- $source_tree = $parser->parse($xml);
- };
- if ($@) {
- throw Apache::AxKit::Exception::Error(-text => "Parse of xml_string failed: $@");
- }
- }
- else {
- $source_tree = get_source_tree($xml_provider, $parser);
- }
-
- $xpath->set_context($source_tree);
-
- AxKit::Debug(7, "AxPoint: creating pdf");
-
- my $pdf = PDFLib->new();
- $pdf->papersize("slides");
- $pdf->set_border_style("solid", 0);
-
- $pdf->info(Title => $xpath->findvalue("/slideshow/title"));
- $pdf->info(Creator => $xpath->findvalue("/slideshow/metadata/speaker"));
-
- my ($logo_node) = $xpath->findnodes("/slideshow/metadata/logo");
- my ($bg_node) = $xpath->findnodes("/slideshow/metadata/background");
+ my $parser = XML::SAX::ParserFactory->parser(
+ Handler =>
+ XML::Handler::AxPoint->new(
+ Output => $output_handler,
+ PrintMode => 1,
+ )
+ );
- AxKit::Debug(7, "AxPoint: loading main bg/logo images");
-
- my ($logo, $bg);
- if ($logo_node) {
- $logo = $pdf->load_image(
- filename => $logo_node->string_value,
- filetype => get_filetype($logo_node->string_value),
- );
- if (!$logo) {
- AxKit::Debug(7, "AxPoint: failed to load logo " . $logo_node->string_value);
- $pdf->finish;
- die "Cannot load image $logo_node!";
- }
- }
-
- if ($bg_node) {
- $bg = $pdf->load_image(
- filename => $bg_node->string_value,
- filetype => get_filetype($bg_node->string_value),
- );
- if (!$bg) {
- AxKit::Debug(7, "AxPoint: failed to load logo " . $bg_node->string_value);
- $pdf->finish;
- die "Cannot load image $bg_node!";
- }
- }
-
- AxKit::Debug(7, "AxPoint: Creating new_page sub");
-
- my $new_page = sub {
- my ($node, $trans) = @_;
-
- $pdf->start_page;
-
- my $transition = $trans || $node->findvalue('ancestor-or-self::*/@transition') || 'replace';
-
- $pdf->set_parameter("transition", lc($transition)) if $transition;
-
- $pdf->add_image(img => $bg, x => 0, y => 0, scale => $bg_node->findvalue('@scale') || 1.0)
- if $bg_node;
-
- if ($logo_node) {
- my $logo_scale = $logo_node->findvalue('@scale') || 1.0;
- my $logo_w = $logo->width * $logo_scale;
- $pdf->add_image(img => $logo, x => 612 - $logo_w, y => 0, scale => $logo_scale);
- }
-
- $pdf->set_font(face => "Helvetica", size => 18.0);
-
- @xindent = ();
-
- $pdf->set_text_pos(80, 300);
+ eval {
+ my $fh = $xml_provider->get_fh();
+ $parser->parse_fh($fh,
+ { Source => { SystemId => $xml_provider->key } });
};
-
- AxKit::Debug(7, "AxPoint: creating front page");
- # title page
- $new_page->($xpath->findnodes('/')->get_node(1));
-
- $pdf->set_font(face => "Helvetica-Bold", size => 24);
-
- my $root_bookmark = $pdf->add_bookmark(text => "Title", open => 1);
-
- $pdf->print_boxed($xpath->findvalue("/slideshow/title"),
- x => 20, y => 50, w => 570, h => 300, mode => "center");
-
- $pdf->print_line("");
- $pdf->print_line("");
- $pdf->print_line("");
- $pdf->print_line("");
-
- my ($x, $y) = $pdf->get_text_pos();
-
- $pdf->set_font(face => "Helvetica-Bold", size => 20);
-
- $pdf->add_link(link => "mailto:" . $xpath->findvalue("/slideshow/metadata/email"),
- x => 20, y => $y - 10, w => 570, h => 24);
- $pdf->print_boxed($xpath->findvalue("/slideshow/metadata/speaker"),
- x => 20, y => 40, w => 570, h => $y - 24, mode => "center");
-
- $pdf->print_line("");
- (undef, $y) = $pdf->get_text_pos();
-
- $pdf->add_link(link => $xpath->findvalue("/slideshow/metadata/link"),
- x => 20, y => $y - 10, w => 570, h => 24);
- $pdf->print_boxed($xpath->findvalue("/slideshow/metadata/organisation"),
- x => 20, y => 40, w => 570, h => $y - 24, mode => "center");
-
- AxKit::Debug(7, "AxPoint: creating slides");
-
- foreach my $slideset ($xpath->findnodes("/slideshow/*[name() = 'slideset' or name() = 'slide']")) {
- if ($slideset->getName() eq 'slide') {
- process_slide($pdf, $new_page, $slideset, $root_bookmark);
- }
- else {
- process_slideset($pdf, $new_page, $slideset, $root_bookmark);
- }
+ if ($@) {
+ my $str = $xml_provider->get_strref();
+ $parser->parse_string($$str,
+ { Source => { SystemId => $xml_provider->key } });
}
AxKit::Debug(7, "AxPoint: outputting pdf");
@@ -177,273 +47,26 @@
$r->content_type("application/pdf");
- AxKit::Debug(5, "finish pdf");
-
- $pdf->finish;
-
- $r->print( $pdf->get_buffer );
-}
-
-sub process_slideset {
- my ($pdf, $new_page, $slideset, $parent_bookmark) = @_;
- $new_page->($slideset);
-
- my $slide_bookmark = $pdf->add_bookmark(
- text => $slideset->findvalue("title"),
- level => 2,
- parent_of => $parent_bookmark,
- open => 1,
- );
-
- $pdf->set_font(face => "Helvetica", size => 24);
- $pdf->print_boxed($slideset->findvalue("title"),
- x => 20, y => 50, w => 570, h => 200, mode => "center");
-
- my ($x, $y) = $pdf->get_text_pos();
- $pdf->add_link(link => $slideset->findvalue('title/@href'),
- x => 20, y => $y - 5, w => 570, h => 24) if $slideset->findvalue('title/@href');
-
- if (my $subtitle = $slideset->findvalue("subtitle")) {
- $pdf->set_font(face => "Helvetica", size => 18);
- $pdf->print_boxed($subtitle,
- x => 20, y => 20, w => 570, h => 200, mode => "center");
- if (my $href = $slideset->findvalue('subtitle/@href')) {
- ($x, $y) = $pdf->get_text_pos();
- $pdf->add_link(link => $href,
- x => 20, y => $y - 5, w => 570, h => 18);
- }
- }
-
- foreach my $slide ($slideset->findnodes("slide")) {
- process_slide($pdf, $new_page, $slide, $slide_bookmark);
- }
-}
-
-sub process_slide {
- my ($pdf, $new_page, $slide, $parent_bookmark, $do_up_to) = @_;
-
- $pdf->end_page;
- my @images;
- foreach my $image ($slide->findnodes("image")) {
- push @images, $pdf->load_image(
- filename => $image->string_value,
- filetype => get_filetype($image->string_value),
- );
- }
-
- if ($do_up_to) {
- my @nodes = $slide->findnodes("point|source_code|image");
- my $do_to_node = $nodes[$do_up_to - 1];
- $new_page->($slide, $do_to_node->findvalue('@transition'));
- }
- else {
- $new_page->($slide);
- }
-
- my $h = 300;
- if (my $title = $slide->findvalue("title")) {
- $pdf->add_bookmark(text => $title, level => 3, parent_of => $parent_bookmark) unless $do_up_to;
- $pdf->set_font(face => "Helvetica", size => 24);
- $pdf->print_boxed($title, x => 20, y => 350,
- w => 570, h => 70, mode => "center");
-
- my ($x, $y) = $pdf->get_text_pos();
- $pdf->add_link(link => $slide->findvalue('title/@href'),
- x => 20, y => $y - 5, w => 570, h => 24) if $slide->findvalue('title/@href');
-
- $h = 370;
- }
-
- $pdf->set_text_pos(60, $h);
-
- my $new_do_up_to = 1;
- foreach my $item ($slide->findnodes("point|source_code|image")) {
- if (!$do_up_to && $item->findvalue('@transition')) {
- process_slide($pdf, $new_page, $slide, $parent_bookmark, $new_do_up_to);
- }
-
- if ($do_up_to) {
- last if $do_up_to == $new_do_up_to;
- }
-
- if ($item->getName eq "point") {
- point($pdf, $item->findvalue('@level') || 1, $item->string_value, $item->findvalue('@href'));
- }
- elsif ($item->getName eq 'source_code') {
- source_code($pdf, $item->string_value, $item->getAttribute('fontsize'));
- }
- elsif ($item->getName eq 'image') {
- image($pdf, $item->getAttribute('scale') || 1, shift @images, $item->findvalue('@href'));
- }
-
- $new_do_up_to++;
- }
-
-}
-
-###########################################################
-# functions
-###########################################################
-
-sub new_page {
- my ($pdf, $node, $logo, $bg) = @_;
-
- $pdf->start_page;
-
- my $transition = $node->findvalue('ancestor-or-self::node()/@transition');
-
- $pdf->set_parameter("transition", lc($transition)) if $transition;
-
- $pdf->add_image(img => $bg, x => 0, y => 0, scale => 1.0);
-
- $pdf->add_image(img => $logo, x => 420, y => 0, scale => 0.4);
-
- $pdf->set_font(face => "Helvetica", size => 18.0);
-
- @xindent = ();
-
- $pdf->set_text_pos(80, 300);
-
-}
-
-sub bullet {
- my ($pdf, $level) = @_;
-
- my ($char, $size);
- if ($level == 1) {
- $char = "l";
- $size = 18;
- }
- elsif ($level == 2) {
- $char = "u";
- $size = 16;
- }
- elsif ($level == 3) {
- $char = "p";
- $size = 14;
- }
-
- my $leading = $pdf->get_value("leading");
- $pdf->set_value("leading", $leading + 4);
- $pdf->set_value("leading", $leading + 20) if $level == 1;
-
- $pdf->print_line("");
-
- my ($x, $y) = $pdf->get_text_pos;
-
- if (!@xindent || $level > $xindent[0]{level}) {
- unshift @xindent, {level => $level, x => $x};
- }
-
- $pdf->set_font(face => "ZapfDingbats", size => $size - 4, encoding => "builtin");
- $pdf->print($char);
- $pdf->set_font(face => "Helvetica", size => $size);
- $pdf->print(" ");
- return $size;
-}
-
-sub point {
- my ($pdf, $level, $text, $href) = @_;
-
- my ($x, $y) = $pdf->get_text_pos;
-
- if (@xindent && $level <= $xindent[0]{level}) {
- my $last;
- while ($last = shift @xindent) {
- if ($last->{level} == $level) {
- $pdf->set_text_pos($last->{x}, $y);
- $x = $last->{x};
- last;
- }
- }
- }
-
- if ($level == 1) {
- $pdf->set_text_pos(80, $y);
- }
-
- my $size = bullet($pdf, $level);
-
- ($x, $y) = $pdf->get_text_pos;
-
- $pdf->print_boxed($text, x => $x, y => 0, w => 570 - $x, h => $y + $size);
- $pdf->add_link(link => $href,
- x => 20, y => $y - 5 + $level, w => 570, h => $size) if $href;
+ AxKit::Debug(5, "AxPoint: done");
+ return OK;
}
-sub source_code {
- my ($pdf, $text, $size) = @_;
-
- my ($x, $y) = $pdf->get_text_pos;
-
- $pdf->set_font(face => "Courier", size => $size || 14);
-
- $y -= 10 if @xindent;
-
- $pdf->print_boxed($text, x => 80, y => 0, w => 500, h => $y);
-
-}
-
-sub image {
- my ($pdf, $scale, $file_handle, $href) = @_;
-
- $pdf->print_line("");
-
- my ($x, $y) = $pdf->get_text_pos;
-
- my ($imgw, $imgh) = (
- $pdf->get_value("imagewidth", $file_handle->img),
- $pdf->get_value("imageheight", $file_handle->img)
- );
-
- $imgw *= $scale;
- $imgh *= $scale;
-
- $pdf->add_image(img => $file_handle,
- x => (612 / 2) - ($imgw / 2),
- y => ($y - $imgh),
- scale => $scale);
- $pdf->add_link(link => $href, x => 20, y => $y - $imgh, w => 570, h => $imgh) if $href;
-
- $pdf->set_text_pos($x, $y - $imgh);
-}
+package Apache::AxKit::Language::AxPoint::Output;
+use XML::SAX::Writer;
+use vars qw(@ISA);
+@ISA = ('XML::SAX::Writer::ConsumerInterface');
-sub get_filetype {
- my $filename = shift;
-
- AxKit::Debug(8, "AxPoint: get_filetype($filename)");
-
- my ($suffix) = $filename =~ /([^\.]+)$/;
- $suffix = lc($suffix);
- if ($suffix eq 'jpg') {
- return 'jpeg';
- }
- return $suffix;
+sub new {
+ my $class = shift;
+ my ($r) = @_;
+ return bless { apache => $r }, $class;
}
-sub get_source_tree {
- my ($provider, $parser) = @_;
- my $source_tree;
- AxKit::Debug(7, "AxPoint: reparsing file");
- eval {
- my $fh = $provider->get_fh();
- # warn("parsing FH $fh with parser $parser\n");
- local $/;
- my $contents = <$fh>;
- # warn("FH contains: $contents\n");
- $source_tree = $parser->parse($contents);
- # warn("Parse completed\n");
- close($fh);
- };
- if ($@) {
- # warn("parse_fh failed\n");
- $source_tree = $parser->parse(${ $provider->get_strref() });
- }
-
- # warn("get_source_tree = $source_tree\n");
- AxKit::Debug(7, "AxPoint: returning source tree");
- return $source_tree;
+sub output {
+ my $self = shift;
+ my ($data) = @_;
+ $self->{apache}->print($data);
}
1;
@@ -462,108 +85,17 @@
=head1 DESCRIPTION
-I got sick of not being able to do pretty slideshows about AxKit without
-resorting to the bloated OpenOffice. So I decided to write something that
-allows you to do simple slideshows with bullet points and a few other
-niceties using XML, AxKit, and rendering to PDF.
-
-I discovered that PDF can do transitions, and full screen mode (even on Linux),
-and so it makes the perfect medium for doing a slideshow.
-
-Note: This module requires PDFLib.pm from CPAN. It also requires the library
-B<pdflib>, which is available under the Alladin license from
-http://www.pdflib.com/. The Alladin license does not allow re-distribution
-of modified binaries, so it is not strictly open source, but it is free to
-use even for commercial use.
-
-=head1 Usage
-
-The SYNOPSIS section describes how to set this thing up in AxKit, so here I
-will focus on the syntax of AxPoint XML files. I tend to use the suffix ".axp"
-for my AxPoint files, but you are free to use whatever you please.
-
-The easiest way to describe all the features is with a complete presentation
-first:
-
- <slideshow transition="glitter">
- <title>AxPoint Example</title>
- <metadata>
- <speaker>Matt Sergeant</speaker>
- <email>matt@axkit.com</email>
- <organisation>AxKit.com Ltd</organisation>
- <link>http://axkit.com/</link>
- <logo>ax_logo.png</logo>
- <background>bg.png</background>
- </metadata>
-
- <slide transition="dissolve">
- <title>Top Level Slide</title>
- <point>This is a top level slide</point>
- <point>It is a child of the <slideshow> tag</point>
- <point>Can have it's own transition</point>
- </slide>
-
- <slideset transition="blinds">
- <title>Slidesets</title>
- <subtitle>Slidesets can have subtitles</subtitle>
-
- <slide>
- <title>Slideset Example</title>
- <point>A slideset groups slides under a particular title</point>
- <point>Slidesets can have a transition for the group of slides</point>
- </slide>
- </slideset>
-
- <slideset>
- <title>Slide Tags</title>
-
- <slide>
- <title>Bullet Points</title>
- <point>Level 1 bullet : <point></point>
- <point level="1">Another Level 1 bullet : <point level="1"></point>
- <point level="2">Level 2 bullet : <point level="2"></point>
- <point level="3">Level 3 bullet : <point level="3"></point>
- <point>Back to level 1</point>
- </slide>
-
- <slide>
- <title>Source Core</title>
- <source_code><![CDATA[
-Source code
-uses fixed font
-Don't forget to use CDATA sections so you can
- <include/><some/><xml/>
- ]]></source_code>
- </slide>
-
- <slide>
- <title>Pictures</title>
- <point>Images are very simple, and always centered</point>
- <image scale="0.5" href="file_large.jpg">file.jpg</image>
- </slide>
-
- </slideset>
-
- <slideset transition="dissolve">
- <title href="http://foo.bar/aslidesettitle">Slideset titles can have href attributes</title>
- <subtitle href="http://foo.bar/aslidesetsubtitle">Slideset subtitles too</subtitle>
-
- <slide>
- <title href="http://foo.bar/aslidetitle">Don't forget links for slide titles</title>
- <point href="http://foo.bar/apoint">...and for points of various levels</point>
- </slide>
- </slideset>
-
-
- </slideshow>
-
-
-It's not very complex. And with good reason: generating PDFs can be slow. With this simple schema
-we can generate a 100 slide PDF in about 1 second. There are many deficiencies with the tagset,
-most significantly that no bold or italics or any coloring can be applied to the text by using
-tags. The reason being that this is quite hard to do with PDFLib - you have to do text measurement
-yourself and do the word-wrapping yourself, and so on. The way it is setup right now is very
-simple to use and implement.
+AxPoint allows you to create slideshows or presentations using an XML
+definition of the slideshow. The full documentation is in
+L<XML::Handler::AxPoint>.
+
+AxPoint when processed via AxKit defaults to producing the slides in
+"Print mode" - this removes all transitions from the slides. If you
+want to get a version with transitions it is recommended to use the
+command line tools shipped with XML::Handler::AxPoint. The reason for
+this decision is because the browser-embedded version of Adobe Acrobat
+does not seem to go full screen very well, if at all, so it is pretty
+much useless for giving live presentations over the web.
=head1 AUTHOR