App-Music-ChordPro

 view release on metacpan or  search on metacpan

lib/ChordPro/Output/PDF/Song.pm  view on Meta::CPAN

	      "\n") if $config->{debug}->{spacing};
	$x += $ps->{_indent};
	$y -= $spreadimage if defined($spreadimage) && !ref($spreadimage);
	# Prevent spread space on other pages (issue #640).
	undef $spreadimage if $col == $ps->{columns}-1;
    };

    my $vsp_ignorefirst;
    my $startpage = $opts->{page_num};
    # These are 1 smaller since they'll be incremented first.
    my $page_num = $startpage - 1; # page number
    my $page_idx = $opts->{page_idx}-1; # page # in PDF

    # Physical newpage handler.
    my $newpage = sub {
	$page_idx++;
	$page_num++;
	$s->{meta}->{page} =
	  [ $s->{page} = $opts->{roman}
	                 ? roman($page_num) : $page_num ];

	# Add page to the PDF.
	$pr->newpage( $opts->{prepend} ? $page_idx : () );
	warn("page: $page_idx(",$s->{page},") added\n")
	  if $config->{debug}->{pages} & 0x01;

	# Put titles and footer.

	# If even/odd pages, leftpage signals whether the
	# header/footer parts must be swapped.
	my $rightpage = 1;
	if ( $pagectrl->{dual_pages} ) {
	    $rightpage = is_odd($page_num);
	}

	# margin* are offsets from the edges of the paper.
	# _*margin are offsets taking even/odd pages into account.
	# _margin* are physical coordinates, taking ...
	if ( $rightpage ) {
	    $ps->{_leftmargin}  = $ps->{marginleft};
	    $ps->{_marginleft}  = $ps->{marginleft};
	    $ps->{_rightmargin} = $ps->{marginright};
	    $ps->{_marginright} = $ps->{papersize}->[0] - $ps->{marginright};
	}
	else {
	    $ps->{_leftmargin}  = $ps->{marginright};
	    $ps->{_marginleft}  = $ps->{marginright};
	    $ps->{_rightmargin} = $ps->{marginleft};
	    $ps->{_marginright} = $ps->{papersize}->[0] - $ps->{marginleft};
	}
	$ps->{_marginbottom}  = $ps->{marginbottom};
	$ps->{_margintop}     = $ps->{papersize}->[1] - $ps->{margintop};
	$ps->{_bottommargin}  = $ps->{marginbottom};

	# Physical coordinates; will be adjusted to columns if needed.
	$ps->{__leftmargin}   = $ps->{_marginleft};
	$ps->{__rightmargin}  = $ps->{_marginright};
	$ps->{__topmargin}    = $ps->{_margintop};
	$ps->{__bottommargin} = $ps->{_marginbottom};

	# Determine page class and background.
	my $class = 2;		# default
	my $bgpdf = $ps->{formats}->{default}->{background};
	if ( $page_num == 1 ) {
	    $class = 0;		# very first page
	    $bgpdf = $ps->{formats}->{first}->{background}
	      || $ps->{formats}->{title}->{background}
	      || $bgpdf;
	}
	elsif ( $page_num == $startpage ) {
	    $class = 1;		# first of a song
	    $bgpdf = $ps->{formats}->{title}->{background}
	      || $bgpdf;
	}
	if ( $bgpdf ) {
	    my ( $fn, $pg ) = ( $bgpdf, 1 );
	    if ( $bgpdf =~ /^(.+):(\d+)$/ ) {
		( $bgpdf, $pg ) = ( $1, $2 );
	    }
	    $fn = CP->findres($bgpdf);
	    if ( $fn && fs_test( rs => $fn ) ) {
		$pg++ if $pagectrl->{dual_pages} && !$rightpage;
		$pr->importpage( $fn, $pg );
	    }
	    else {
		warn( "PDF: Missing or empty background document: ",
		      $bgpdf, "\n" );
	    }
	}

	$x = $ps->{__leftmargin};
	$y = $ps->{_margintop};
	$y += $ps->{headspace} if $ps->{'head-first-only'} && $class == 2;
	$x += $ps->{_indent};
	$ps->{_top} = $y;
	$col = 0;
	$vsp_ignorefirst = 1;
	$col_adjust->();

	# Render the 'allpages' images.
	for ( @allpages ) {
	    my %imageinfo = %$_;
	    my $img = delete $imageinfo{img};
	    my $x   = delete $imageinfo{x};
	    my $y   = delete $imageinfo{y};
	    $pr->add_object( $img, $x, $y, %imageinfo );
	}
    };

    my $checkspace = sub {

	# Verify that the amount of space if still available.
	# If not, perform a column break or page break.
	# Use negative argument to force a break.
	# Returns true if there was space.

	my $vsp = $_[0];
	return 1 if $vsp >= 0 && $y - $vsp >= $ps->{_bottommargin};

	if ( ++$col >= $ps->{columns}) {
	    $newpage->();
	    $vsp_ignorefirst = 0;
	}
	$col_adjust->();
	return;
    };

    my $chorddiagrams = sub {
	my ( $chords, $show, $ldisp ) = @_;
	return if $lyrics_only || !$dctl->{show};
	my @chords;
	$chords = $s->{chords}->{chords}
	  if !defined($chords) && $s->{chords};
	$show //= $dctl->{show};
	if ( $chords ) {
	    for ( @$chords ) {
		if ( my $i = $s->{chordsinfo}->{$_} ) {
		    push( @chords, $i ) if $i->has_diagram;
		}
		else {
		    warn("PDF: Missing chord info for \"$_\"\n");
		}
	    }
	}
	return unless @chords;

lib/ChordPro/Output/PDF/Song.pm  view on Meta::CPAN

		$ftext = $fonts->{tab};
	    }

	    # Get vertical space the songline will occupy.
	    my $vsp = songline_vsp( $elt, $ps );
	    if ( $elt->{type} eq "songline" && !$elt->{indent} ) {
		my $e = wrap( $pr, $elt, $x );
		if ( @$e > 1 ) {
		    $checkspace->($vsp * scalar( @$e ));
		    $elt = shift( @$e );
		    unshift( @elts, @$e );
		}
	    }

	    # Add prespace if fit. Otherwise newpage.
	    $checkspace->($vsp);

	    $pr->show_vpos( $y, 0 ) if $config->{debug}->{spacing};

	    my $indent = 0;

	    # Handle decorations.

	    if ( $elt->{context} eq "chorus" ) {
		my $style = $ps->{chorus};
		$indent = $style->{indent};
		if ( $style->{bar}->{offset} && $style->{bar}->{width} ) {
		    my $cx = $ps->{__leftmargin} + $ps->{_indent}
		      - $style->{bar}->{offset}
			+ $indent;
		    $pr->vline( $cx, $y, $vsp,
				$style->{bar}->{width},
				$style->{bar}->{color} );
		}
		$curctx = "chorus";
		$i_tag = "" unless $config->{settings}->{choruslabels};
	    }

	    # Substitute metadata in comments.
	    if ( $elt->{type} =~ /^comment/ && !$elt->{indent} ) {
		$elt = { %$elt };
		# Flatten chords/phrases.
		if ( $elt->{chords} ) {
		    $elt->{text} = "";
		    for ( 0..$#{ $elt->{chords} } ) {
			$elt->{text} .= $elt->{chords}->[$_] . $elt->{phrases}->[$_];
		    }
		}
		$elt->{text} = fmt_subst( $s, $elt->{text} );
	    }

	    # Comment decorations.

	    $pr->setfont( $ftext );

=begin xxx

	    my $text = $elt->{text};
	    my $w = $pr->strwidth( $text );

	    # Draw background.
	    my $bgcol = $ftext->{background};
	    if ( $elt->{type} eq "comment" ) {
		# Default to grey.
		$bgcol ||= "#E5E5E5";
		# Since we default to grey, we need a way to cancel it.
		undef $bgcol if $bgcol eq "none";
	    }
	    if ( $bgcol ) {
		$pr->rectxy( $x + $indent - 2, $y + 2,
			     $x + $indent + $w + 2, $y - $vsp, 3, $bgcol );
	    }

	    # Draw box.
	    my $x0 = $x;
	    if ( $elt->{type} eq "comment_box" ) {
		$x0 += 0.25;	# add some offset for the box
		$pr->rectxy( $x0 + $indent, $y + 1,
			     $x0 + $indent + $w + 1, $y - $vsp + 1,
			     0.5, undef,
			     $ftext->{color} || $ps->{theme}->{foreground} );
	    }

=cut

	    my $r = songline( $elt, $x, $y, $ps, song => $s, indent => $indent );

	    $y -= $vsp;
	    $pr->show_vpos( $y, 1 ) if $config->{debug}->{spacing};

	    unshift( @elts, $r ) if $r;
	    next;
	}

	if ( $elt->{type} eq "chorus" ) {
	    warn("NYI: type => chorus\n");
	    my $cy = $y + vsp($ps,-2); # ####TODO????
	    foreach my $e ( @{$elt->{body}} ) {
		if ( $e->{type} eq "songline" ) {
		    $y = songline( $e, $x, $y, $ps );
		    next;
		}
		elsif ( $e->{type} eq "empty" ) {
		    warn("***SHOULD NOT HAPPEN2***");
		    $y -= vsp($ps);
		    next;
		}
	    }
	    my $style = $ps->{chorus};
	    my $cx = $ps->{__leftmargin} - $style->{bar}->{offset};
	    $pr->vline( $cx, $cy, vsp($ps), 1, $style->{bar}->{color} );
	    $y -= vsp($ps,4); # chordii
	    next;
	}

	if ( $elt->{type} eq "verse" ) {
	    warn("NYI: type => verse\n");
	    foreach my $e ( @{$elt->{body}} ) {
		if ( $e->{type} eq "songline" ) {
		    my $h = songline_vsp( $e, $ps );
		    $checkspace->($h);
		    songline( $e, $x, $y, $ps );



( run in 0.751 second using v1.01-cache-2.11-cpan-f56aa216473 )