3 # -*- perl -*- vim:set ft=perl sw=4 sts=4:
5 # Usage: relational-schema out.png RELATION:_Primary_Key,.Foreign_Key,Etc
6 # To clarifiy, specifiy the relation name, followed by a colon, followed by
7 # the attributes seperated by commas. Primary keys should be prefixed with
8 # an underscore, and foreign keys with a period.
9 # It is also possible to override or augment the functional dependencies by
10 # adding a second colon and additional specifications. Since this was
11 # unnecessary for the assignment, it is not documented here.
16 use vars qw($font $maxwidth $pd $fh);
21 my $out = shift or die "No output file specified.\n";
23 die "No rows.\n" unless (@rows);
25 my $image = new Image::Imlib2->new(1,1);
26 $image->add_font_path ("/usr/share/fonts/truetype/msttcorefonts");
27 $image->load_font($font);
28 ($fh, $fh) = $image->get_text_size("(Ay)");
29 $image = new Image::Imlib2->new($maxwidth, ($#rows+1)*($fh*2+$pd*12+2));
30 $image->add_font_path ("/usr/share/fonts/truetype/msttcorefonts");
31 $image->load_font($font);
32 $image->set_color(255,255,255,255);
33 #$image->fill_rectangle(0,0,$maxwidth,($#rows+1)*($fh*2+$pd*12+2));
36 my ($image, $text, $x, $y, $underline)=@_;
37 $image->load_font($font);
38 my ($w, $h) = $image->get_text_size($text);
39 $image->set_color(255,255,255,255);
40 $image->fill_rectangle($x,$y,$w+2*$pd+2,$fh+2*$pd+2);
41 $image->set_color(0,0,0,255);
42 $image->draw_rectangle($x,$y,$w+2*$pd+2,$fh+2*$pd+2);
43 $image->draw_text($x+$pd,$y+$pd,$text);
44 if(($underline||0)==1) { # Solid underline
45 $image->draw_line($x+$pd,$y+$pd+$fh,$x+$w+$pd,$y+$pd+$fh);
46 } elsif(($underline||0)==2) { # Dashed underline
47 for(my $i=0;$i<$w;$i+=5) {
48 $image->draw_line($x+$pd+$i,$y+$pd+$fh,
49 $x+$pd+($i+2>$w?$w$i+2),$y+$pd+$fh);
57 foreach my $row (@rows) {
58 my ($title,$element,@depends) = split (':',$row);
59 my @elements = split (',',$element);
62 my ($toffset)=(2*$pd);
63 while ($title =~ s/^>//) {
66 my ($offset) = ($toffset);
67 foreach $element (@elements) {
69 if ($element =~ s/^_//) {
72 } elsif ($element =~ s/^\.//) {
77 warn "Element $element in $title not marked as ".
78 "primary or foreign key.\n" if ($element=~/_ID$/);
80 my $o=draw_boxed_text($image,$element,$offset,$line+$fh+5*$pd,$under);
81 $elcenters{$element}=($offset+$o/2);
86 if((($#depends>=0 and $depends[0] eq 'auto') or $#depends=-1)
87 and $#in>=0 and $#out>=0) {
88 $depends[0]=(join(",",@out)."/".join(",",@in));
89 } elsif($#depends>=0 and $depends[0] eq 'auto') {
92 foreach my $depend (@depends) {
97 $image->set_color(0,(32*($updown>>1))%128,(64*($updown>>1))%256,255);
98 my ($out,$in) = split('/',$depend);
100 my @out = split(',', $out);
101 my @in = split(',', $in );
102 my @temp = sort { $elcenters{$a} <=> $elcenters{$b} } (@out, @in);
105 $near=$line+$fh+5*$pd-1;
106 $far=$line+$fh+1*$pd-1;
108 $near=$line+2*$fh+7*$pd+2;
109 $far=$line+2*$fh+11*$pd+2;
111 $image->draw_line($elcenters{$temp[0]}+$pd*($updown>>1),
112 $far,$elcenters{$temp[$#temp]}+$pd*($updown>>1),$far);
113 foreach $out (@out) {
114 $image->draw_line($elcenters{$out}+$pd*($updown>>1),
115 $far,$elcenters{$out}+$pd*($updown>>1),$near);
117 foreach $in (@in) { # Draw arrowheads
118 my $arrow = Image::Imlib2::Polygon->new();
119 $arrow->add_point($elcenters{$in}+$pd*($updown>>1),$near);
120 $arrow->add_point($elcenters{$in}+$pd+$pd*($updown>>1),
122 $arrow->add_point($elcenters{$in}-$pd+$pd*($updown>>1),
124 $arrow->add_point($elcenters{$in},$near);
126 $image->draw_line($elcenters{$in}+$pd*($updown>>1),
127 $far,$elcenters{$in}+$pd*($updown>>1),$near);
128 $image->draw_polygon($arrow,1);
132 $image->set_color(0,0,0,255);
133 $image->draw_text($toffset+$pd*2,$line+4*$pd-$shifttitle*(7*$pd/2),$title);
134 $line+=2*$fh+12*$pd+2;