SVG-Rasterize

 view release on metacpan or  search on metacpan

lib/SVG/Rasterize/Engine/PangoCairo.pm  view on Meta::CPAN

	    # If nothing comes back it means that a radius is 0
	    # (but then we would not be here because the command
	    # has been switched to a lineto) or start and end are
	    # equal. In this case we do nothing.
	    next if(!defined($cx));

	    my $sin_phi = sin($_->[3]);
	    my $cos_phi = cos($_->[3]);
	    my $matrix  = SVG::Rasterize::multiply_matrices
		($state->{matrix}, [$rx * $cos_phi, -$ry * $sin_phi,
				    $rx * $sin_phi,  $ry * $cos_phi,
				    $cx, $cy]);
	    $context->save;
	    $context->set_matrix(Cairo::Matrix->init(@$matrix));
	    if($dth > 0) {
		$context->arc(0, 0, 1, $th1, $th1 + $dth);
	    }
	    else {
		$context->arc_negative(0, 0, 1, $th1, $th1 + $dth);
	    }
	    $context->restore;
	    next;
	}
	if($_->[0] eq 'a') {
	    @last_control = ();
	    my @curr = $context->get_current_point;
	    my @end  = ($curr[0] + $_->[6], $curr[1] + $_->[7]);  
	    my ($cx, $cy, $rx, $ry, $th1, $dth) =
		SVG::Rasterize::endpoint_to_center
		    (@curr, (@$_)[1..5], @end);

	    # see 'A'
	    next if(!defined($cx));

	    my $sin_phi = sin($_->[3]);
	    my $cos_phi = cos($_->[3]);
	    my $matrix  = SVG::Rasterize::multiply_matrices
		($state->{matrix}, [$rx * $cos_phi, -$ry * $sin_phi,
				    $rx * $sin_phi,  $ry * $cos_phi,
				    $cx, $cy]);
	    $context->save;
	    $context->set_matrix(Cairo::Matrix->init(@$matrix));
	    if($dth > 0) {
		$context->arc(0, 0, 1, $th1, $th1 + $dth);
	    }
	    else {
		$context->arc_negative(0, 0, 1, $th1, $th1 + $dth);
	    }
	    $context->restore;
	    next;
	}
    }

    $self->_fill_and_stroke($state->properties);
    $context->restore;

    return;
}

sub _text_layout {
    my ($self, $state, $cdata) = @_;
    my %font_weights           = (100 => 'thin',
				  200 => 'ultralight',
				  300 => 'light',
				  400 => 'normal',
				  500 => 'medium',
				  600 => 'semibold',
				  700 => 'bold',
				  800 => 'ultrabold',
				  900 => 'heavy');

    my $properties = $state->properties;
    my $layout     = Pango::Cairo::create_layout($self->{context});
    my $desc       = Pango::FontDescription->new;
    $desc->set_absolute_size
	(Pango::units_from_double($properties->{'font-size'}));
    $desc->set_family($properties->{'font-family'})
	if($properties->{'font-family'});
    $desc->set_style($properties->{'font-style'})
	if($properties->{'font-style'});
    $desc->set_variant($properties->{'font-variant'})
	if($properties->{'font-variant'});
    $desc->set_weight($font_weights{$properties->{'font-weight'}})
	if($properties->{'font-weight'});
    $desc->set_stretch($properties->{'font-stretch'})
	if($properties->{'font-stretch'});
    $layout->set_font_description($desc);
    $layout->set_text($cdata);

    return $layout;
}

sub text_width {
    my ($self, $state, $cdata) = @_;

    return 0 if(!$cdata);

    my $context = $self->{context};
    $context->save;

    $context->set_matrix(Cairo::Matrix->init(@{$state->matrix}));
    my $layout  = $self->_text_layout($state, $cdata);
    my $extents = $layout->get_pixel_extents;

    $context->restore;
    return $extents->{width};
}

sub draw_text {
    my ($self, $state, $x, $y, $rotate, $cdata) = @_;

    return if(!$cdata);

    my $properties = $state->properties;
    my $context    = $self->{context};
    $context->save;

    $context->set_matrix(Cairo::Matrix->init(@{$state->matrix}));
    my $layout   = $self->_text_layout($state, $cdata);
    my $extents  = $layout->get_pixel_extents;
    my $baseline = Pango::units_to_double($layout->get_baseline);
    $context->translate($x, $y);
    $context->rotate(($rotate || 0) * PI / 180);
    $context->translate(0 ,-$baseline);
    
    if($properties->{stroke}) {
	Pango::Cairo::layout_path($context, $layout);
	$self->_fill_and_stroke($properties);
    }
    else {
	$self->_prepare_fill($properties);
	Pango::Cairo::show_layout($context, $layout);
    }

    $context->restore;
    return;
}

sub write {
    my ($self, @args) = @_;

    my %args = validate_with
	(params  => \@args,
	 spec    => {type      => {regex => qr/^(?:png)$/},
		     file_name => {type  => SCALAR}},
	 on_fail => sub { SVG::Rasterize->ex_pv($_[0]) });

    if($args{type} eq 'png') {
	if(!$args{file_name}) {
	    warn("Unable to write png file. No file name specified.\n");
	    return undef;
	}

	$self->{context}->show_page;
	$self->{context}->get_target->write_to_png($args{file_name});
    }
    else {
	warn "Unknown output type ($args{type}).\n";
    }

    return;
}

1;

__END__

=head1 SYNOPSIS

  # explicit construction (unusual)
  use SVG::Rasterize::Engine::PangoCairo;
  my $engine = SVG::Rasterize::Engine::PangoCairo->new
      (width  => 640, height => 480);

=head1 DESCRIPTION

This class provides a rasterization backend for
L<SVG::Rasterize|SVG::Rasterize> based on the L<Cairo|Cairo> and
L<Pango|Pango> libraries.



( run in 1.608 second using v1.01-cache-2.11-cpan-df04353d9ac )