File Coverage

lib/ChordPro/lib/SVGPDF/Svg.pm
Criterion Covered Total %
statement 11 98 11.2
branch 0 42 0.0
condition 0 28 0.0
subroutine 4 7 57.1
pod 0 3 0.0
total 15 178 8.4


line stmt bran cond sub pod time code
1             #! perl
2              
3 1     1   12 use v5.26;
  1         5  
4 1     1   6 use Object::Pad;
  1         2  
  1         6  
5 1     1   112 use utf8;
  1         2  
  1         6  
6 1     1   25 use Carp;
  1         2  
  1         120  
7              
8             class SVGPDF::Svg :isa(SVGPDF::Element);
9              
10 0     0 0   method process () {
  0            
  0            
11 0           my $atts = $self->atts;
12 0 0         return if $atts->{omit}; # for testing/debugging.
13              
14 0           my $xo = $self->xo;
15 0           my $xoforms = $self->root->xoforms;
16              
17 0           delete $atts->{$_} for qw( xmlns:xlink xmlns:svg xmlns version );
18 0           my ( $x, $y, $vwidth, $vheight, $vbox, $par, $tf ) =
19             $self->get_params( $atts, qw( x:U y:U width:s height:s viewBox preserveAspectRatio:s transform:s ) );
20 0 0         $self->nfi("nested svg transform") if $tf;
21 0 0         $self->nfi("preserveAspectRatio") if $par;
22 0           my $style = $self->style;
23              
24 0           my $parent;
25 0           for ( @{ $self->root->xoforms } ) {
  0            
26 0 0         next unless $_->{xo} eq $xo;
27 0           $parent = $_;
28 0           last;
29             }
30 0 0         croak("I feel like a motherless child") unless $parent;
31              
32 0           my $pwidth = $parent->{width};
33 0           my $pheight = $parent->{height};
34 0           for ( $vwidth ) {
35 0   0       $_ = $self->u( $_ || $pwidth, width => $pwidth );
36             }
37 0           for ( $vheight ) {
38 0   0       $_ = $self->u( $_ || $pheight, width => $pheight );
39             }
40              
41 0           $self->_dbg("pp w=$pwidth h=$pheight vw=$vwidth vh=$vheight");
42              
43 0           my @vb; # viewBox: llx lly width height
44             my @bb; # bbox: llx lly urx ury
45              
46 0           my $width; # width of the vbox
47 0           my $height; # height of the vbox
48 0 0         if ( $vbox ) {
49 0           @vb = $self->getargs($vbox);
50 0           $width = $self->u( $vb[2],
51             width => $pwidth );
52 0           $height = $self->u( $vb[3],
53             width => $height );
54             }
55             else {
56 0           $width = $vwidth;
57 0           $height = $vheight;
58 0           @vb = ( 0, 0, $width, $height );
59 0           $vbox = "@vb";
60             }
61              
62             # Get llx lly urx ury bounding box rectangle.
63 0           @bb = $self->root->vb2bb_noflip(@vb);
64 0           $self->_dbg( "vb $vbox => bb %.2f %.2f %.2f %.2f", @bb );
65 0 0 0       warn( sprintf("vb $vbox => bb %.2f %.2f %.2f %.2f\n", @bb ))
66             if $self->root->verbose && !$self->root->debug;
67              
68 0           my $new_xo = $self->root->pdf->xo_form;
69 0           $new_xo->bbox(@bb);
70              
71             # Set up result forms.
72 0   0       push( @$xoforms,
      0        
73             { xo => $new_xo,
74             # Design (desired) width and height.
75             vwidth => $vwidth || $vb[2],
76             vheight => $vheight || $vb[3],
77             # viewBox (SVG coordinates)
78             vbox => [ @vb ],
79             width => $vb[2],
80             height => $vb[3],
81             diag => sqrt( $vb[2]**2 + $vb[3]**2 ) / sqrt(2),
82             # bbox (PDF coordinates)
83             bbox => [ @bb ],
84             yflip => 0,
85             } );
86 0           $self->_dbg("XObject #", scalar(@$xoforms) );
87              
88 0           $self->traverse;
89              
90 0           my $scalex = 1;
91 0           my $scaley = 1;
92 0           my $dx = 0;
93 0           my $dy = 0;
94 0 0         if ( $vbox ) {
95 0           my @pbb = $xo->bbox; # parent
96 0 0         if ( $vwidth ) {
97 0           $scalex = $vwidth / $vb[2];
98             }
99 0 0         if ( $vheight ) {
100 0           $scaley = $vheight / $vb[3];
101             }
102             # warn("pbbx @pbb\n");
103             # warn("bbox @bb scale=$scalex/$scaley\n");
104 0 0         if ( $par =~ /none/i ) {
105 0           $par = "";
106             }
107             else {
108             # Uniform scale.
109             # $scalex = $scaley = min( $scalex, $scaley );
110             }
111 0 0 0       if ( $par =~ /xM(ax|id|in)/i && $scalex > $scaley ) {
112 0 0         if ( $1 eq "ax" ) {
    0          
113 0           $dx = max($pbb[0],$pbb[2]) - max($bb[0],$bb[2]);
114             }
115             elsif ( $1 eq "id" ) {
116 0           $dx = (($pbb[2]-$pbb[0])/2) - (($bb[2]-$bb[0])/2);
117             }
118             else {
119 0           $dx = min($pbb[0],$pbb[2]) - min($bb[0],$bb[2]);
120             }
121             }
122 0 0 0       if ( $par =~ /yM(in|id|ax)/i && $scaley > $scalex ) {
123 0 0         if ( $1 eq "ax" ) {
    0          
124 0           $dy = max($pbb[1],$pbb[3]) - max($bb[1],$bb[3]);
125             }
126             elsif ( $1 eq "id" ) {
127 0           $dy =
128             ((max($pbb[1],$pbb[3])-min($pbb[1],$pbb[3]))/2)
129             - ((max($bb[1],$bb[3])-min($bb[1],$bb[3]))/2)
130             }
131             else {
132 0           $dy = min($pbb[1],$pbb[3]) - min($bb[1],$bb[3]);
133             }
134             }
135 0 0         if ( $par ) {
136 0           $scalex = $scaley = min( $scalex, $scaley );
137 0           $dx *= $scalex;
138 0           $dy *= $scaley;
139 0           warn("disp dx=$dx, dy=$dy\n");
140             }
141             }
142 0   0       $self->_dbg( "xo object( %.2f%+.2f %.2f%+.2f %.3f %.3f ) %s",
143             $x, $dx, $y, $dy, $scalex, $scaley, $par//"" );
144 0 0 0       warn(sprintf("xo object( %.2f%+.2f %.2f%+.2f %.3f %.3f ) %s\n",
      0        
145             $x, $dx, $y, $dy, $scalex, $scaley, $par//"" ))
146             if $self->root->verbose && !$self->root->debug;
147 0           $xo->object( $new_xo, $x+$dx, $y+$dy, $scalex, $scaley );
148              
149 0           pop( @$xoforms );
150              
151 0           $self->css_pop;
152              
153             }
154              
155 0 0   0 0   sub min ( $x, $y ) { $x < $y ? $x : $y }
  0            
  0            
  0            
  0            
156 0 0   0 0   sub max ( $x, $y ) { $x > $y ? $x : $y }
  0            
  0            
  0            
  0            
157              
158             1;