SVG-Rasterize

 view release on metacpan or  search on metacpan

examples/stroke_width.pl  view on Meta::CPAN

$svg->circle(cx => 30, cy => 30, r => 20,
	     'stroke' => 'black',
	     'stroke-width' => 5,
	     'fill' => 'none');
$svg->circle(cx => 30, cy => 50, r => 10,
	     'stroke' => 'black',
	     'stroke-width' => 5,
	     'fill' => 'none',
	     transform => 'scale(2, 1)');
$svg->text('x' => 5, 'y' => 20, 'font-size' => 20,
	   transform => 'scale(4, 1)')->cdata('O');

print $svg->xmlify, "\n";

examples/text.pl  view on Meta::CPAN

my $g;
my $points;
my $text;
my $node;

$svg = SVG->new;

$svg->rect('width' => 300, 'height' => 300, 'fill' => 'white');

# baseline test
$svg->text('x' => 30, 'y' => 20, 'fill' => 'red')->cdata('Hello World');
$svg->line(x1 => 30, y1 => 20, x2 => 104, y2 => 20, 'stroke' => 'black');
$g = $svg->group(transform => 'translate(30, 20) rotate(15)');
$g->text('fill' => 'blue')->cdata('Hello World');
$g->line(x1 => 0, y1 => 0, x2 => 74, y2 => 0, 'stroke' => 'black');

# deferred rasterization, flush in right order, text carries on
$text = $svg->text('x' => 30, 'y' => 60);
$text->tspan('font-style' => 'italic')->cdata('foo');
$text->a('xlink:href' => 'foo')->circle
    (cx => 50, cy => 60, r => 7, 'fill' => 'yellow');
$text->tspan('font-size' => 'large')->cdata('bar');

# text-anchor
$svg->line(x1 => 80, y1 => 100, x2 => 80, y2 => 140, 'stroke' => 'blue');
$svg->text('x' => 80, 'y' => 110, 'font-weight' => 900)->cdata('baz');
$text = $svg->text('x' => 80, 'y' => 122,
		   'text-anchor'  => 'middle',
		   'font-weight'  => 'bold',
		   'font-stretch' => 'expanded');
$text->cdata('qux');
$text = $svg->text('x' => 80, 'y' => 134, 'text-anchor' => 'end',
		   'font-variant' => 'small-caps');
$text->cdata('Corge');

# positioning of single characters, directly from SVG spec
$g    = $svg->group(transform => 'translate(50, 200) scale(0.2)');
$g    = $g->group('font-family' => 'Verdana', 'font-size' => 45);
$text = $g->text(fill => 'rgb(255, 164, 0)');
$node = $text->tspan(x => '300 350 400 450 500 550 600 650', 'y' => "100");
$node->cdata('Cute and');
$node = $text->tspan(x => '375 425 475 525 575', 'y' => "200");
$node->cdata('fuzzy');
$g->rect(x => "1", 'y' => "1", width => "998", height => "298",
	 fill => "none", stroke => "blue", 'stroke-width' => "2");

# new chunks are started only due to y
$text = $svg->text(x => 150, 'y' => '50 52 54 56 58 60');
$node = $text->tspan('font-family' => 'Verdana');
$node->cdata('stairs');

# two rotate examples, taken from SVG spec
$text = $svg->text(x => 150, 'y' => 90, 'font-family' => 'Verdana');
$text->tspan('rotate' => '-30,0,30')->cdata('Hello, out there');

# here we cannot rebuild it exactly due to limitations in SVG
$g    = $svg->group(transform => 'translate(150, 120)');
$text = $g->text('font-family' => 'Arial, sans-serif',
		 'fill'        => 'red',
		 'rotate'      => '5 15 25 35 45 55');
$text->cdata('Not ');
$node = $text->tspan('rotate' => "-10,-20,-30,-40",
		     'fill'   => "orange")->cdata('all characters ');
my $node2 = $node->tspan('rotate' => "70,60,50,40,30,20,10",
			 'fill'   => "yellow")->cdata('in ');

$rasterize = SVG::Rasterize->new;
$rasterize->rasterize(width => 300, height => 300, svg => $svg);

$rasterize->write(type => 'png', file_name => 'text.png');

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

	     (map { ['L', @$_] } @points),
	     ['Z']);
    }

    if($points_str) { $self->ie_at_po($state->node_attributes->{points}) }
    else            { return $result }
}

################################### Text ##################################

sub _process_cdata {
    my ($self, $state, %args) = @_;

    return if($args{queued});

    foreach(sort { $a->{atomID} <=> $b->{atomID} } @{$state->text_atoms}) {
	$self->{engine}->draw_text($state,
				   $_->{x}, $_->{y}, $_->{rotate},
				   $_->{cdata});
    }

    return;
}

sub _process_tspan {}

sub _process_text {
    my ($self, $state, %args) = @_;

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

	SVG::Rasterize::Exception::Setting->caught ? 0 : 1;

    # loop through chunks (@chunk_atoms is updated at end of loop)
    while(@chunk_atoms) {
	my $x = 0;
	my $y = 0;

	if($can_text_width) {
	    foreach(@chunk_atoms) {
		my $width = $self->{engine}->text_width
		    ($_->{state}, $_->{cdata});
	    
		$_->{offset}       = [$x, $y];
		$_->{displacement} =
		    [defined($width) ? ($_->{dx} || 0) + $width : undef,
		     ($_->{dy} || 0)];
		$x += $_->{displacement}->[0];
		$y += $_->{displacement}->[1];
	    }

	    # TODO: What to do if right-to-left?

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

    return $self->_process_circle($state, %args)
	if($this_node_name eq 'circle');
    return $self->_process_ellipse($state, %args)
	if($this_node_name eq 'ellipse');
    return $self->_process_line($state, %args)
	if($this_node_name eq 'line');
    return $self->_process_polyline($state, %args)
	if($this_node_name eq 'polyline');
    return $self->_process_polygon($state, %args)
	if($this_node_name eq 'polygon');
    return $self->_process_cdata($state, %args)
	if($this_node_name eq '#text');
    return $self->_process_tspan($state, %args)
	if($this_node_name eq 'tspan');
    return $self->_process_text($state, %args)
	if($this_node_name eq 'text');

    return;
}

###########################################################################

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

#                             Tree Traversal                              #
#                                                                         #
###########################################################################

sub in_error {
    my ($self, $exception) = @_;
    my $state              = SVG::Rasterize::State->new
	(rasterize       => $self,
	 node_name       => 'g',
	 node_attributes => {},
	 cdata           => undef,
	 child_nodes     => undef);

    $self->in_error_hook->($self, $state);

    die $exception;
}

sub _flush_rasterization_queue {
    my ($self) = @_;

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


sub _process_node_object {
    my ($self, $node, %args) = @_;

    my %state_args =
       (node            => $node,
        node_name       => $node->getNodeName,
	node_attributes => $self->_process_normalize_attributes
	    ($args{normalize_attributes}, scalar($node->getAttributes)));

    $state_args{cdata} = $state_args{node_name} eq '#text'
	    ? $node->getData : undef;

    my $child_nodes = $node->getChildNodes;
    if($node->isa('SVG::Element')) {
	# For a SVG::Element we can just take the child nodes
	# directly, because this gives us only the child elements
	# anyway. We have to take care of comments, though.
	# A copy is made to enable manipulation in hooks without
	# changing the node object.
	$state_args{child_nodes} = defined($child_nodes)
	    ? [grep { !$IGNORED_NODES{$_->getNodeName} } @$child_nodes]
	    : undef;

	# extrawurst for text elements in SVG.pm
	if(my $cdata = $node->getData) {
	    $state_args{child_nodes} ||= [];
	    push(@{$state_args{child_nodes}},
		 SVG::Rasterize::TextNode->new(data => $cdata));
	}
    }
    else {
	# For a generic DOM node we only take the children which
	# are either element or text nodes. Note that this excludes
	# comment nodes.
	$state_args{child_nodes} = [];
	foreach(@{$child_nodes || []}) {
	    my $type = $_->getType;
	    next if($type != 1 and $type != 3);

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


=item * C<rasterize>: the C<SVG::Rasterize> object

=item * C<node>: the node object

=item * C<node_name>: the C<DOM> node name

=item * C<node_attributes>: the attributes as HASH reference,
already L<normalized|/White Space Handling>

=item * C<cdata>: string or C<undef>

=item * C<child_nodes>: ARRAY reference with node objects or
C<undef>.

=back

In addition, it may contain the following elements:

=over 4

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


Expects that C<< $state->node_attributes >> have been
validated. Determines C<text-anchor> and the absolute rasterization
position for each
L<text atom|SVG::Rasterize::State::Text/DESCRIPTION>.

=item * _process_tspan

Currently does not do anything. All text processing is done by
either L<_process_text|/_process_text> or
L<_process_cdata|/_process_cdata>. Might be deleted in the future.

=item * _process_cdata

Expects a L<SVG::Rasterize::State|SVG::Rasterize::State> object and
optionally a hash of options. If the option C<queued> is set to a
true value, nothing is done.

Expects that C<< $state->node_attributes >> have been
validated. Calls the C<draw_text> method of the rasterization engine
on each of its atoms in the right order.

=item * make_ro_accessor

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

	}
    }

    $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');

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

	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);
    }

lib/SVG/Rasterize/Specification.pm  view on Meta::CPAN


Version 0.003007

=cut

our $VERSION = '0.003007';

our @EXPORT      = ();
our @EXPORT_OK   = qw(spec_is_element
                      spec_has_child
                      spec_has_pcdata
                      spec_has_attribute
                      spec_attribute_validation
                      spec_attribute_hints
                      spec_is_length
                      spec_is_color);
our %EXPORT_TAGS =  (all => [@EXPORT, @EXPORT_OK]);

our %CHILDREN = ('a'                   => 'Hyperlink',
                 'altGlyph'            => 'TextContent',
                 'altGlyphDef'         => 'Text',

lib/SVG/Rasterize/Specification.pm  view on Meta::CPAN

sub spec_has_child {
    my ($parent, $child) = @_;

    return undef if(!$parent or ref($parent) or !$child or ref($child));
    return undef if(!exists($CHILDREN{$parent}));

    _load_module($parent);
    return($CHILDREN{$parent}->{$child} ? 1 : 0);
}

sub spec_has_pcdata {
    my ($element) = @_;

    return undef if(!$element or ref($element));
    return undef if(!exists($CHILDREN{$element}));
    return($PCDATA{$element} ? 1 : 0);
}

sub spec_has_attribute {
    my ($element, $attr) = @_;

lib/SVG/Rasterize/Specification.pm  view on Meta::CPAN


=head3 spec_has_child

  spec_has_child($parent_element_name, $child_element_name)

Returns C<undef> if there is no C<SVG> element of name
C<$parent_element_name>. Otherwise, returns C<1> if the element is
allowed to have child elements of name C<$child_element_name>, C<0>
if it is not allowed.

=head3 spec_has_pcdata

  spec_has_pcdata($element_name)

Returns C<undef> if there is no C<SVG> element of name
C<$element_name>. Otherwise, returns C<1> if the element is allowed
to contain parsed character data (other than white space), C<0> if
it is not allowed.

=head3 spec_has_attribute

  spec_has_attribute($element_name, $attribute_name)

lib/SVG/Rasterize/State.pm  view on Meta::CPAN

=cut

our $VERSION = '0.003007';


__PACKAGE__->mk_accessors(qw());

__PACKAGE__->mk_ro_accessors(qw(parent
                                rasterize
                                node_name
                                cdata
                                node
                                matrix
                                properties
                                defer_rasterization
                                text_atoms));

###########################################################################
#                                                                         #
#                      Class Variables and Methods                        # 
#                                                                         #

lib/SVG/Rasterize/State.pm  view on Meta::CPAN

sub init {
    my ($self, @args) = @_;
    my %args          = validate_with
	(params  => \@args,
	 spec    =>
	     {rasterize       => {isa      => 'SVG::Rasterize'},
	      parent          => {isa      => 'SVG::Rasterize::State',
				  optional => 1},
	      node_name       => {type     => SCALAR},
	      node_attributes => {type     => HASHREF},
	      cdata           => {type     => SCALAR|UNDEF},
	      node            => {type     => OBJECT,
				  optional => 1},
	      child_nodes     => {type     => ARRAYREF|UNDEF},
	      matrix          => {type     => ARRAYREF,
				  optional => 1}},
	on_fail => sub { SVG::Rasterize->ex_pv($_[0]) });

    # read only and private arguments
    if(exists($args{parent})) { $self->{parent} = $args{parent} }
    $self->{rasterize} = $args{rasterize};

    $self->{node_name}       = $args{node_name};
    $self->{node_attributes} = $args{node_attributes};
    $self->{child_nodes}     = $args{child_nodes};
    $self->{cdata}           = $args{cdata};
    $self->{node}            = $args{node}   if(exists($args{node}));
    $self->{matrix}          = $args{matrix} if(exists($args{matrix}));

    # check matrix and set default
    $self->{matrix} ||= [1, 0, 0, 1, 0, 0];
    foreach(@{$self->{matrix}}) {
	$self->ex_pm_ma_nu('undef') if(!defined($_));
	$self->ex_pm_ma_nu($_)      if(!looks_like_number($_));
    }

lib/SVG/Rasterize/State.pm  view on Meta::CPAN

sub _process_node {
    my ($self)     = @_;
    my $name       = $self->{node_name};
    my $attributes = $self->{node_attributes};

    # element validation either as a child or as existing element
    if($self->{parent}) {
	# allowed child element?
	my $p_node_name = $self->{parent}->node_name;
	if($name eq '#text') {
	    if(!spec_has_pcdata($p_node_name)) {
		$self->ie_el($name, $p_node_name);
	    }	    
	}
	else {
	    if(!spec_has_child($p_node_name, $name)) {
		$self->ie_el($name, $p_node_name);
	    }
	}
    }
    else {
	# as root element we accept any existing element
	$self->ie_el($name) if(!spec_is_element($name));
    }

    # Attribute validation except for cdata nodes. They have no
    # attributes and the Specification modules do not hold
    # validation information for them.
    unless($name eq '#text') {
	my @attr_buffer = %$attributes;
	validate_with(params  => \@attr_buffer,
		      spec    => spec_attribute_validation($name),
		      on_fail => sub { $self->ie_at_pv($_[0]) });
    }

    # defer rasterization

lib/SVG/Rasterize/State.pm  view on Meta::CPAN

object

=item * parent (optional): the parent state object, always
expected except for the root

=item * node_name (mandatory): defined scalar, name of the current
node

=item * node_attributes (mandatory): HASH reference

=item * cdata (mandatory): C<undef> or scalar (no reference)

=item * child_nodes (mandatory): C<undef> or an ARRAY reference

Array entries are not further validated as they are not used within
this object. Do not just provide the return value of
C<getChildNodes> on a node object, because modification of the array
(e.g. by L<shift_child_node|/shift_child_node>) will (usually)
affect the list saved in the node object itself. Make a copy,
e.g. C<< [@{$node->getChildNodes}] >>. Note that changing the
objects in the list will still affect the child nodes saved in the

lib/SVG/Rasterize/State.pm  view on Meta::CPAN

Can only be set at construction time (any arguments to the accessor
are silently ignored). Stores the attributes of the current node as
a HASH reference even if L<node|/node> above is C<undef>. The
accessor does not create a copy of the hash, so changes will affect
the hash stored in the object. This is on purpose to give you full
control e.g. inside a L<hook|SVG::Rasterize/Hooks>. In case the node
has no attributes an empty HASH reference is returned. If the
content differs from C<< $node->getAttributes >> (usage not
recommended), C<node_attributes> is used.

=head3 cdata

Can only be set on construction time. If the node is a character
data node, those character data can be stored in here.

=head3 matrix

Readonly attribute (you can change the contents, of course, but this
is considered a hack bypassing the interface). Stores an ARRAY
reference with 6 numbers C<[a, b, c, d, e, f]> such that the matrix

lib/SVG/Rasterize/State/Text.pm  view on Meta::CPAN

    my $attributes = $self->node_attributes;
    foreach(qw(x y dx dy rotate)) {
	if(defined($attributes->{$_})) {
	    $self->{$_.'_buffer'} = 
		[map { $self->map_length($_) }
		 split($RE_LENGTH{LENGTHS_SPLIT}, $attributes->{$_})];
	}
    }

    # collect position information
    if($self->node_name eq '#text' and my $cdata = $self->cdata) {
	my $ancestor = $self->parent;
	my $buffers  = {'x'    => [],
			'y'    => [],
			dx     => [],
			dy     => [],
			rotate => []};
	while(1) {
	    $self->ex_co_pt if(!defined($ancestor));
	    foreach(keys %$buffers) {
		my $name = $_.'_buffer';

lib/SVG/Rasterize/State/Text.pm  view on Meta::CPAN

	    }
	    if($SVG::Rasterize::TEXT_ROOT_ELEMENTS{$ancestor->node_name}) {
		$founder = $ancestor;
		last;
	    }
	    else {
		$ancestor = $ancestor->parent;
	    }
	}

	# split cdata into atoms
	my @atoms = ();
	while($cdata) {
	    my $found = 0;
	    my $atom  = {state => $self};
	    weaken $atom->{state};
	  BUFFER:
	    foreach(keys %$buffers) {
		while(@{$buffers->{$_}}) {
		    # there are still levels possibly with data
		    if(@{$buffers->{$_}->[0]}) {
			# there are still entries, so we take one
			if($_ eq 'rotate') {

lib/SVG/Rasterize/State/Text.pm  view on Meta::CPAN

		    }
		}
		# if we arrive here we have not found anything
		$atom->{$_} = undef;
	    }

	    # If we have found something we create a new atom.
	    # Otherwise we attach the rest of the string to the last
	    # atom.
	    if($found) {
		$atom->{cdata} = substr($cdata, 0, 1, '');
		if(defined($atom->{x}) or defined($atom->{y})) {
		    # new absolute position creates new chunk;
		    # this implies a new block
		    $atom->{new_chunk} = 1;
		}
		push(@atoms, $atom);
	    }
	    elsif(!@atoms) {
		$atom->{cdata} = $cdata;
		$cdata = '';
		
		# We are at the first atom. Under certain
		# circumstances, we need to start a new block.
		# TODO: user $founder's last atom to check whether
		# ‘glyph-orientation-horizontal’ or
		# ‘glyph-orientation-vertical’ have changed. Maybe
		# I should split whenever this is set explicitly
		# and remerge later if it doesn't have an effect?
		
		push(@atoms, $atom);
	    }
	    else {
		$atoms[-1]->{cdata} .= $cdata;
		$cdata = '';
	    }
	}

	$self->add_text_atoms(@atoms);
    }
}

###########################################################################
#                                                                         #
#                               Accessors                                 # 

lib/SVG/Rasterize/State/Text.pm  view on Meta::CPAN

			 dx        => {type      => UNDEF|SCALAR,
				       callbacks => {length => $lcb}},
			 dy        => {type      => UNDEF|SCALAR,
				       callbacks => {length => $lcb}},
			 rotate    => {type      => UNDEF|SCALAR,
				       callbacks => {length => $ncb}},
			 new_chunk => {type      => BOOLEAN,
				       optional  => 1},
			 new_block => {type      => BOOLEAN,
				       optional  => 1},
			 cdata     => {type      => SCALAR}},
	     on_fail => sub { SVG::Rasterize->ex_pv($_[0]) });
	    
	if($SVG::Rasterize::TEXT_ROOT_ELEMENTS{$self->node_name}) {
	    if(@{$self->{text_atoms}}) {
		if($_->{new_chunk}) {
		    $_->{chunkID} = 
			$self->{text_atoms}->[-1]->{chunkID} + 1;
		}
		else {
		    $_->{chunkID} =

lib/SVG/Rasterize/State/Text.pm  view on Meta::CPAN

		}
		if($_->{new_chunk} or $_->{new_block}) {
		    $_->{blockID} = 
			$self->{text_atoms}->[-1]->{blockID} + 1;
		}
		else {
		    $_->{blockID} =
			$self->{text_atoms}->[-1]->{blockID};
		}
		$_->{atomID} = $self->{text_atoms}->[-1]->{atomID}
		    + length($self->{text_atoms}->[-1]->{cdata});
	    }
	    else {
		$_->{chunkID} = 0;
		$_->{blockID} = 0;
		$_->{atomID}  = 0;
	    }
	}

	push(@{$self->{text_atoms}}, $_);
    }

lib/SVG/Rasterize/State/Text.pm  view on Meta::CPAN

=item * new_block

only present for first atom of each block, leftover of processing,
should not be used

=item * atomID

number of the atom, equal to the length of text before this atom
thereby allowing further splitting without renumbering

=item * cdata: the actual characters of this atom

=item * state: weak reference to this object.

=back

=head3 x_buffer

ARRAY reference, list of explicit x positions that this element
still has to offer.

t/015_specification.t  view on Meta::CPAN

    $module = $SVG::Rasterize::Specification::CHILDREN{rect};
    ok(!spec_has_child('rect', 'bar'), 'rect has no child bar');
    ok(spec_has_child('rect', 'animate'), 'rect has child animate');
    _unload($module);

    $module = $SVG::Rasterize::Specification::CHILDREN{desc};
    ok(!spec_has_child('desc', 'polyline'), 'desc has child polyline');
    _unload($module);
}

sub has_pcdata {
    is(spec_has_pcdata('text'), 1, 'text has pcdata');
    is(spec_has_pcdata('textPath'), 1, 'textPath has pcdata');
    is(spec_has_pcdata('tspan'), 1, 'tspan has pcdata');
    is(spec_has_pcdata('title'), 1, 'title has pcdata');
    is(spec_has_pcdata('a'), 1, 'a has pcdata');
    is(spec_has_pcdata('g'), 0, 'g has no pcdata');
}

sub has_attribute {
    my $module;

    $module = $SVG::Rasterize::Specification::CHILDREN{g};
    is(spec_has_attribute('g', 'font-size'), 1, 'g has font-size');
    is(spec_has_attribute('g', 'foo'), 0, 'g has no attribute foo');
    ok(!defined(spec_has_attribute('bar', 'foo')),
       'bar cannot be asked for attributes');

t/015_specification.t  view on Meta::CPAN

    is(spec_is_color('text', 'stroke-width'), 0,
       'stroke-width is no color on text');
    ok(!defined(spec_is_color('baz', 'font-size')),
       'font-size cannot be checked for color on baz');
    _unload($module);
}

load;
is_element;
has_child;
has_pcdata;
has_attribute;
attribute_validation;
is_length;
is_color;

t/025_instance.t  view on Meta::CPAN

    my $svg;
    my $state;

    $rasterize = SVG::Rasterize->new;
    $svg       = SVG->new->firstChild;
    $state     = SVG::Rasterize::State->new
	(rasterize          => $rasterize,
	 node               => $svg,
	 node_name          => $svg->getNodeName,
	 node_attributes    => {$svg->getAttributes},
	 cdata              => undef,
	 child_nodes        => undef);
    ok(defined($state), 'state defined');
    isa_ok($state, 'SVG::Rasterize::State');

    my @attributes = qw(parent
                        rasterize
                        node_name
                        cdata
                        node
                        matrix
                        properties
                        defer_rasterization);
    my @methods    = qw(new
                        init
                        node_attributes
                        map_length
                        transform
                        shift_child_node);

t/025_instance.t  view on Meta::CPAN

    my $svg;
    my $state;

    $rasterize = SVG::Rasterize->new;
    $svg       = SVG->new->firstChild;
    $state     = SVG::Rasterize::State::Text->new
	(rasterize          => $rasterize,
	 node               => $svg,
	 node_name          => $svg->getNodeName,
	 node_attributes    => {$svg->getAttributes},
	 cdata              => undef,
	 child_nodes        => undef);
    ok(defined($state), 'state::text defined');
    isa_ok($state, 'SVG::Rasterize::State::Text');
    isa_ok($state, 'SVG::Rasterize::State');

    my @attributes = qw(cdata);
    my @methods    = ();
    can_ok($state, @attributes, @methods);
}

sub svg_rasterize_textnode {
    my $node;

    eval { SVG::Rasterize::TextNode->new };
    ok(defined($@), 'node without data fails');
    isa_ok($@, 'SVG::Rasterize::Exception::ParamsValidate');

t/055_exceptions.t  view on Meta::CPAN

	$rasterize = SVG::Rasterize->new;
	warning_is { eval { $rasterize->$_ } } undef,
	    "no warning in rasterize->$_ without arguments";
	ok(defined($@), 'exception has been thrown');
	isa_ok($@, 'SVG::Rasterize::Exception::Base');

	$state = SVG::Rasterize::State->new
	    (rasterize       => $rasterize,
	     node_name       => 'svg',
	     node_attributes => {},
	     cdata           => undef,
	     child_nodes     => undef);
	warning_is { eval { $state->$_ } } undef,
	    "no warning in state->$_ without arguments";
	ok(defined($@), 'exception has been thrown');
	isa_ok($@, 'SVG::Rasterize::Exception::Base');
    }

    warning_is { eval { SVG::Rasterize::Exception::ex_se_lo
                           (bless({}, 'UNIVERSAL')) } }
        undef,

t/055_exceptions.t  view on Meta::CPAN


sub test_ex_co_pt {
    my $rasterize;
    my $state;

    $rasterize = SVG::Rasterize->new;
    $state = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node_name       => 'svg',
	 node_attributes => {},
	 cdata           => undef,
	 child_nodes     => undef);
    warning_is { eval { $state->ex_co_pt } } undef,
        "no warning in state->ex_co_pt without arguments";
    ok(defined($@), 'exception has been thrown');
    isa_ok($@, 'SVG::Rasterize::Exception::Param');

    $state = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node_name       => 'svg',
	 node_attributes => {id => 'foo'},
	 cdata           => undef,
	 child_nodes     => undef);
    warning_is { eval { $state->ex_co_pt } } undef,
        "no warning in state->ex_co_pt without arguments";
    ok(defined($@), 'exception has been thrown');
    isa_ok($@, 'SVG::Rasterize::Exception::Param');
    ok($@->message =~ /ancestor for svg element with id foo/,
       'message contains id');
}

sub test_ex_pa {

t/055_exceptions.t  view on Meta::CPAN

	      qr/Attribute SVG::Rasterize->engine is readonly/,
	      'readonly attribute');

    $rasterize = SVG::Rasterize->new;
    $svg       = SVG->new(width => 10, height => 10)->firstChild;
    $state     = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 node_attributes => {$svg->getAttributes},
	 cdata           => undef,
	 child_nodes     => undef);
    throws_ok(sub { $state->parent('foo') },
	      qr/Attribute SVG::Rasterize::State->parent is readonly/,
	      'readonly attribute');
}

test_caller;
in_error;
test_ex_co_pt;
test_ex_pa;

t/060_geometry.t  view on Meta::CPAN

    my $state;
    my $svg;
    
    $rasterize = SVG::Rasterize->new;
    $svg       = SVG->new(width => 10, height => 10)->firstChild;
    $state     = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 node_attributes => {$svg->getAttributes},
	 cdata           => undef,
	 child_nodes     => undef,
	 matrix          => [1, 0, 0, 1, 0, 0]);

    can_ok($state, 'transform');
    is_deeply([$state->transform(4, -5)], [4, -5], 'identity');

    $state->{matrix} = [1, 0, 0, 1, 3, -1];
    is_deeply([$state->transform(-2, 3)], [1, 2], 'translate');

    $state->{matrix} = [0, -1, 1, 0, 0, 0];

t/060_geometry.t  view on Meta::CPAN

    my $node;

    $rasterize = SVG::Rasterize->new;
    $svg       = SVG->new(width => 10, height => 10)->firstChild;
    $node   = $svg->group(transform => "translate(10, 10)");
    $state     = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 node_attributes => {$svg->getAttributes},
	 cdata           => undef,
	 child_nodes     => undef,
	 matrix          => [1, 0, 0, 1, 0, 0]);
    $state     = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 parent          => $state,
	 node            => $node,
	 node_name       => $node->getNodeName,
	 cdata           => undef,
	 child_nodes     => undef,
	 node_attributes => {$node->getAttributes});
    is_deeply($state->matrix, [1, 0, 0, 1, 10, 10], 'translate matrix');

    $svg   = SVG->new(width => 10, height => 10)->firstChild;
    $node  = $svg->group(transform => "translate(10, 0) scale(3)");
    $state     = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 node_attributes => {$svg->getAttributes},
	 cdata           => undef,
	 child_nodes     => undef,
	 matrix          => [1, 0, 0, 1, 0, 0]);
    $state     = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 parent          => $state,
	 node            => $node,
	 node_name       => $node->getNodeName,
	 cdata           => undef,
	 child_nodes     => undef,
	 node_attributes => {$node->getAttributes});
    is_deeply([$state->transform(-1, 0.5)], [7, 1.5], 'translate scale');

    # with units
    is_deeply([$state->transform('3in', '-144pt')], [820, -540],
	      'with in and pt');

    $svg    = SVG->new(width => 10, height => 10)->firstChild;
    $state  = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 node_attributes => {$svg->getAttributes},
	 cdata           => undef,
	 child_nodes     => undef,
	 matrix          => [1, 0, 0, 1, 0, 0]);
    $node  = $svg->group(transform => "translate(7, -1) scale(3)");
    $state  = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 parent          => $state,
	 node            => $node,
	 node_name       => $node->getNodeName,
	 cdata           => undef,
	 child_nodes     => undef,
	 node_attributes => {$node->getAttributes});
    $node  = $node->group(transform => "translate(-4.2)");
    $state  = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 parent          => $state,
	 node            => $node,
	 node_name       => $node->getNodeName,
	 cdata           => undef,
	 child_nodes     => undef,
	 node_attributes => {$node->getAttributes});
    is_deeply([$state->transform(4, 9)], [6.4, 26], 'double nested');
}

sub initial_viewport {
    my $rasterize;
    my $state;
    my $svg;
    my $node;
    my $attributes;

    $rasterize = SVG::Rasterize->new;
    $svg       = SVG->new->firstChild;
    $state     = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 cdata           => undef,
	 child_nodes     => undef,
	 node_attributes => {$svg->getAttributes});

    $attributes = {width => 100, height => 50};
    $rasterize->_initial_viewport({$svg->getAttributes},
				  $attributes);
    is_deeply($attributes->{matrix}, [1, 0, 0, 1, 0, 0], 'matrix');

    $attributes = {width => '1in', height => '0.5in'};
    $rasterize->_initial_viewport({$svg->getAttributes},

t/060_geometry.t  view on Meta::CPAN


    is($attributes->{width}, 90, 'width transformation');
    is($attributes->{height}, 45, 'height transformation');

    $rasterize = SVG::Rasterize->new;
    $svg       = SVG->new(width => 50)->firstChild;
    $state     = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 cdata           => undef,
	 child_nodes     => undef,
	 node_attributes => {$svg->getAttributes});
    is($state->node_attributes->{width}, 50, 'width attribute');
    $attributes = {width => 100, height => 50};
    $rasterize->_initial_viewport({$svg->getAttributes},
			       $attributes);
    is_deeply($attributes->{matrix}, [2, 0, 0, 1, 0, 0], 'matrix');

    $svg->attrib('height', 200);
    $state  = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 cdata           => undef,
	 child_nodes     => undef,
	 node_attributes => {$svg->getAttributes});
    $attributes = {width => 100, height => 50};
    $rasterize->_initial_viewport({$svg->getAttributes},
			       $attributes);
    is_deeply($attributes->{matrix}, [2, 0, 0, 0.25, 0, 0], 'matrix');

    $rasterize = SVG::Rasterize->new;
    $svg       = SVG->new->firstChild;
    $svg->attrib('width', 100);
    $svg->attrib('height', 50);
    $state  = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 cdata           => undef,
	 child_nodes     => undef,
	 node_attributes => {$svg->getAttributes});
    $attributes = {};
    $rasterize->_initial_viewport({$svg->getAttributes}, $attributes);
    is_deeply($attributes->{matrix}, [1, 0, 0, 1, 0, 0], 
	      'matrix without viewBox');

    $rasterize = SVG::Rasterize->new;
    $svg       = SVG->new->firstChild;
    $svg->attrib('width', 100);
    $svg->attrib('height', 50);
    $svg->attrib('viewBox', '50, 30, 200, 100');
    $state  = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 cdata           => undef,
	 child_nodes     => undef,
	 node_attributes => {$svg->getAttributes});
    $attributes = {};
    $rasterize->_initial_viewport({$svg->getAttributes}, $attributes);
    is_deeply($attributes->{matrix}, [1, 0, 0, 1, 0, 0], 
	      'matrix with viewBox');
    is_deeply([$state->transform(50, 30)], [0, 0],
	      'transform with viewBox');
    is_deeply([$state->transform(50, 130)], [0, 50],
	      'transform with viewBox');

t/060_geometry.t  view on Meta::CPAN

    $attributes = {width => 500, height => 200};
    $rasterize->_initial_viewport({$svg->getAttributes}, 
			       $attributes);
    is_deeply($attributes->{matrix}, [5, 0, 0, 4, 0, 0], 
	      'matrix with viewBox');
    $state  = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 node_attributes => {$svg->getAttributes},
	 cdata           => undef,
	 child_nodes     => undef,
	 matrix          => $attributes->{matrix});
    is_deeply([$state->transform(50, 30)], [0, 0],
	      'transform with viewBox');
    is_deeply([$state->transform(50, 130)], [0, 200],
	      'transform with viewBox');
    is_deeply([$state->transform(250, 130)], [500, 200],
	      'transform with viewBox');
    is_deeply([$state->transform(250, 30)], [500, 0],
	      'transform with viewBox');

t/060_geometry.t  view on Meta::CPAN

    $svg->attrib(height => 600);
    $svg->attrib(viewBox => '0, 0, 2000, 3000');
    $svg->attrib(preserveAspectRatio => 'none');
    $attributes = {};
    $rasterize->_initial_viewport({$svg->getAttributes}, $attributes);
    $state  = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 node_attributes => {$svg->getAttributes},
	 cdata           => undef,
	 child_nodes     => undef,
	 matrix          => $attributes->{matrix});
    is_deeply([$state->transform(0, 0)], [0, 0],
	      'transform with pAR none');
    is_deeply([$state->transform(0, 3000)], [0, 600],
	      'transform with pAR none');
    is_deeply([$state->transform(2000, 3000)], [800, 600],
	      'transform with pAR none');
    is_deeply([$state->transform(2000, 0)], [800, 0],
	      'transform with pAR none');

    $svg->attrib(preserveAspectRatio => 'xMinYMin');
    $attributes = {};
    $rasterize->_initial_viewport({$svg->getAttributes}, $attributes);
    $state  = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 node_attributes => {$svg->getAttributes},
	 cdata           => undef,
	 child_nodes     => undef,
	 matrix          => $attributes->{matrix});
    is_deeply([$state->transform(0, 0)], [0, 0],
	      'transform with pAR xMinYMin');
    is_deeply([$state->transform(0, 3000)], [0, 600],
	      'transform with pAR xMinYMin');
    is_deeply([$state->transform(2000, 3000)], [400, 600],
	      'transform with pAR xMinYMin');
    is_deeply([$state->transform(2000, 0)], [400, 0],
	      'transform with pAR xMinYMin');

    $svg->attrib(preserveAspectRatio => 'xMinYMin meet');
    $attributes = {};
    $rasterize->_initial_viewport({$svg->getAttributes}, $attributes);
    $state  = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 node_attributes => {$svg->getAttributes},
	 cdata           => undef,
	 child_nodes     => undef,
	 matrix          => $attributes->{matrix});
    is_deeply([$state->transform(0, 0)], [0, 0],
	      'transform with pAR xMinYMin meet');
    is_deeply([$state->transform(0, 3000)], [0, 600],
	      'transform with pAR xMinYMin meet');
    is_deeply([$state->transform(2000, 3000)], [400, 600],
	      'transform with pAR xMinYMin meet');
    is_deeply([$state->transform(2000, 0)], [400, 0],
	      'transform with pAR xMinYMin meet');

    $svg->attrib(preserveAspectRatio => 'xMinYMin slice');
    $attributes = {};
    $rasterize->_initial_viewport({$svg->getAttributes}, $attributes);
    $state  = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 node_attributes => {$svg->getAttributes},
	 cdata           => undef,
	 child_nodes     => undef,
	 matrix          => $attributes->{matrix});
    is_deeply([$state->transform(0, 0)], [0, 0],
	      'transform with pAR xMinYMin slice');
    is_deeply([$state->transform(0, 3000)], [0, 1200],
	      'transform with pAR xMinYMin slice');
    is_deeply([$state->transform(2000, 3000)], [800, 1200],
	      'transform with pAR xMinYMin slice');
    is_deeply([$state->transform(2000, 0)], [800, 0],
	      'transform with pAR xMinYMin slice');

    $svg->attrib(preserveAspectRatio => 'xMidYMin');
    $attributes = {};
    $rasterize->_initial_viewport({$svg->getAttributes}, $attributes);
    $state  = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 node_attributes => {$svg->getAttributes},
	 cdata           => undef,
	 child_nodes     => undef,
	 matrix          => $attributes->{matrix});
    is_deeply([$state->transform(0, 0)], [200, 0],
	      'transform with pAR xMidYMin');
    is_deeply([$state->transform(0, 3000)], [200, 600],
	      'transform with pAR xMidYMin');
    is_deeply([$state->transform(2000, 3000)], [600, 600],
	      'transform with pAR xMidYMin');
    is_deeply([$state->transform(2000, 0)], [600, 0],
	      'transform with pAR xMidYMin');

    $svg->attrib(preserveAspectRatio => 'xMidYMin slice');
    $attributes = {};
    $rasterize->_initial_viewport({$svg->getAttributes}, $attributes);
    $state  = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 node_attributes => {$svg->getAttributes},
	 cdata           => undef,
	 child_nodes     => undef,
	 matrix          => $attributes->{matrix});
    is_deeply([$state->transform(0, 0)], [0, 0],
	      'transform with pAR xMidYMin slice');
    is_deeply([$state->transform(0, 3000)], [0, 1200],
	      'transform with pAR xMidYMin slice');
    is_deeply([$state->transform(2000, 3000)], [800, 1200],
	      'transform with pAR xMidYMin slice');
    is_deeply([$state->transform(2000, 0)], [800, 0],
	      'transform with pAR xMidYMin slice');

    $svg->attrib(preserveAspectRatio => 'xMaxYMin');
    $attributes = {};
    $rasterize->_initial_viewport({$svg->getAttributes}, $attributes);
    $state  = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 node_attributes => {$svg->getAttributes},
	 cdata           => undef,
	 child_nodes     => undef,
	 matrix          => $attributes->{matrix});
    is_deeply([$state->transform(0, 0)], [400, 0],
	      'transform with pAR xMaxYMin');
    is_deeply([$state->transform(0, 3000)], [400, 600],
	      'transform with pAR xMaxYMin');
    is_deeply([$state->transform(2000, 3000)], [800, 600],
	      'transform with pAR xMaxYMin');
    is_deeply([$state->transform(2000, 0)], [800, 0],
	      'transform with pAR xMaxYMin');

    $svg->attrib(preserveAspectRatio => 'xMaxYMin slice');
    $attributes = {};
    $rasterize->_initial_viewport({$svg->getAttributes}, $attributes);
    $state  = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 node_attributes => {$svg->getAttributes},
	 cdata           => undef,
	 child_nodes     => undef,
	 matrix          => $attributes->{matrix});
    is_deeply([$state->transform(0, 0)], [0, 0],
	      'transform with pAR xMaxYMin slice');
    is_deeply([$state->transform(0, 3000)], [0, 1200],
	      'transform with pAR xMaxYMin slice');
    is_deeply([$state->transform(2000, 3000)], [800, 1200],
	      'transform with pAR xMaxYMin slice');
    is_deeply([$state->transform(2000, 0)], [800, 0],
	      'transform with pAR xMaxYMin slice');

    $svg->attrib(preserveAspectRatio => 'xMinYMid');
    $attributes = {};
    $rasterize->_initial_viewport({$svg->getAttributes}, $attributes);
    $state  = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 node_attributes => {$svg->getAttributes},
	 cdata           => undef,
	 child_nodes     => undef,
	 matrix          => $attributes->{matrix});
    is_deeply([$state->transform(0, 0)], [0, 0],
	      'transform with pAR xMinYMid');
    is_deeply([$state->transform(0, 3000)], [0, 600],
	      'transform with pAR xMinYMid');
    is_deeply([$state->transform(2000, 3000)], [400, 600],
	      'transform with pAR xMinYMid');
    is_deeply([$state->transform(2000, 0)], [400, 0],
	      'transform with pAR xMinYMid');

    $svg->attrib(preserveAspectRatio => 'xMinYMid slice');
    $attributes = {};
    $rasterize->_initial_viewport({$svg->getAttributes}, $attributes);
    $state  = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 node_attributes => {$svg->getAttributes},
	 cdata           => undef,
	 child_nodes     => undef,
	 matrix          => $attributes->{matrix});
    is_deeply([$state->transform(0, 0)], [0, -300],
	      'transform with pAR xMinYMid slice');
    is_deeply([$state->transform(0, 3000)], [0, 900],
	      'transform with pAR xMinYMid slice');
    is_deeply([$state->transform(2000, 3000)], [800, 900],
	      'transform with pAR xMinYMid slice');
    is_deeply([$state->transform(2000, 0)], [800, -300],
	      'transform with pAR xMinYMid slice');

    $svg->attrib(preserveAspectRatio => 'xMidYMid');
    $attributes = {};
    $rasterize->_initial_viewport({$svg->getAttributes}, $attributes);
    $state  = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 node_attributes => {$svg->getAttributes},
	 cdata           => undef,
	 child_nodes     => undef,
	 matrix          => $attributes->{matrix});
    is_deeply([$state->transform(0, 0)], [200, 0],
	      'transform with pAR xMidYMid');
    is_deeply([$state->transform(0, 3000)], [200, 600],
	      'transform with pAR xMidYMid');
    is_deeply([$state->transform(2000, 3000)], [600, 600],
	      'transform with pAR xMidYMid');
    is_deeply([$state->transform(2000, 0)], [600, 0],
	      'transform with pAR xMidYMid');

    $svg->attrib(preserveAspectRatio => 'xMidYMid slice');
    $attributes = {};
    $rasterize->_initial_viewport({$svg->getAttributes}, $attributes);
    $state  = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 node_attributes => {$svg->getAttributes},
	 cdata           => undef,
	 child_nodes     => undef,
	 matrix          => $attributes->{matrix});
    is_deeply([$state->transform(0, 0)], [0, -300],
	      'transform with pAR xMidYMid slice');
    is_deeply([$state->transform(0, 3000)], [0, 900],
	      'transform with pAR xMidYMid slice');
    is_deeply([$state->transform(2000, 3000)], [800, 900],
	      'transform with pAR xMidYMid slice');
    is_deeply([$state->transform(2000, 0)], [800, -300],
	      'transform with pAR xMidYMid slice');

    $svg->attrib(preserveAspectRatio => 'xMaxYMid');
    $attributes = {};
    $rasterize->_initial_viewport({$svg->getAttributes}, $attributes);
    $state  = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 node_attributes => {$svg->getAttributes},
	 cdata           => undef,
	 child_nodes     => undef,
	 matrix          => $attributes->{matrix});
    is_deeply([$state->transform(0, 0)], [400, 0],
	      'transform with pAR xMaxYMid');
    is_deeply([$state->transform(0, 3000)], [400, 600],
	      'transform with pAR xMaxYMid');
    is_deeply([$state->transform(2000, 3000)], [800, 600],
	      'transform with pAR xMaxYMid');
    is_deeply([$state->transform(2000, 0)], [800, 0],
	      'transform with pAR xMaxYMid');

    $svg->attrib(preserveAspectRatio => 'xMaxYMid slice');
    $attributes = {};
    $rasterize->_initial_viewport({$svg->getAttributes}, $attributes);
    $state  = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 node_attributes => {$svg->getAttributes},
	 cdata           => undef,
	 child_nodes     => undef,
	 matrix          => $attributes->{matrix});
    is_deeply([$state->transform(0, 0)], [0, -300],
	      'transform with pAR xMaxYMid slice');
    is_deeply([$state->transform(0, 3000)], [0, 900],
	      'transform with pAR xMaxYMid slice');
    is_deeply([$state->transform(2000, 3000)], [800, 900],
	      'transform with pAR xMaxYMid slice');
    is_deeply([$state->transform(2000, 0)], [800, -300],
	      'transform with pAR xMaxYMid slice');

    $svg->attrib(preserveAspectRatio => 'xMinYMax');
    $attributes = {};
    $rasterize->_initial_viewport({$svg->getAttributes}, $attributes);
    $state  = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 node_attributes => {$svg->getAttributes},
	 cdata           => undef,
	 child_nodes     => undef,
	 matrix          => $attributes->{matrix});
    is_deeply([$state->transform(0, 0)], [0, 0],
	      'transform with pAR xMinYMax');
    is_deeply([$state->transform(0, 3000)], [0, 600],
	      'transform with pAR xMinYMax');
    is_deeply([$state->transform(2000, 3000)], [400, 600],
	      'transform with pAR xMinYMax');
    is_deeply([$state->transform(2000, 0)], [400, 0],
	      'transform with pAR xMinYMax');

    $svg->attrib(preserveAspectRatio => 'xMinYMax slice');
    $attributes = {};
    $rasterize->_initial_viewport({$svg->getAttributes}, $attributes);
    $state  = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 node_attributes => {$svg->getAttributes},
	 cdata           => undef,
	 child_nodes     => undef,
	 matrix          => $attributes->{matrix});
    is_deeply([$state->transform(0, 0)], [0, -600],
	      'transform with pAR xMinYMax slice');
    is_deeply([$state->transform(0, 3000)], [0, 600],
	      'transform with pAR xMinYMax slice');
    is_deeply([$state->transform(2000, 3000)], [800, 600],
	      'transform with pAR xMinYMax slice');
    is_deeply([$state->transform(2000, 0)], [800, -600],
	      'transform with pAR xMinYMax slice');

    $svg->attrib(preserveAspectRatio => 'xMidYMax');
    $attributes = {};
    $rasterize->_initial_viewport({$svg->getAttributes}, $attributes);
    $state  = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 node_attributes => {$svg->getAttributes},
	 cdata           => undef,
	 child_nodes     => undef,
	 matrix          => $attributes->{matrix});
    is_deeply([$state->transform(0, 0)], [200, 0],
	      'transform with pAR xMidYMax');
    is_deeply([$state->transform(0, 3000)], [200, 600],
	      'transform with pAR xMidYMax');
    is_deeply([$state->transform(2000, 3000)], [600, 600],
	      'transform with pAR xMidYMax');
    is_deeply([$state->transform(2000, 0)], [600, 0],
	      'transform with pAR xMidYMax');

    $svg->attrib(preserveAspectRatio => 'xMidYMax slice');
    $attributes = {};
    $rasterize->_initial_viewport({$svg->getAttributes}, $attributes);
    $state  = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 node_attributes => {$svg->getAttributes},
	 cdata           => undef,
	 child_nodes     => undef,
	 matrix          => $attributes->{matrix});
    is_deeply([$state->transform(0, 0)], [0, -600],
	      'transform with pAR xMidYMax slice');
    is_deeply([$state->transform(0, 3000)], [0, 600],
	      'transform with pAR xMidYMax slice');
    is_deeply([$state->transform(2000, 3000)], [800, 600],
	      'transform with pAR xMidYMax slice');
    is_deeply([$state->transform(2000, 0)], [800, -600],
	      'transform with pAR xMidYMax slice');

    $svg->attrib(preserveAspectRatio => 'xMaxYMax');
    $attributes = {};
    $rasterize->_initial_viewport({$svg->getAttributes}, $attributes);
    $state  = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 node_attributes => {$svg->getAttributes},
	 cdata           => undef,
	 child_nodes     => undef,
	 matrix          => $attributes->{matrix});
    is_deeply([$state->transform(0, 0)], [400, 0],
	      'transform with pAR xMaxYMax');
    is_deeply([$state->transform(0, 3000)], [400, 600],
	      'transform with pAR xMaxYMax');
    is_deeply([$state->transform(2000, 3000)], [800, 600],
	      'transform with pAR xMaxYMax');
    is_deeply([$state->transform(2000, 0)], [800, 0],
	      'transform with pAR xMaxYMax');

    $svg->attrib(preserveAspectRatio => 'xMaxYMax slice');
    $attributes = {};
    $rasterize->_initial_viewport({$svg->getAttributes}, $attributes);
    $state  = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 node_attributes => {$svg->getAttributes},
	 cdata           => undef,
	 child_nodes     => undef,
	 matrix          => $attributes->{matrix});
    is_deeply([$state->transform(0, 0)], [0, -600],
	      'transform with pAR xMaxYMax slice');
    is_deeply([$state->transform(0, 3000)], [0, 600],
	      'transform with pAR xMaxYMax slice');
    is_deeply([$state->transform(2000, 3000)], [800, 600],
	      'transform with pAR xMaxYMax slice');
    is_deeply([$state->transform(2000, 0)], [800, -600],
	      'transform with pAR xMaxYMax slice');

t/060_geometry.t  view on Meta::CPAN

    $svg->attrib(viewBox => '200, -500, 8000, 3000');
    $svg->attrib(preserveAspectRatio => 'none');
    $svg->attrib(preserveAspectRatio => 'defer xMidYMax meet');
    $attributes = {};
    $rasterize->_initial_viewport({$svg->getAttributes}, $attributes);
    $state  = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 node_attributes => {$svg->getAttributes},
	 cdata           => undef,
	 child_nodes     => undef,
	 matrix          => $attributes->{matrix});
    is_deeply([$state->transform(200, -500)], [0, 150],
	      'transform with pAR xMidYMax');
    is_deeply([$state->transform(200, 2500)], [0, 300],
	      'transform with pAR xMidYMax');
    is_deeply([$state->transform(8200, 2500)], [400, 300],
	      'transform with pAR xMidYMax');
    is_deeply([$state->transform(8200, -500)], [400, 150],
	      'transform with pAR xMidYMax');

    $svg->attrib(preserveAspectRatio => 'defer   xMidYMax  slice');
    $attributes = {};
    $rasterize->_initial_viewport({$svg->getAttributes}, $attributes);
    $state  = SVG::Rasterize::State->new
	(rasterize       => $rasterize,
	 node            => $svg,
	 node_name       => $svg->getNodeName,
	 node_attributes => {$svg->getAttributes},
	 cdata           => undef,
	 child_nodes     => undef,
	 matrix          => $attributes->{matrix});
    is_deeply([$state->transform(200, -500)], [-200, 0],
	      'transform with pAR xMidYMax');
    is_deeply([$state->transform(200, 2500)], [-200, 300],
	      'transform with pAR xMidYMax');
    is_deeply([$state->transform(8200, 2500)], [600, 300],
	      'transform with pAR xMidYMax');
    is_deeply([$state->transform(8200, -500)], [600, 0],
	      'transform with pAR xMidYMax');

t/080_text.t  view on Meta::CPAN

use warnings;

# $Id: 080_text.t 6649 2011-04-30 05:30:57Z powergnom $

use Test::More tests => 234;

use SVG;
use Test::Exception;
use SVG::Rasterize;

sub state_cdata {
    my $rasterize;
    my $svg;
    my $node;

    $rasterize = SVG::Rasterize->new;
    $svg       = SVG->new(width => 400, height => 300);
    $svg->firstChild->attrib('id' => 'svg');
    $node = $svg->group(id => 'g01');
    $node->text(id => 'te01')->cdata('Hello World');
    $rasterize->start_node_hook(sub {
	my ($rasterize, $state) = @_;
	if($state->node_name eq '#text') {
	    is($state->cdata, 'Hello World', 'cdata arrived at State');
	}
    });
    $rasterize->rasterize(svg => $svg);
}

sub font_properties {
    my $rasterize;
    my $svg;
    my $node;

t/080_text.t  view on Meta::CPAN

    $svg       = SVG->new(id => 'svg', width => 400, height => 300);
    $svg->svg(id => 'svg01', 'font-size' => 'humangous');
    throws_ok(sub { $rasterize->rasterize(svg => $svg) },
	      qr/font\-size/,
	      'invalid font-size');

    $rasterize = SVG::Rasterize->new;
    $svg       = SVG->new(width => 400, height => 300);
    $svg->firstChild->attrib('id' => 'svg');
    $node = $svg->text(id => 'te01', 'font-size' => 'large');
    $node->cdata('Hello World');
    $rasterize->start_node_hook(sub {
	my ($rasterize, $state) = @_;
	if($state->node_attributes->{id}) {
	    if($state->node_attributes->{id} eq 'te01') {
		is($state->properties->{'font-size'}, 18,
		   'font-size large');
	    }
	}
    });
    $rasterize->rasterize(svg => $svg);

t/080_text.t  view on Meta::CPAN

    $svg       = SVG->new(id => 'svg', width => 400, height => 300);
    $svg->svg(id => 'svg01', 'font-weight' => 350);
    throws_ok(sub { $rasterize->rasterize(svg => $svg) },
	      qr/font\-weight/,
	      'invalid numerical font-weight');

    $rasterize = SVG::Rasterize->new;
    $svg       = SVG->new(width => 400, height => 300);
    $svg->firstChild->attrib('id' => 'svg');
    $node = $svg->text(id => 'te01', 'font-weight' => 'bold');
    $node->cdata('Hello World');
    $rasterize->start_node_hook(sub {
	my ($rasterize, $state) = @_;
	if($state->node_attributes->{id}) {
	    if($state->node_attributes->{id} eq 'te01') {
		is($state->properties->{'font-weight'}, 700,
		   'font-weight 700 (bold)');
	    }
	}
    });
    $rasterize->rasterize(svg => $svg);

    $rasterize = SVG::Rasterize->new;
    $svg       = SVG->new(width => 400, height => 300);
    $svg->firstChild->attrib('id' => 'svg');
    $node = $svg->text(id => 'te01', 'font-weight' => '300');
    $node->cdata('Hello World');
    $rasterize->start_node_hook(sub {
	my ($rasterize, $state) = @_;
	if($state->node_attributes->{id}) {
	    if($state->node_attributes->{id} eq 'te01') {
		is($state->properties->{'font-weight'}, 300,
		   'font-weight 300');
	    }
	}
    });
    $rasterize->rasterize(svg => $svg);

t/080_text.t  view on Meta::CPAN

    $svg       = SVG->new(id => 'svg', width => 400, height => 300);
    $svg->svg(id => 'svg01', 'font-stretch' => 'so wide');
    throws_ok(sub { $rasterize->rasterize(svg => $svg) },
	      qr/font\-stretch/,
	      'invalid font-stretch');

    $rasterize = SVG::Rasterize->new;
    $svg       = SVG->new(width => 400, height => 300);
    $svg->firstChild->attrib('id' => 'svg');
    $node = $svg->text(id => 'te01', 'font-stretch' => 'ultra-condensed');
    $node->cdata('Hello World');
    $rasterize->start_node_hook(sub {
	my ($rasterize, $state) = @_;
	if($state->node_attributes->{id}) {
	    if($state->node_attributes->{id} eq 'te01') {
		is($state->properties->{'font-stretch'}, 'ultra-condensed',
		   'font-stretch ultra-condensed');
	    }
	}
    });
    $rasterize->rasterize(svg => $svg);

t/080_text.t  view on Meta::CPAN

	}
    });
    $rasterize->rasterize(svg => $svg);
}

sub split_into_atoms {
    my $rasterize;
    my $svg;
    my $node;
    my $text;
    my @expected_cdata;
    my @expected_chunks;
    my @expected_blocks;

    ok(1);
    ok(1, '==== split into atoms ====');
    $rasterize = SVG::Rasterize->new;
    $svg       = SVG->new(width => 400, height => 300);
    $svg->firstChild->attrib('id' => 'svg');
    $node = $svg->group(id => 'g01');
    $node = $node->text(id => 'te01');
    $node->cdata('foo');
    $rasterize->end_node_hook(sub {
	my ($rasterize, $state) = @_;
	if(!$state->node_attributes->{id}) {
	    if($state->node_name eq '#text') {
		my $text_atoms = $state->text_atoms;
		ok(defined($text_atoms),
		   'text_atoms defined for cdata state object');
		is(ref($text_atoms), 'ARRAY',
		   'text_atoms ARRAY reference');
		is(@$text_atoms, 1, 'there is 1 atom');
		ok(defined($text_atoms->[0]), 'atom is defined');
		is(ref($text_atoms->[0]), 'HASH',
		   'atom is HASH reference');
		is($text_atoms->[0]->{cdata}, 'foo', 'cdata foo');
		is($text_atoms->[0]->{chunkID}, 0, 'chunkID 0');
		is($text_atoms->[0]->{blockID}, 0, 'blockID 0');
		is($text_atoms->[0]->{atomID},  0, 'atomID 0');
	    }
	}
	elsif($state->node_attributes->{id} eq 'te01') {
	    my $text_atoms = $state->text_atoms;
	    ok(defined($text_atoms),
		   'text_atoms defined for text state object');
	    is(ref($text_atoms), 'ARRAY',
	       'text_atoms ARRAY reference');
	    is(@$text_atoms, 1, 'there is 1 atom');
	    is($text_atoms->[0]->{cdata}, 'foo', 'cdata foo');
	}
    });
    $rasterize->rasterize(svg => $svg);

    ok(1);
    ok(1, '---- text with tspan ----');
    $rasterize = SVG::Rasterize->new;
    $svg       = SVG->new(width => 400, height => 300);
    $svg->firstChild->attrib('id' => 'svg');
    $node = $svg->group(id => 'g01');
    $node = $node->text(id => 'te01');
    $node = $node->tspan(id => 'ts01');
    $node->cdata('bar');
    $rasterize->end_node_hook(sub {
	my ($rasterize, $state) = @_;
	if(!$state->node_attributes->{id}) {
	    if($state->node_name eq '#text') {
		my $text_atoms = $state->text_atoms;
		ok(defined($text_atoms),
		   'text_atoms defined for cdata state object');
		is(ref($text_atoms), 'ARRAY',
		   'text_atoms ARRAY reference');
		is(@$text_atoms, 1, 'there is 1 atom');
		ok(defined($text_atoms->[0]), 'atom is defined');
		is(ref($text_atoms->[0]), 'HASH',
		   'atom is HASH reference');
		is($text_atoms->[0]->{cdata}, 'bar', 'cdata bar');
		is($text_atoms->[0]->{chunkID}, 0, 'chunkID 0');
		is($text_atoms->[0]->{blockID}, 0, 'blockID 0');
		is($text_atoms->[0]->{atomID},  0, 'atomID 0');
	    }
	}
	elsif($state->node_attributes->{id} eq 'te01') {
	    my $text_atoms = $state->text_atoms;
	    ok(defined($text_atoms),
	       'text_atoms defined for text state object');
	    is(ref($text_atoms), 'ARRAY',
	       'text_atoms ARRAY reference');
	    is(@$text_atoms, 1, 'there is 1 atom');
	    is($text_atoms->[0]->{cdata}, 'bar', 'cdata bar');
	}
    });
    $rasterize->rasterize(svg => $svg);

    ok(1);
    ok(1, '---- text with two tspans ----');
    $rasterize = SVG::Rasterize->new;
    $svg       = SVG->new(width => 400, height => 300);
    $svg->firstChild->attrib('id' => 'svg');
    $node = $svg->group(id => 'g01');
    $text = $node->text(id => 'te01');
    $node = $text->tspan(id => 'ts01');
    $node->cdata('baz');
    $node = $text->tspan(id => 'ts02');
    $node->cdata('qux');
    $rasterize->end_node_hook(sub {
	my ($rasterize, $state) = @_;
	if(!$state->node_attributes->{id}) {
	    if($state->node_name eq '#text') {
		if($state->cdata and $state->cdata eq 'baz') {
		    my $text_atoms = $state->text_atoms;
		    ok(defined($text_atoms),
		       'text_atoms defined for cdata state object');
		    is(ref($text_atoms), 'ARRAY',
		       'text_atoms ARRAY reference');
		    is(@$text_atoms, 1, 'there is 1 atom');
		    ok(defined($text_atoms->[0]), 'atom is defined');
		    is(ref($text_atoms->[0]), 'HASH',
		       'atom is HASH reference');
		    is($text_atoms->[0]->{cdata}, 'baz', 'cdata baz');
		    is($text_atoms->[0]->{chunkID}, 0, 'chunkID 0');
		    is($text_atoms->[0]->{blockID}, 0, 'blockID 0');
		    is($text_atoms->[0]->{atomID},  0, 'atomID 0');
		}
		elsif($state->cdata and $state->cdata eq 'qux') {
		    my $text_atoms = $state->text_atoms;
		    ok(defined($text_atoms),
		       'text_atoms defined for cdata state object');
		    is(ref($text_atoms), 'ARRAY',
		       'text_atoms ARRAY reference');
		    is(@$text_atoms, 1, 'there is 1 atom');
		    ok(defined($text_atoms->[0]), 'atom is defined');
		    is(ref($text_atoms->[0]), 'HASH',
		       'atom is HASH reference');
		    is($text_atoms->[0]->{cdata}, 'qux', 'cdata qux');
		    is($text_atoms->[0]->{chunkID}, 0, 'chunkID 0');
		    is($text_atoms->[0]->{blockID}, 0, 'blockID 0');
		    is($text_atoms->[0]->{atomID},  3, 'atomID 3');
		}
	    }
	}
	elsif($state->node_attributes->{id} eq 'te01') {
	    my $text_atoms = $state->text_atoms;
	    ok(defined($text_atoms),
	       'text_atoms defined for text state object');
	    is(ref($text_atoms), 'ARRAY',
	       'text_atoms ARRAY reference');
	    is(@$text_atoms, 2, 'there are 2 atoms');
	    is($text_atoms->[0]->{cdata}, 'baz', 'cdata baz');
	    is($text_atoms->[0]->{atomID}, 0, 'atomID 0');
	    is($text_atoms->[1]->{cdata}, 'qux', 'cdata qux');
	    is($text_atoms->[1]->{atomID}, 3, 'atomID 3');
	}
    });
    $rasterize->rasterize(svg => $svg);
    
    ok(1);
    ok(1, '---- dx, y, and direct cdata mixed with tspans ----');
    $rasterize = SVG::Rasterize->new;
    $svg       = SVG->new(width => 400, height => 300);
    $svg->firstChild->attrib('id' => 'svg');
    $node = $svg->group(id => 'g01');
    $text = $node->text(id => 'te01');
    $node = $text->tspan(id => 'ts01');
    $node->cdata('foo');
    $node = $text->tspan(id => 'ts02', dx => 10);
    $node->cdata('bar');
    $node = $text->tspan(id => 'ts03', 'y' => -30);
    $node->cdata('baz');
    $text->cdata('qux');
    $rasterize->end_node_hook(sub {
	my ($rasterize, $state) = @_;
	if(!$state->node_attributes->{id}) {
	    if($state->node_name eq '#text') {
		if($state->cdata and $state->cdata eq 'foo') {
		    my $text_atoms = $state->text_atoms;
		    ok(defined($text_atoms),
		       'text_atoms defined for cdata state object');
		    is(ref($text_atoms), 'ARRAY',
		       'text_atoms ARRAY reference');
		    is(@$text_atoms, 1, 'there is 1 atom');
		    ok(defined($text_atoms->[0]), 'atom is defined');
		    is(ref($text_atoms->[0]), 'HASH',
		       'atom is HASH reference');
		    is($text_atoms->[0]->{cdata}, 'foo', 'cdata foo');
		    is($text_atoms->[0]->{chunkID}, 0, 'chunkID 0');
		    is($text_atoms->[0]->{blockID}, 0, 'blockID 0');
		    is($text_atoms->[0]->{atomID},  0, 'atomID 0');
		}
		elsif($state->cdata and $state->cdata eq 'bar') {
		    my $text_atoms = $state->text_atoms;
		    ok(defined($text_atoms),
		       'text_atoms defined for cdata state object');
		    is(ref($text_atoms), 'ARRAY',
		       'text_atoms ARRAY reference');
		    is(@$text_atoms, 1, 'there is 1 atom');
		    ok(defined($text_atoms->[0]), 'atom is defined');
		    is(ref($text_atoms->[0]), 'HASH',
		       'atom is HASH reference');
		    is($text_atoms->[0]->{cdata}, 'bar', 'cdata bar');
		    is($text_atoms->[0]->{dx}, 10, 'dx 10');
		    is($text_atoms->[0]->{chunkID}, 0, 'chunkID 0');
		    is($text_atoms->[0]->{blockID}, 0, 'blockID 0');
		    is($text_atoms->[0]->{atomID},  3, 'atomID 3');
		}
		elsif($state->cdata and $state->cdata eq 'baz') {
		    my $text_atoms = $state->text_atoms;
		    ok(defined($text_atoms),
		       'text_atoms defined for cdata state object');
		    is(ref($text_atoms), 'ARRAY',
		       'text_atoms ARRAY reference');
		    is(@$text_atoms, 1, 'there is 1 atom');
		    ok(defined($text_atoms->[0]), 'atom is defined');
		    is(ref($text_atoms->[0]), 'HASH',
		       'atom is HASH reference');
		    is($text_atoms->[0]->{cdata}, 'baz', 'cdata baz');
		    ok(!defined($text_atoms->[0]->{dx}), 'no dx setting');
		    is($text_atoms->[0]->{y}, -30, 'y -30');
		    is($text_atoms->[0]->{chunkID}, 1, 'chunkID 1');
		    is($text_atoms->[0]->{blockID}, 1, 'blockID 1');
		    is($text_atoms->[0]->{atomID},  6, 'atomID 6');
		}
		elsif($state->cdata and $state->cdata eq 'qux') {
		    my $text_atoms = $state->text_atoms;
		    ok(defined($text_atoms),
		       'text_atoms defined for cdata state object');
		    is(ref($text_atoms), 'ARRAY',
		       'text_atoms ARRAY reference');
		    is(@$text_atoms, 1, 'there is 1 atom');
		    ok(defined($text_atoms->[0]), 'atom is defined');
		    is(ref($text_atoms->[0]), 'HASH',
		       'atom is HASH reference');
		    is($text_atoms->[0]->{cdata}, 'qux', 'cdata qux');
		    ok(!defined($text_atoms->[0]->{dx}), 'no dx setting');
		    ok(!defined($text_atoms->[0]->{y}), 'no y setting');
		    is($text_atoms->[0]->{chunkID}, 1, 'chunkID 1');
		    is($text_atoms->[0]->{blockID}, 1, 'blockID 1');
		    is($text_atoms->[0]->{atomID},  9, 'atomID 9');
		}
	    }
	}
	elsif($state->node_attributes->{id} eq 'te01') {
	    my $text_atoms = $state->text_atoms;
	    ok(defined($text_atoms),
	       'text_atoms defined for text state object');
	    is(ref($text_atoms), 'ARRAY',
	       'text_atoms ARRAY reference');
	    is(@$text_atoms, 4, 'there are 2 atoms');
	    is($text_atoms->[0]->{cdata}, 'foo', 'cdata foo');
	    is($text_atoms->[1]->{cdata}, 'bar', 'cdata bar');
	    is($text_atoms->[2]->{cdata}, 'baz', 'cdata baz');
	    is($text_atoms->[3]->{cdata}, 'qux', 'cdata qux');
	}
    });
    $rasterize->rasterize(svg => $svg);

    ok(1);
    ok(1, '---- text with multiple dx ----');
    $rasterize = SVG::Rasterize->new;
    $svg       = SVG->new(width => 400, height => 300);
    $svg->firstChild->attrib('id' => 'svg');
    $node = $svg->group(id => 'g01');
    $node = $node->text(id => 'te01', dx => '0 1 2');
    $node->cdata('foobar');
    $rasterize->end_node_hook(sub {
	my ($rasterize, $state) = @_;
	if(!$state->node_attributes->{id}) {
	    if($state->node_name eq '#text') {
		my $text_atoms = $state->text_atoms;
		ok(defined($text_atoms),
		   'text_atoms defined for cdata state object');
		is(ref($text_atoms), 'ARRAY',
		   'text_atoms ARRAY reference');
		@expected_cdata = ('f', 'o', 'obar');
		is(@$text_atoms, scalar(@expected_cdata),
		   sprintf('there are %d atoms', scalar(@expected_cdata)));
		for(my $i=0;$i<@expected_cdata;$i++) {
		    ok(defined($text_atoms->[$i]), 'atom is defined');
		    is(ref($text_atoms->[$i]), 'HASH',
		       'atom is HASH reference');
		    is($text_atoms->[$i]->{cdata}, $expected_cdata[$i],
		       "cdata $expected_cdata[$i]");
		    is($text_atoms->[$i]->{chunkID}, 0, 'chunkID 0');
		    is($text_atoms->[$i]->{blockID}, 0, 'blockID 0');
		}
	    }
	}
	elsif($state->node_attributes->{id} eq 'te01') {
	    my $text_atoms = $state->text_atoms;
	    ok(defined($text_atoms),
		   'text_atoms defined for text state object');
	    is(ref($text_atoms), 'ARRAY',
	       'text_atoms ARRAY reference');
	    @expected_cdata = ('f', 'o', 'obar');
	    is(@$text_atoms, scalar(@expected_cdata),
	       sprintf('there are %d atoms', scalar(@expected_cdata)));
	    for(my $i=0;$i<@expected_cdata;$i++) {
		ok(defined($text_atoms->[$i]), 'atom is defined');
		is(ref($text_atoms->[$i]), 'HASH',
		   'atom is HASH reference');
		is($text_atoms->[$i]->{cdata}, $expected_cdata[$i],
		   "cdata $expected_cdata[$i]");
		is($text_atoms->[$i]->{chunkID}, 0, 'chunkID 0');
		is($text_atoms->[$i]->{blockID}, 0, 'blockID 0');
	    }
	}
    });
    $rasterize->rasterize(svg => $svg);

    ok(1);
    ok(1, '---- text with multiple x ----');
    $rasterize = SVG::Rasterize->new;
    $svg       = SVG->new(width => 400, height => 300);
    $svg->firstChild->attrib('id' => 'svg');
    $node = $svg->group(id => 'g01');
    $node = $node->text(id => 'te01', x => '0 1 2');
    $node->cdata('foobar');
    $rasterize->end_node_hook(sub {
	my ($rasterize, $state) = @_;
	if(!$state->node_attributes->{id}) {
	    if($state->node_name eq '#text') {
		my $text_atoms = $state->text_atoms;
		ok(defined($text_atoms),
		   'text_atoms defined for cdata state object');
		is(ref($text_atoms), 'ARRAY',
		   'text_atoms ARRAY reference');
		is(@$text_atoms, 3, 'there are 3 atoms');
		is($text_atoms->[0]->{cdata},   'f', "cdata f");
		is($text_atoms->[0]->{x},       0,   "x 0");
		is($text_atoms->[0]->{chunkID}, 0,   "chunkID 0");
		is($text_atoms->[0]->{blockID}, 0,   "blockID 0");
		is($text_atoms->[0]->{atomID},  0,   'atomID 0');

		is($text_atoms->[1]->{cdata},    'o', "cdata o");
		is($text_atoms->[1]->{x},         1,  "x 1");
		is($text_atoms->[1]->{new_chunk}, 1,  'new chunk');
		is($text_atoms->[1]->{chunkID},   1,  "chunkID 1");
		is($text_atoms->[1]->{blockID},   1,  "blockID 1");
		is($text_atoms->[1]->{atomID},    1,  'atomID 1');

		is($text_atoms->[2]->{cdata},    'obar', "cdata obar");
		is($text_atoms->[2]->{x},         2,  "x 2");
		is($text_atoms->[2]->{new_chunk}, 1,  'new chunk');
		is($text_atoms->[2]->{chunkID},   2,  "chunkID 2");
		is($text_atoms->[2]->{blockID},   2,  "blockID 2");
		is($text_atoms->[2]->{atomID},    2,  'atomID 2');
	    }
	}
	elsif($state->node_attributes->{id} eq 'te01') {
	    my $text_atoms = $state->text_atoms;
	    ok(defined($text_atoms),
		   'text_atoms defined for text state object');
	    is(ref($text_atoms), 'ARRAY',
	       'text_atoms ARRAY reference');
	    @expected_cdata = ('f', 'o', 'obar');
	    is(@$text_atoms, scalar(@expected_cdata),
	       sprintf('there are %d atoms', scalar(@expected_cdata)));
	    for(my $i=0;$i<@expected_cdata;$i++) {
		ok(defined($text_atoms->[$i]), 'atom is defined');
		is(ref($text_atoms->[$i]), 'HASH',
		   'atom is HASH reference');
		is($text_atoms->[$i]->{cdata}, $expected_cdata[$i],
		   "cdata $expected_cdata[$i]");
	    }
	}
    });
    $rasterize->rasterize(svg => $svg);

    ok(1);
    ok(1, '---- text with tspan position inheritance ----');
    $rasterize = SVG::Rasterize->new;
    $svg       = SVG->new(width => 400, height => 300);
    $svg->firstChild->attrib('id' => 'svg');
    $node = $svg->group(id => 'g01');
    $text = $node->text(id => 'te01', dy => '1 2 3 4 5 6');
    $node = $text->tspan(id => 'ts01', dy => '7 8');
    $node->cdata('foo');
    $node = $text->tspan(id => 'ts02');
    $node->cdata('bar');
    $rasterize->end_node_hook(sub {
	my ($rasterize, $state) = @_;
	if($state->node_name eq '#text' and $state->cdata eq 'foo') {
	    my $text_atoms = $state->text_atoms;
	    ok(defined($text_atoms),
	       'text_atoms defined for cdata state object');
	    is(ref($text_atoms), 'ARRAY',
	       'text_atoms ARRAY reference');
	    is(@$text_atoms, 3, 'there is 3 atom');
	    is($text_atoms->[0]->{cdata},   'f', 'cdata f');
	    is($text_atoms->[0]->{dy},      7,    'dy 7');
	    is($text_atoms->[0]->{chunkID}, 0,    'chunkID 0');
	    is($text_atoms->[0]->{blockID}, 0,    'blockID 0');
	    is($text_atoms->[0]->{atomID},  0,    'atomID 0');
	    is($text_atoms->[1]->{cdata},   'o',  'cdata o');
	    is($text_atoms->[1]->{dy},      8,    'dy 8');
	    is($text_atoms->[1]->{chunkID}, 0,    'chunkID 0');
	    is($text_atoms->[1]->{blockID}, 0,    'blockID 0');
	    is($text_atoms->[1]->{atomID},  1,    'atomID 1');
	    is($text_atoms->[2]->{cdata},   'o',  'cdata o');
	    is($text_atoms->[2]->{dy},      1,    'dy 1');
	    is($text_atoms->[2]->{chunkID}, 0,    'chunkID 0');
	    is($text_atoms->[2]->{blockID}, 0,    'blockID 0');
	    is($text_atoms->[2]->{atomID},  2,    'atomID 2');
	}
	if($state->node_name eq '#text' and $state->cdata eq 'bar') {
	    my $text_atoms = $state->text_atoms;
	    ok(defined($text_atoms),
	       'text_atoms defined for cdata state object');
	    is(ref($text_atoms), 'ARRAY',
	       'text_atoms ARRAY reference');
	    is(@$text_atoms, 3, 'there is 3 atom');
	    is($text_atoms->[0]->{cdata},   'b', 'cdata b');
	    is($text_atoms->[0]->{dy},      2,    'dy 2');
	    is($text_atoms->[0]->{chunkID}, 0,    'chunkID 0');
	    is($text_atoms->[0]->{blockID}, 0,    'blockID 0');
	    is($text_atoms->[0]->{atomID},  3,    'atomID 3');
	    is($text_atoms->[1]->{cdata},   'a',  'cdata a');
	    is($text_atoms->[1]->{dy},      3,    'dy 3');
	    is($text_atoms->[1]->{chunkID}, 0,    'chunkID 0');
	    is($text_atoms->[1]->{blockID}, 0,    'blockID 0');
	    is($text_atoms->[1]->{atomID},  4,    'atomID 4');
	    is($text_atoms->[2]->{cdata},   'r',  'cdata r');
	    is($text_atoms->[2]->{dy},      4,    'dy 4');
	    is($text_atoms->[2]->{chunkID}, 0,    'chunkID 0');
	    is($text_atoms->[2]->{blockID}, 0,    'blockID 0');
	    is($text_atoms->[2]->{atomID},  5,    'atomID 5');
	}
    });
    $rasterize->rasterize(svg => $svg);
}

state_cdata;
font_properties;
process_character_positions;
split_into_atoms;

t/100_ignored_elements.t  view on Meta::CPAN

    lives_ok(sub { $rasterize->rasterize(svg => $svg) },
	     'comment in group');
}

sub ignored_elements {
    my $rasterize;
    my $svg;

    $rasterize = SVG::Rasterize->new(width => 400, height => 300);
    $svg       = SVG->new;
    $svg->desc->cdata('foo');
    lives_ok(sub { $rasterize->rasterize(svg => $svg) },
	     'desc element in root');

    $rasterize = SVG::Rasterize->new(width => 400, height => 300);
    $svg       = SVG->new;
    $svg->g->desc->cdata('bar');
    lives_ok(sub { $rasterize->rasterize(svg => $svg) },
	     'desc element in group');

    $rasterize = SVG::Rasterize->new(width => 400, height => 300);
    $svg       = SVG->new;
    $svg->title->cdata('foo');
    lives_ok(sub { $rasterize->rasterize(svg => $svg) },
	     'title element in root');

    $rasterize = SVG::Rasterize->new(width => 400, height => 300);
    $svg       = SVG->new;
    $svg->metadata->cdata('foo');
    lives_ok(sub { $rasterize->rasterize(svg => $svg) },
	     'metadata element in root');

    $rasterize = SVG::Rasterize->new(width => 400, height => 300);
    $svg       = SVG->new;
    $svg->g->metadata->cdata('bar');
    lives_ok(sub { $rasterize->rasterize(svg => $svg) },
	     'metadata element in group');

    $rasterize = SVG::Rasterize->new(width => 400, height => 300);
    $svg       = SVG->new;
    $svg->g->element('foo')->cdata('bar');
    throws_ok(sub { $rasterize->rasterize(svg => $svg) },
	      qr/Element \'foo\' is not a valid child of element \'g\'\./,
	     'foo element in group throws error');

    $SVG::Rasterize::IGNORED_NODES{foo} = 1;
    $rasterize = SVG::Rasterize->new(width => 400, height => 300);
    $svg       = SVG->new;
    $svg->g->element('foo')->cdata('bar');
    lives_ok(sub { $rasterize->rasterize(svg => $svg) },
	     'IGNORED_NODES rescues foo element in group');
}

comments;
ignored_elements;



( run in 0.820 second using v1.01-cache-2.11-cpan-454fe037f31 )