Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / tools / perl-5.8.0 / lib / site_perl / 5.8.0 / SVG / Element.pm
CommitLineData
86530b38
AT
1=pod
2
3=head1 NAME
4
5SVG::Element - Generate the element bits for SVG.pm
6
7=head1 AUTHOR
8
9Ronan Oger, ronan@roasp.com
10
11=head1 SEE ALSO
12
13perl(1),L<SVG>,L<SVG::XML>,L<SVG::Element>,L<SVG::Parser>, L<SVG::Manual>
14http://www.roasp.com/
15http://www.perlsvg.com/
16http://www.roitsystems.com/
17http://www.w3c.org/Graphics/SVG/
18
19=cut
20
21package SVG::Element;
22
23$VERSION = "2.26";
24
25use strict;
26use SVG::XML;
27use SVG::DOM;
28use SVG::Extension;
29use vars qw($AUTOLOAD %autosubs);
30
31my @autosubs=qw(
32 animateMotion animateColor animateTransform circle ellipse rect polyline
33 path polygon line title desc defs
34 altGlyph altGlyphDef altGlyphItem clipPath color-profile
35 cursor definition-src font-face-format font-face-name
36 font-face-src font-face-url foreignObject glyph
37 glyphRef hkern marker mask metadata missing-glyph
38 mpath switch symbol textPath tref tspan view vkern marker textbox
39 flowText style
40);
41
42%autosubs=map { $_ => 1 } @autosubs;
43
44#-------------------------------------------------------------------------------
45
46sub new ($$;@) {
47 my ($proto,$name,%attrs)=@_;
48 my $class=ref($proto) || $proto;
49 my $self={-name => $name};
50 foreach my $key (keys %attrs) {
51 next if $key=~/^\-/;
52 $self->{$key}=$attrs{$key};
53 }
54
55 return bless($self,$class);
56}
57
58#-------------------------------------------------------------------------------
59
60sub release ($) {
61 my $self=shift;
62
63 foreach my $key (keys(%{$self})) {
64 next if $key=~/^\-/;
65 if (ref($self->{$key})=~/^SVG/) {
66 eval { $self->{$key}->release; };
67 }
68 delete($self->{$key});
69 }
70
71 return $self;
72}
73
74sub xmlify ($) {
75 my $self = shift;
76 my $ns = $self->{-namespace} || $self->{-docref}->{-namespace} || undef;
77 my $xml = '';
78 #prep the attributes
79 my %attrs;
80 foreach my $k (keys(%{$self})) {
81 if($k=~/^\-/) { next; }
82 if(ref($self->{$k}) eq 'ARRAY') {
83 $attrs{$k}=join(', ',@{$self->{$k}});
84 } elsif(ref($self->{$k}) eq 'HASH') {
85 $attrs{$k}=cssstyle(%{$self->{$k}});
86 } elsif(ref($self->{$k}) eq '') {
87 $attrs{$k}=$self->{$k};
88 }
89 }
90 #prep the tag
91 if($self->{-comment}) {
92 $xml .= $self->xmlcomment($self->{-comment});
93 return $xml;
94 } elsif($self->{-pi}) {
95 $xml .= $self->xmlpi($self->{-pi});
96 return $xml;
97 } elsif ($self->{-name} eq 'document') {
98 #write the xml header
99 $xml .= $self->xmldecl;
100 #and write the dtd if this is inline
101 $xml .= $self->dtddecl unless $self->{-inline};
102 foreach my $k (@{$self->{-childs}}) {
103 if(ref($k)=~/^SVG::Element/) {
104 $xml .= $k->xmlify($ns);
105 }
106 }
107 return $xml;
108 }
109 if(defined $self->{-childs} ||
110 defined $self->{-cdata} ||
111 defined $self->{-CDATA} ||
112 defined $self->{-cdata_noxmlesc}) {
113 $xml .= $self->{-docref}->{-elsep};
114 $xml .= $self->{-docref}->{-indent} x $self->{-docref}->{-level};
115 $xml .= xmltagopen_ln($self->{-name},$ns,%attrs);
116 $self->{-docref}->{-level}++;
117 foreach my $k (@{$self->{-childs}}) {
118 if(ref($k)=~/^SVG::Element/) {
119 $xml .= $k->xmlify($ns);
120 }
121 }
122
123 if(defined $self->{-cdata}) {
124 $xml .= xmlescp($self->{-cdata});
125 }
126 if(defined $self->{-CDATA}) {
127 $xml .= '<![CDATA['.$self->{-CDATA}.']]>';
128 }
129 if(defined $self->{-cdata_noxmlesc}) {
130 $xml .= $self->{-cdata_noxmlesc};
131 }
132
133
134 #return without writing the tag out if it the document tag
135 $self->{-docref}->{-level}--;
136 $xml .= $self->{-docref}->{-elsep};
137 $xml .= $self->{-docref}->{-indent} x $self->{-docref}->{-level};
138 $xml .= xmltagclose_ln($self->{-name},$ns);
139 } else {
140 $xml .= $self->{-docref}->{-elsep};
141 $xml .= $self->{-docref}->{-indent} x $self->{-docref}->{-level};
142 $xml .= xmltag_ln($self->{-name},$ns,%attrs);
143 }
144 #return the finished tag
145 return $xml;
146}
147
148sub perlify {
149 my $self=shift;
150 my $code='';
151
152 #prep the attributes
153 my %attrs;
154 foreach my $k (keys(%{$self})) {
155 if($k=~/^\-/) { next; }
156 if(ref($self->{$k}) eq 'ARRAY') {
157 $attrs{$k}=join(', ',@{$self->{$k}});
158 } elsif(ref($self->{$k}) eq 'HASH') {
159 $attrs{$k}=cssstyle(%{$self->{$k}});
160 } elsif(ref($self->{$k}) eq '') {
161 $attrs{$k}=$self->{$k};
162 }
163 }
164
165 if($self->{-comment}) {
166 $code .= "->comment($self->{-comment})";
167 return $code;
168 } elsif($self->{-pi}) {
169 $code .= "->pi($self->{-pi})";
170 return $code;
171 } elsif ($self->{-name} eq 'document') {
172 #write the xml header
173 #$xml .= $self->xmldecl;
174 #and write the dtd if this is inline
175 #$xml .= $self->dtddecl unless $self->{-inline};
176 foreach my $k (@{$self->{-childs}}) {
177 if(ref($k)=~/^SVG::Element/) {
178 $code .= $k->perlify();
179 }
180 }
181 return $code;
182 }
183
184 if (defined $self->{-childs}) {
185 $code .= $self->{-docref}->{-elsep};
186 $code .= $self->{-docref}->{-indent} x $self->{-docref}->{-level};
187 $code .= $self->{-name}.'('.(join ', ',(map { "$_=>'$attrs{$_}'"} sort keys %attrs)).')';
188 if ($self->{-cdata}) {
189 $code.="->cdata($self->{-cdata})";
190 } elsif ($self->{-CDATA}) {
191 $code.="->CDATA($self->{-CDATA})";
192 } elsif ($self->{-cdata_noxmlesc}) {
193 $code.="->cdata_noxmlesc($self->{-cdata_noxmlesc})";
194 }
195
196 $self->{-docref}->{-level}++;
197 foreach my $k (@{$self->{-childs}}) {
198 if(ref($k)=~/^SVG::Element/) {
199 $code .= $k->perlify();
200 }
201 }
202 $self->{-docref}->{-level}--;
203 } else {
204 $code .= $self->{-docref}->{-elsep};
205 $code .= $self->{-docref}->{-indent} x $self->{-docref}->{-level};
206 $code .= $self->{-name}.'('.(join ', ',(map { "$_=>'$attrs{$_}'"} sort keys %attrs)).')';
207 }
208
209 return $code;
210}
211*toperl=\&perlify;
212
213
214sub addchilds ($@) {
215 my $self=shift;
216 push @{$self->{-childs}},@_;
217 return $self;
218}
219
220=pod
221
222=head2 tag (alias: element)
223
224$tag = $SVG->tag($name, %attributes)
225
226Generic element generator. Creates the element named $name with the attributes
227specified in %attributes. This method is the basis of most of the explicit
228element generators.
229
230B<Example:>
231
232 my $tag = $SVG->tag('g', transform=>'rotate(-45)');
233
234=cut
235
236sub tag ($$;@) {
237 my ($self,$name,%attrs)=@_;
238
239 unless ($self->{-parent}) {
240 #traverse down the tree until you find a non-document entry
241 while ($self->{-document}) {$self = $self->{-document}}
242 }
243 my $tag=new SVG::Element($name,%attrs);
244
245 #define the element namespace
246 $tag->{-namespace}=$attrs{-namespace} if ($attrs{-namespace});
247
248 #add the tag to the document element
249 $tag->{-docref} = $self->{-docref};
250
251 #create the empty idlist hash ref unless it already exists
252 $tag->{-docref}->{-idlist} = {}
253 unless (defined $tag->{-docref}->{-idlist});
254
255 #verify that the current id is unique. compain on exception
256 #>>>TBD: add -strictids option to disable this check if desired
257 if ($tag->{id}) {
258 if ($self->getElementByID($tag->{id})) {
259 $self->error($tag->{id} => "ID already exists in document");
260 return undef;
261 }
262 }
263
264 #add the current id reference to the document id hash
265 $tag->{-docref}->{-idlist}->{$tag->{id}} = $tag if defined ($tag->{id});
266
267 #create the empty idlist hash ref unless it already exists
268 $tag->{-docref}->{-elist} = {}
269 unless (defined $tag->{-docref}->{-elist});
270
271 #create the empty idlist hash ref unless it already exists
272 $tag->{-docref}->{-elist}->{$tag->{-name}} = []
273 unless (defined $tag->{-docref}->{-elist}->{$tag->{-name}});
274
275 #add the current element ref to the corresponding element-hash array
276 # -elist is a hash of element names. key name is element, content is object ref.
277
278 # add the reference to $tag to the array of refs that belong to the
279 # key $tag->{-name}.
280 unshift @{$tag->{-docref}->{-elist}->{$tag->{-name}}},$tag;
281
282 # attach element to the DOM of the document
283 $tag->{-parent}=$self;
284 $tag->{-parentname}=$self->{-name};
285 $self->addchilds($tag);
286
287 return($tag);
288}
289
290*element=\&tag;
291
292=pod
293
294=head2 anchor
295
296$tag = $SVG->anchor(%attributes)
297
298Generate an anchor element. Anchors are put around objects to make them
299'live' (i.e. clickable). It therefore requires a drawn object or group element
300as a child.
301
302B<Example:>
303
304 # generate an anchor
305 $tag = $SVG->anchor(
306 -href=>'http://here.com/some/simpler/SVG.SVG'
307 );
308 # add a circle to the anchor. The circle can be clicked on.
309 $tag->circle(cx=>10,cy=>10,r=>1);
310
311 # more complex anchor with both URL and target
312 $tag = $SVG->anchor(
313 -href => 'http://somewhere.org/some/other/page.html',
314 -target => 'new_window'
315 );
316
317=cut
318
319sub anchor {
320 my ($self,%attrs)=@_;
321 my $an=$self->tag('a',%attrs);
322 $an->{'xlink:href'}=$attrs{-href} if(defined $attrs{-href});
323 $an->{'target'}=$attrs{-target} if(defined $attrs{-target});
324 return($an);
325}
326
327sub svg {
328 my ($self,%attrs)=@_;
329 my $svg=$self->tag('svg',%attrs);
330 $svg->{'height'} = '100%' unless ($svg->{'height'});
331 $svg->{'width'} = '100%' unless ($svg->{'width'});
332 return($svg);
333}
334
335=pod
336
337=head2 circle
338
339$tag = $SVG->circle(%attributes)
340
341Draw a circle at (cx,cy) with radius r.
342
343B<Example:>
344
345 my $tag = $SVG->circlecx=>4, cy=>2, r=>1);
346
347=cut
348
349=pod
350
351=head2 ellipse
352
353$tag = $SVG->ellipse(%attributes)
354
355Draw an ellipse at (cx,cy) with radii rx,ry.
356
357B<Example:>
358
359 my $tag = $SVG->ellipse(
360 cx=>10, cy=>10,
361 rx=>5, ry=>7,
362 id=>'ellipse',
363 style=>{
364 'stroke'=>'red',
365 'fill'=>'green',
366 'stroke-width'=>'4',
367 'stroke-opacity'=>'0.5',
368 'fill-opacity'=>'0.2'
369 }
370 );
371
372=cut
373
374=pod
375
376=head2 rectangle (alias: rect)
377
378$tag = $SVG->rectangle(%attributes)
379
380Draw a rectangle at (x,y) with width 'width' and height 'height' and side radii
381'rx' and 'ry'.
382
383B<Example:>
384
385 $tag = $SVG->rectangle(
386 x=>10, y=>20,
387 width=>4, height=>5,
388 rx=>5.2, ry=>2.4,
389 id=>'rect_1'
390 );
391
392=cut
393
394sub rectangle ($;@) {
395 my ($self,%attrs)=@_;
396 return $self->tag('rect',%attrs);
397}
398
399=pod
400
401=head2 image
402
403 $tag = $SVG->image(%attributes)
404
405Draw an image at (x,y) with width 'width' and height 'height' linked to image
406resource '-href'. See also L<"use">.
407
408B<Example:>
409
410 $tag = $SVG->image(
411 x=>100, y=>100,
412 width=>300, height=>200,
413 '-href'=>"image.png", #may also embed SVG, e.g. "image.SVG"
414 id=>'image_1'
415 );
416
417B<Output:>
418
419 <image xlink:href="image.png" x="100" y="100" width="300" height="200"/>
420
421=cut
422
423sub image ($;@) {
424 my ($self,%attrs)=@_;
425 my $im=$self->tag('image',%attrs);
426 $im->{'xlink:href'}=$attrs{-href} if(defined $attrs{-href});
427 return $im;
428}
429
430=pod
431
432=head2 use
433
434$tag = $SVG->use(%attributes)
435
436Retrieve the content from an entity within an SVG document and apply it at
437(x,y) with width 'width' and height 'height' linked to image resource '-href'.
438
439B<Example:>
440
441 $tag = $SVG->use(
442 x=>100, y=>100,
443 width=>300, height=>200,
444 '-href'=>"pic.SVG#image_1",
445 id=>'image_1'
446 );
447
448B<Output:>
449
450 <use xlink:href="pic.SVG#image_1" x="100" y="100" width="300" height="200"/>
451
452According to the SVG specification, the 'use' element in SVG can point to a
453single element within an external SVG file.
454
455=cut
456
457sub use ($;@) {
458 my ($self,%attrs)=@_;
459 my $u=$self->tag('use',%attrs);
460 $u->{'xlink:href'}=$attrs{-href} if(defined $attrs{-href});
461 return $u;
462}
463
464=pod
465
466=head2 polygon
467
468$tag = $SVG->polygon(%attributes)
469
470Draw an n-sided polygon with vertices at points defined by a string of the form
471'x1,y1,x2,y2,x3,y3,... xy,yn'. The L<"get_path"> method is provided as a
472convenience to generate a suitable string from coordinate data.
473
474B<Example:>
475
476 # a five-sided polygon
477 my $xv = [0,2,4,5,1];
478 my $yv = [0,0,2,7,5];
479
480 $points = $a->get_path(
481 x=>$xv, y=>$yv,
482 -type=>'polygon'
483 );
484
485 $c = $a->polygon(
486 %$points,
487 id=>'pgon1',
488 style=>\%polygon_style
489 );
490
491SEE ALSO:
492
493L<"polyline">, L<"path">, L<"get_path">.
494
495=cut
496
497=pod
498
499=head2 polyline
500
501$tag = $SVG->polyline(%attributes)
502
503Draw an n-point polyline with points defined by a string of the form
504'x1,y1,x2,y2,x3,y3,... xy,yn'. The L<"get_path"> method is provided as a
505convenience to generate a suitable string from coordinate data.
506
507B<Example:>
508
509 # a 10-pointsaw-tooth pattern
510 my $xv = [0,1,2,3,4,5,6,7,8,9];
511 my $yv = [0,1,0,1,0,1,0,1,0,1];
512
513 $points = $a->get_path(
514 x=>$xv, y=>$yv,
515 -type=>'polyline',
516 -closed=>'true' #specify that the polyline is closed.
517 );
518
519 my $tag = $a->polyline (
520 %$points,
521 id=>'pline_1',
522 style=>{
523 'fill-opacity'=>0,
524 'stroke-color'=>'rgb(250,123,23)'
525 }
526 );
527
528=head2 line
529
530$tag = $SVG->line(%attributes)
531
532Draw a straight line between two points (x1,y1) and (x2,y2).
533
534B<Example:>
535
536 my $tag = $SVG->line(
537 id=>'l1',
538 x1=>0, y1=>10,
539 x2=>10, y2=>0
540 );
541
542To draw multiple connected lines, use L<"polyline">.
543
544=head2 text
545
546$text = $SVG->text(%attributes)->cdata();
547
548$text_path = $SVG->text(-type=>'path');
549$text_span = $text_path->text(-type=>'span')->cdata('A');
550$text_span = $text_path->text(-type=>'span')->cdata('B');
551$text_span = $text_path->text(-type=>'span')->cdata('C');
552
553
554define the container for a text string to be drawn in the image.
555
556B<Input:>
557 -type = path type (path | polyline | polygon)
558 -type = text element type (path | span | normal [default])
559
560B<Example:>
561
562 my $text1 = $SVG->text(
563 id=>'l1', x=>10, y=>10
564 )->cdata('hello, world');
565
566 my $text2 = $SVG->text(
567 id=>'l1', x=>10, y=>10, -cdata=>'hello, world');
568
569 my $text = $SVG->text(
570 id=>'tp', x=>10, y=>10 -type=>path)
571 ->text(id=>'ts' -type=>'span')
572 ->cdata('hello, world');
573
574SEE ALSO:
575
576 L<"desc">, L<"cdata">.
577
578=cut
579
580sub text ($;@) {
581 my ($self,%attrs)=@_;
582 my $pre = '';
583 $pre = $attrs{-type} || 'std';
584 my %get_pre = (std=>'text',
585 path=>'textPath',
586 span=>'tspan',);
587
588 $pre = $get_pre{lc($pre)};
589 my $text=$self->tag($pre,%attrs);
590 $text->{'xlink:href'} = $attrs{-href} if(defined $attrs{-href});
591 $text->{'target'} = $attrs{-target} if(defined $attrs{-target});
592 return($text);
593}
594
595=pod
596
597=head2 title
598
599$tag = $SVG->title(%attributes)
600
601Generate the title of the image.
602
603B<Example:>
604
605 my $tag = $SVG->title(id=>'document-title')->cdata('This is the title');
606
607=cut
608
609=pod
610
611=head2 desc
612
613$tag = $SVG->desc(%attributes)
614
615Generate the description of the image.
616
617B<Example:>
618
619 my $tag = $SVG->desc(id=>'document-desc')->cdata('This is a description');
620
621=head2 comment
622
623$tag = $SVG->comment(@comments)
624
625Generate the description of the image.
626
627B<Example:>
628
629 my $tag = $SVG->comment('comment 1','comment 2','comment 3');
630
631=cut
632
633sub comment ($;@) {
634 my ($self,@text)=@_;
635 my $tag = $self->tag('comment');
636 $tag->{-comment} = [@text];
637 return $tag;
638}
639
640=pod
641
642$tag = $SVG->pi(@pi)
643
644Generate a set of processing instructions
645
646B<Example:>
647
648 my $tag = $SVG->pi('instruction one','instruction two','instruction three');
649
650 returns:
651 <lt>?instruction one?<gt>
652 <lt>?instruction two?<gt>
653 <lt>?instruction three?<gt>
654
655=cut
656
657
658sub pi ($;@) {
659 my ($self,@text)=@_;
660 my $tag = $self->tag('pi');
661 $tag->{-pi} = [@text];
662 return $tag;
663}
664
665=pod
666
667=head2 script
668
669$tag = $SVG->script(%attributes)
670
671Generate a script container for dynamic (client-side) scripting using
672ECMAscript, Javascript or other compatible scripting language.
673
674B<Example:>
675
676 my $tag = $SVG->script(-type=>"text/ecmascript");
677
678 # populate the script tag with cdata
679 # be careful to manage the javascript line ends.
680