Subject: | weird usage of parameterized class |
This seemed pretty cool so I had a look and noticed you were using a parameterized class a little strangely.
Like there shouldn't be any need to grab the spec and manually fiddle with it. I thought perhaps you were working around a limitation in MooX::Pression, so I tried reworking it to see if there was any way I could add a feature to make this kind of thing easier, but I can't find any such limitation.
Attached is a patch that moves the processing of @plugins into the parameterized class itself. I've run the test suite and it appears to produce a visually similar PDF, but other than that I haven't verified it performs as expected because I'm not 100% sure on what the $p method is SUPPOSED to do.
If I'm misunderstanding what you were doing with the File class generator, please do clarify. I've not used class generators much, so it would be interesting to explore more about how they could be used, and ensure MooX::Pression can cover these use cases without needing to hack the hashrefs being passed around.
Subject: | mxpress-pdf.patch |
diff -urN Mxpress-PDF-0.02/lib/Mxpress/PDF.pm Mxpress-PDF-0.02-hacked/lib/Mxpress/PDF.pm
--- Mxpress-PDF-0.02/lib/Mxpress/PDF.pm 2020-02-11 15:27:59.000000000 +0000
+++ Mxpress-PDF-0.02-hacked/lib/Mxpress/PDF.pm 2020-02-11 17:53:13.707890888 +0000
@@ -5,19 +5,32 @@
package Mxpress::PDF {
our $VERSION = '0.02';
use MooX::Pression (
- version => '0.02',
+ version => '0.02',
authority => 'cpan:LNATION',
);
use Colouring::In;
use constant mm => 25.4 / 72;
use constant pt => 1;
- class File () {
+ class File (HashRef $args) {
+ my @plugins = (qw/font boxed text title subtitle subsubtitle toc/, ($args->{plugins} ? @{$args->{plugins}} : ()));
+ for my $p (@plugins) {
+ my $meth = sprintf('_store_%s', $p);
+ has {$meth} ( type => Object );
+ method {$p} () {
+ my $klass = $self->$meth;
+ if (!$klass) {
+ $klass = $class->FACTORY->$p($self, %{$args->{$p}});
+ $self->$meth($klass);
+ }
+ return $klass;
+ }
+ }
has file_name (type => Str, required => 1);
has pdf (required => 1, type => Object);
has pages (required => 1, type => ArrayRef);
has page (type => Object);
has page_args (type => HashRef);
- has onsave_cbs (type => ArrayRef);
+ has onsave_cbs (type => ArrayRef);
method add_page (Map %args) {
my $page = $self->FACTORY->page(
$self->pdf,
@@ -29,7 +42,7 @@
push @{$self->pages}, $page;
$self->page($page);
$self->boxed->add( fill_colour => $page->background ) if $page->background;
- $self->page->set_position($page->parse_position([]));
+ $self->page->set_position($page->parse_position([]));
$self;
}
method save {
@@ -60,7 +73,7 @@
has w (type => Num);
has h (type => Num);
factory page (Object $pdf, Map %args) {
- my $page = $args{open} ? $pdf->openpage($args{num}) : $pdf->page($args{num});
+ my $page = $args{open} ? $pdf->openpage($args{num}) : $pdf->page($args{num});
$page->mediabox($args{page_size});
my ($blx, $bly, $trx, $try) = $page->get_mediabox;
my $new_page = $class->new(
@@ -252,7 +265,7 @@
while (@paragraph and ($line_width + (scalar(@line) * $space_width) + $width{$paragraph[0]}) < $lw) {
$line_width += $width{$paragraph[0]};
push @line, shift(@paragraph);
- }
+ }
my ($wordspace, $align);
if ($self->align eq 'fulljustify' or $self->align eq 'justify' and @paragraph) {
if (scalar(@line) == 1) {
@@ -286,7 +299,7 @@
my $pad_end = $self->pad_end;
my $pad = sprintf ("%s%s",
$self->pad x int(((
- (((($lw + $wordspace) - $line_width) - $text->advancewidth($self->pad . $pad_end)) - ($self->padding/mm))
+ (((($lw + $wordspace) - $line_width) - $text->advancewidth($self->pad . $pad_end)) - ($self->padding/mm))
) / $text->advancewidth($self->pad))),
$pad_end
);
@@ -305,7 +318,7 @@
return $self->file;
}
method _set_indent (Num $xpos, Num $w, Num $fl, Num $fp) {
- if ($fl && $self->first_line_indent) {
+ if ($fl && $self->first_line_indent) {
$xpos += $self->first_line_indent/mm;
$w -= $self->first_line_indent/mm;
} elsif ($fp && $self->first_paragraph_indent) {
@@ -376,7 +389,7 @@
y => $y,
children => [],
level => $args{level} || 0,
- title => $args{title},
+ title => $args{title},
file => $file,
page => $file->page,
outline => $new,
@@ -439,7 +452,7 @@
$self->file->subtitle->add($args{title} ? @{$args{title}} : 'Table of contents');
$self->toc_placeholder({
page => $self->file->page,
- position => [$self->parse_position($args{position} || [])]
+ position => [$self->parse_position($args{position} || [])]
});
$self->file->onsave('toc', 'render', %args);
$self->file->add_page;
@@ -483,7 +496,7 @@
my $total_height = ($self->count * $one_toc_link) - $h;
while ($total_height > 0) {
$args{page_offset}++;
- $self->file->add_page(num => $placeholder->{page}->num + $args{page_offset});
+ $self->file->add_page(num => $placeholder->{page}->num + $args{page_offset});
$total_height -= $self->file->page->h;
}
$self->file->page($placeholder->{page});
@@ -494,36 +507,9 @@
}
}
class Factory {
- use PDF::API2;
factory new_pdf (Str $name, Map %args) {
- my @plugins = (qw/font boxed text title subtitle subsubtitle toc/, ($args{plugins} ? @{$args{plugins}} : ()));
- my $spec = Mxpress::PDF::File->_generate_package_spec();
- for my $p (@plugins) {
- my $meth = sprintf('_store_%s', $p);
- $spec->{has}->{$meth} = { type => Object };
- $spec->{can}->{$p} = {
- code => sub {
- my $class = $_[0]->$meth;
- if (!$class) {
- $class = $factory->$p($_[0], %{$args{$p}});
- $_[0]->$meth($class)
- }
- return $class;
- }
- };
- }
- return MooX::Press->generate_package(
- 'class',
- "Mxpress::PDF::File",
- {
- factory_package => $factory,
- caller => $class,
- prefix => $factory,
- toolkit => 'Moo',
- type_library => 'Mxpress::PDF::Types',
- },
- $spec
- )->new(
+ require PDF::API2;
+ $factory->generate_file( \%args )->new(
file_name => $name,
pages => [],
num => 0,
Binary files Mxpress-PDF-0.02/test.pdf and Mxpress-PDF-0.02-hacked/test.pdf differ