<?php
//      Copyright (c) 2008, 2009, 2010 Frank Bruder
/*
 *      Redistribution and use in source and binary forms, with or without
 *      modification, are permitted provided that the following conditions are
 *      met:
 *      
 *      * Redistributions of source code must retain the above copyright
 *        notice, this list of conditions and the following disclaimer.
 *      * Redistributions in binary form must reproduce the above
 *        copyright notice, this list of conditions and the following disclaimer
 *        in the documentation and/or other materials provided with the
 *        distribution.
 *      
 *      THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *      "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *      LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *      A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *      OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *      SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *      LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *      DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *      THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *      (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *      OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/*
_________________________________________

        visit my website or don't
http://purl.org/NET/2008,frankbruder/home
_________________________________________


This script displays pictures with accompanying texts in thought bubbles.

The above license applies to this script, but not - unless explicitly stated
- to any of the content stored in other files which is displayed using this
script.
This script can link to its own source code, but that link can be deactivated
in the customization settings below. By using this script on your website
with the source code link deactivated, you provide site visitors with the
output created by this script, but you're not redistributing this software,
so it's perfectly legal to deactivate the source code link, and the lincense
does not create any obligations for you in that case.


The naming scheme for the picture and text files can be customised, but the
filenames have to contain numbers, and it is assumed that they are numbered
consecutively. Omiting numbers would break the navigation.

The text files should be UTF-8 encoded. XML type numerical character
references (e.g. &#x263a; or &#9786;) can be used as well as the entity
reference &amp; , so it's also possible to use pure ASCII in the text files.

Image files can be in JPEG/JFIF or PNG format and their filenames must end
in '.jpg', '.jpeg', or '.png' (all lowercase!)

There may be only a picture with no text, or only a text with no picture for
any number. Both these cases are handled.

Unrecognized HTTP GET parameters get reproduced in the navigation links. So
they can be used in the customization settings in order to use the same
script file for multiple different series of content.


Sample code snippet for embedding this script in an HTML document:

<object type="image/svg+xml" data="showThought.php" width="100%" height="500">
  <param name="src"         value="showThought.php">
  <!-- fallback content: -->
  <a href="http://wiki.svg.org/Viewer_Matrix" title="link to SVG Viewer Matrix">
  So you&#8217;re the one who uses a non-SVG-enabled browser. You&#8217;re
  holding back the whole internet, you know that?</a>
  <!-- end of fallback content -->
</object>

The <param> tag is only needed for visitors of your site who use the Adobe
SVG Viewer. It is not required for standard conformance.

*/
error_reporting(E_ERROR|E_WARNING|E_PARSE|E_USER_ERROR|E_DEPRECATED);
define('yes', TRUE);
define('no' , FALSE);

##################################
##--  Customization settings  --##

##- External PHP file with customization settings -##
 #  Remove that line to use only the settings defined below
 $settings = 'settings.php';


##- Title -##
 $title = 'Just Thinking...';


##- Link to homepage -##
 $home = 'index.php';	# URL
 $thome = "&#8216;$title&#8217; home page";	# title


##- Titles to be used for navigation links -##
 #  Most browsers show them as tooltips on mouseover
 $next = 'Next';
 $previous = 'Previous';
 $first = 'First';
 $current = 'Current';


##- Background Colors -##
 #  May be omitted
 $backgroundColor      = '#000000';
 $backgroundGradientTo = '#cccccc';


##- takes effect on the positioning of the navigation links -##
 #  must be 'ltr' or 'rtl'
 $dir = 'ltr';


##- Parts of image/text filenames before and after the numbers -##
 #  The suffix '.jpg', '.jpeg', or '.png' for images isn't part of $ipost,
 #  because they are added automatically.
 $ipre = 'thinking';	# first part of image names
 $ipost = '';	# third part of image names (second part is the number)
 $ipath = substr($_SERVER['SCRIPT_NAME'], 0, strrpos($_SERVER['SCRIPT_NAME'], '/')+1); # is prepended before the image filename in the image element's xlink:href attribute. set to empty string to use relative paths.
 $tpre = $ipre;	# first part of text file names
 $tpost = '.txt';	# third part of text file names (second part is the number)


##- Index number of first image/text file -##
 #  Typically 1, or 0 if you prefer, but may be any number
 $start = 1;


##- Default text file, image, or text -##
 #  Will be shown if no image or text file with the requested number exists
 $tdefault = $tpre . 'error' . $tpost;
 $idefault = $ipre . 'error' . $ipost . '.png';
 $tdefaultText = 'ERROR:
This strip
does not exist.';


##- Whether to add a link to this source code -##
 #  You don't have to
 $source = yes;
 $sourcet = 'view source code'; # link title
 $nsource = 'showsource'; # name of query variable for viewing the source code
 $ndownload = 'download'; # name of query variable for downloading the source code


##- Variable name for index number to be used in query strings -##
 #  This is part of the URLs used to link to a specific strip
 $nvar = 'number';


##- Link to this page -##
 #  Can be customized to point to a PURL with partial redirect
 $here = yes;
 $herepre = "${_SERVER['SCRIPT_NAME']}?$nvar="; # part before the number
 $herepost = ''; # part after the number
 $heretitle = 'Permalink'; # title


##- Font size and line spacing in user coordinates -##
 #  Only the ratio $tspace/$fsize has a visual effect.
 #  Everything is scaled relative to the text, so the
 #  only way to change the visible font size is by
 #  adjusting the line breaks in your texts.
 $fsize = 30;
 $tspace = $fsize;


##- Whether to deliver the SVG inline in XHTML or as standalone SVG
 $inline = no;

##--  End of customization settings  --##
#########################################
##--  Actual source code  --##

##- Include external customization file -##
if($settings && file_exists($settings)) {
  include $settings;
}

##- Output own source code, if requested -##
if($source && (isset($_GET[$nsource])||isset($_GET[$ndownload]))) {
  if(isset($_GET[$ndownload])) {
    header('Content-Type: application/x-php');
    header('Content-Disposition: attachment');
  } else {
    header('Content-Type: text/plain; charset=UTF-8');
  }
  @readfile(__FILE__);
  
  exit();

}

##- Function to test for existence of a strip -##
function exists($number) {
  global $ipre, $tpre, $ipost, $tpost;
  return (file_exists($tpre . $number . $tpost) || file_exists($ipre . $number . $ipost . '.jpg') || file_exists($ipre . $number . $ipost . '.jpeg') || file_exists($ipre . $number . $ipost . '.png'));
}

##- Read strip number from query string -##
if(isset($_GET[$nvar])) {
  $number = (int) $_GET[$nvar];
} else {
  ##- If no strip number given then find the latest strip -##
  $i = 1;
  while(exists($start + $i - 1)) {
    $i <<= 1;
  }
  $x = $i;
  $i >>= 1;
  $j = $i >> 1;
  while($j > 0) {
    if(exists($start + ($i | $j) - 1)) {
      $i |= $j;
    }
    $j >>= 1;
  }
  $number = $start + $i - 1;
}

##- Put together image filename -##
#   Firstly with '.jpg' extension.
$ifile = $ipre . $number . $ipost . '.jpg';

#   If no such file exists then try '.jpeg' and then '.png' extensions.
if(! file_exists($ifile)) {
  $ifile = $ipre . $number . $ipost . '.jpeg';

  if(! file_exists($ifile)) {
    $ifile = $ipre . $number . $ipost . '.png';

    # If no PNG exists either then set to empty string.
    # This is our way to remember that we don't have an image file
    if(! file_exists($ifile)) {
      $ifile = '';
    }
  }
}

##- Put together text filename -##
$tfile = $tpre . $number . $tpost;

#   and read the text into an array
if(file_exists($tfile)) {
  $text = file($tfile, FILE_IGNORE_NEW_LINES | FILE_TEXT);
}

##- If neither image nor text were found then try default (error) values -##
if(!($text || $ifile)) {
  if($tdefault && file_exists($tdefault)) {
    $text = file($tdefault, FILE_IGNORE_NEW_LINES | FILE_TEXT);
  } else if($tdefaultText) {
    $text = preg_split('/\n/', $tdefaultText);
  }
  if($idefault && file_exists($idefault)) {
    $ifile = $idefault;
  }
}

##- function to produce XML safe attribute values -##
function attribute_escape($string) {
	return str_replace(array('&', '"', '\''), array('&amp;', '&#34;', '&#39;'), $string);
}

##- Put together links -##
$self = $_SERVER['SCRIPT_NAME'];

# keep all unknown parameters
# maybe they are interpreted in the customization part
$otherparameters = '';
foreach($_GET as $key => $value) {
	if($key!=$nvar) {
		$otherparameters .= '&'.rawurlencode($key).'='.rawurlencode($value);
	}
}

# create backward and forward links
if(exists($number-1)) {
  $frstlink = $self.'?'.$nvar.'='.$start.$otherparameters;
  $prevlink = $self.'?'.$nvar.'='.($number-1).$otherparameters;
  $frstlinkxml = attribute_escape($frstlink);
  $prevlinkxml = attribute_escape($prevlink);
}
if(exists($number+1)) {
  $nextlink = $self.'?'.$nvar.'='.($number+1).$otherparameters;
  $lastlink = $self;
  if($otherparameters) {
    $lastlink .= '?'.substr($otherparameters, 1);
  }
  $nextlinkxml = attribute_escape($nextlink);
  $lastlinkxml = attribute_escape($lastlink);
}

# create link to this strip
$herelink = "$herepre$number$herepost";
$herelinkxml = attribute_escape($herelink);

# if an invalid number was given, set the link to the current strip
# otherwise there would be no link at all in that case
if(!exists($number)) {
	$lastlink = $self;
	$lastlinkxml = attribute_escape($lastlink);
	$here = no;
}

# link to source code, if desired
if($source) {
	$sourcelink = $self.'?'.$nsource;
}

##- Assign links to their positions -##
#   depending on the direction
if ($dir=='ltr') {
  $rtdn = $lastlinkxml;
  $rtdnt = $current;
  $rght = $nextlinkxml;
  $rghtt = $next;
  $left = $prevlinkxml;
  $leftt = $previous;
  $ltup = $frstlinkxml;
  $ltupt = $first;
  $homepos = 0; # possible values are 0 to 3 for the four edges
  $sourcepos = 1; # possible values are 0 to 3 for the four edges
  $permalinkpos = 3; # possible values are 0 to 3 for the four edges
} elseif ($dir=='rtl') {
  $ltdn = $lastlinkxml;
  $ltdnt = $current;
  $left = $nextlinkxml;
  $leftt = $next;
  $rght = $prevlinkxml;
  $rghtt = $previous;
  $rtup = $frstlinkxml;
  $rtupt = $first;
  $homepos = 1; # possible values are 0 to 3 for the four edges
  $sourcepos = 0; # possible values are 0 to 3 for the four edges
  $permalinkpos = 2; # possible values are 0 to 3 for the four edges
}

##- Layout -##

$margin = 3;	# A margin

# horizontal and vertical semi-major axes of the text box' rounded edges
$hr = $fsize*1.4;
$vr =  $fsize;

# horizontal and vertical offset of the ellipses from the text box edges
$ehsp = 2*$fsize;
$evsp = 0;
# horizontal and vertical semi-major axes of the ellipses
$ehr = $hr;
$evr = $vr;

# vertical distance between centers of top and bottom trail ellipses
$bdist = $evr*7;

$N = 3;	# number of trail ellipses minus one

# Function used for positioning and scaling of trail ellipses
function brad($s) {
  return pow($s, 1.4);
}

# Get size of image, if present
if ($ifile) {
  $isize = getimagesize($ifile);
}

# Determin size and position of text box, if text exists
if ($text) {
  # Text width is roughly estimated based on the maximum
  # line length by characters
  $twidth = 0;
  foreach($text as $line) {
    $twidth = max($twidth, strlen(preg_replace('/\&(\#x?[0-9a-fA-F]+|amp)\;/', '#', $line))*$fsize*0.6);
  }
  $theight = $fsize + (count($text)-1)*$tspace;

  # Determin rectangle position (except for left offset)
  $rtop = $evsp + $evr + $margin;
  $rwidth = $twidth + 2*$hr;
  $rheight = $theight + 2*$vr;

  $texty = $rtop + $vr;	# vertical position for first line of text
}

# Determin size and position of image, if present
if($ifile) {
  if ($text) {
    # Align image verticalle at the center of the lowest but one trail ellipse.
    $itop = $rtop + $rheight + $evsp + $bdist*(1-brad(1/$N));

    # Image width equal to text box size and preserve aspect ratio.
    $iwidth = $rwidth;
    $iheight = $iwidth*$isize[1]/$isize[0];
  } else {
    # If no text is given then use pixel size of the image
    # one unit equals one image pixel.
    $itop = $margin;
    $iwidth = $isize[0];
    $iheight = $isize[1];
  }
  # Width and height of the whole content
  # i.e. without the navigation links at the left and right
  $cheight = $itop + $iheight + $margin;
  $cwidth = $iwidth;
} else {
  $cheight = $rtop + $rheight + $evsp + $evr + $margin;
  $cwidth = $rwidth;
}

$bwidth = $cheight/10;	# width of navigation bars
$brad1 = $bwidth*0.4;	# radius of large navigation links
$brad2 = $brad1*0.9;	# radius of smaller navigation links

# Make room for the left navigation bar
if($text) {
  $rleft = $margin + $bwidth;	# left edge position of text box
  $textx = $rleft + 0.5*$rwidth;	# horizontal coordinate for text
}
if($ifile) {
  $ileft = $margin + $bwidth;	# left edge of image
}

# Overall dimensions of content and navigation links
$width = $cwidth + 2*($bwidth + $margin);
$height = $cheight;

##- End of layout -##
##- Output -##
if($inline) {
	header('Content-Type: application/xhtml+xml');
} else {
	header('Content-Type: image/svg+xml');
}

echo "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\" ?>\n";
if($inline) {
	echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN" "http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd">' . "\n";
	echo "<html xmlns='http://www.w3.org/1999/xhtml' style='height:100%'>";
	echo "<head>";
	echo "<title>$title</title>";
	if($prevlink) {
		echo "<link rel='prev' href='$prevlinkxml' title='$previous' />";
	}
	if($nextlink) {
		echo "<link rel='next' href='$nextlinkxml' title='$next' />";
	}
	if($frstlink) {
		echo "<link rel='first' href='$frstlinkxml' title='$first' />";
	}
	if($lastlink) {
		echo "<link rel='last' href='$lastlinkxml' title='$current' />";
	}
	if($home) {
		echo "<link rel='index' href='$homexml' title='$thome' />";
	}
	echo "</head>";
	echo "<body style='height:100%'>";
	echo "<div style='position:fixed;top:0px;left:0px;right:0px;bottom:0px;background-color:$backgroundColor'>";
} else {
	echo '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Basic//EN"  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-basic.dtd">' . "\n";
}
echo "<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 $width $height'>";
echo "<title>$title</title>\n";
?><defs>
<?php if($backgroundGradientTo && ($backgroundColor != $backgroundGradientTo)) {
 echo '<radialGradient id="rgBG" cx="0.5" cy="0.5" r="0.5">';
 echo "<stop offset='0' stop-color='$backgroundGradientTo'/>";
 echo "<stop offset='0.3' stop-color='$backgroundGradientTo'/>";
 if($backgroundColor) {
  echo "<stop offset='1' stop-color='$backgroundColor'/>";
 } else {
  echo "<stop offset='1' stop-color='$backgroundGradientTo' stop-opacity='0'/>";
 }
 echo "</radialGradient>";
} ?>
<radialGradient id="rgFillGreen" cx="30%" cy="35%" r="80%">
 <stop offset="0" stop-color="#9fd"/>
 <stop offset="1" stop-color="#5f5"/>
</radialGradient>
<radialGradient id="rgFillBlue" cx="30%" cy="35%" r="80%">
 <stop offset="0" stop-color="#9df"/>
 <stop offset="1" stop-color="#55f"/>
</radialGradient>
<radialGradient id="rgFillGrey" cx="30%" cy="35%" r="80%">
 <stop offset="0" stop-color="#fff"/>
 <stop offset="1" stop-color="#555"/>
</radialGradient>
<radialGradient id="rgFillDark" cx="30%" cy="35%" r="80%">
 <stop offset="0" stop-color="#fff"/>
 <stop offset="1" stop-color="#000"/>
</radialGradient>
<radialGradient id="rgStrokeGreen" cx="90%" cy="80%" r="90%">
 <stop offset="0" stop-color="#eff"/>
 <stop offset="1" stop-color="#050"/>
</radialGradient>
<radialGradient id="rgStrokeBlue" cx="90%" cy="80%" r="90%">
 <stop offset="0" stop-color="#eff"/>
 <stop offset="1" stop-color="#005"/>
</radialGradient>
<radialGradient id="rgStrokeGrey" cx="90%" cy="80%" r="90%">
 <stop offset="0" stop-color="#fff"/>
 <stop offset="1" stop-color="#555"/>
</radialGradient>
<linearGradient id="lgStrokeGrey" x1="0%" y1="-40%" x2="0%" y2="100%">
 <stop offset="0" stop-color="#fff"/>
 <stop offset="0.5" stop-color="#222"/>
 <stop offset="0.75" stop-color="#888"/>
 <stop offset="1" stop-color="#fff"/>
</linearGradient>
<linearGradient id="lgFillBlue" x1="0%" y1="-40%" x2="0%" y2="100%">
 <stop offset="0" stop-color="#9df" stop-opacity="0.3"/>
 <stop offset="0.65" stop-color="#9df" stop-opacity="0.3"/>
 <stop offset="0.85" stop-color="#fff" stop-opacity="0.7"/>
 <stop offset="0.9" stop-color="#fff" stop-opacity="0.7"/>
 <stop offset="1" stop-color="#cef" stop-opacity="0.5"/>
</linearGradient>
<style type="text/css"><![CDATA[
<?php
 if($backgroundColor) {
   echo "svg { background-color:$backgroundColor; }";
 }
?>
 .btnfg {
  fill:url(#rgFillGrey);
  stroke:url(#rgStrokeGrey);
  stroke-width:8px;
 }
 a .btnfg {
  fill:url(#rgFillBlue);
  stroke:url(#rgStrokeBlue);
 }
 a:hover .btnfg {
  fill:url(#rgFillGreen);
  stroke:url(#rgStrokeGreen);
 }
 .btnbg {
  fill:url(#rgFillDark);
  stroke-width:1px;
  stroke:#555;
 }
 .ctrpn {
   fill:url(#lgFillBlue);
   stroke:url(#lgStrokeGrey);
   stroke-width:<?php echo($bwidth/20) ?>px;
 }
]]></style>
<script><![CDATA[ // makes this navigatable my mouse wheel
try {
window.addEventListener("DOMMouseScroll", function(evt) {<?php
if($prevlink) {
	echo " if(evt.detail<0) location = '$prevlink';";
}
if($nextlink) {
	echo " if(evt.detail>0) location = '$nextlink';";
}
?> evt.preventDefault(); }, false);
window.addEventListener("mousewheel", function(evt) {<?php
if($prevlink) {
	echo " if(evt.wheelDelta>0) location = '$prevlink';";
}
if($nextlink) {
	echo " if(evt.wheelDelta<0) location = '$nextlink';";
}
?> evt.preventDefault(); }, false);
} catch (exc) {}
]]></script>
</defs><?php

## these are redundant with the stylesheet, but CSS doesn't work in SVG Web
$btnfg = ' fill="url(#rgFillGrey)" stroke="url(#rgStrokeGrey)" stroke-width="8px"';
$btnbg = ' fill="url(#rgFillDark)" stroke-width="1px" stroke="#555"';
$ctrpn = ' fill="url(#lgFillBlue)" stroke="url(#lgStrokeGrey)" stroke-width="'.($bwidth/20).'"';
##

if($backgroundGradientTo && ($backgroundColor != $backgroundGradientTo)) {
  echo "<rect fill='url(#rgBG)' x='0' y='0' width='$width' height='$height'/>";
}
echo "<g id='nav'>";
$relw = 0.5;
$posx = $bwidth*(1-$relw)/2.5;
$posy = $bwidth*(1-$relw)/2.5;
$wd = $bwidth*$relw;
$ht = $height - 2*$posy;
$rd = $wd/2;
echo "<rect class='ctrpn'$ctrpn x='$posx' y='$posy' width='$wd' height='$ht' rx='$rd' ry='$rd'/>";

$posx = $width - $posx - $wd;
echo "<rect class='ctrpn'$ctrpn x='$posx' y='$posy' width='$wd' height='$ht' rx='$rd' ry='$rd'/>";


$posx = $bwidth/2;
$posy = $height/2;
if($left) { echo "<a xlink:href='$left' xlink:title='$leftt'>"; }
echo "<circle class='btnbg'$btnbg cx='$posx' cy='$posy' r='$brad1'/>";
echo "<path class='btnfg'$btnfg d='M19 -55a17 17 0 0 1 25 15v80a17 17 0 0 1 -25 15l-75 -40a17 17 0 0 1 0 -30z' transform='translate($posx $posy) scale(".($brad1/79.5).")'/>";
if($left) { echo "</a>"; }

$posx = $bwidth/2;
$posy = $height/2 - 2*$brad1;
if($ltup) {
echo "<a xlink:href='$ltup' xlink:title='$ltupt'>";
}
echo "<circle class='btnbg'$btnbg cx='$posx' cy='$posy' r='$brad2'/>";
if($ltup) {
  echo "<path class='btnfg'$btnfg d='M33 -27.5a8.5 8.5 0 0 1 12.5 7.5v40a8.5 8.5 0 0 1 -12.5 7.5l-37.5 -20v25a8.5 8.5 0 0 1 -8.5 8.5h-14a8.5 8.5 0 0 1 -8.5 -8.5v-65a8.5 8.5 0 0 1 8.5 -8.5h14a8.5 8.5 0 0 1 8.5 8.5v25z' transform='translate($posx $posy) scale(".($brad2/79.5).")'/>";
  echo "</a>";
}
$posx = $bwidth/2;
$posy = $height/2 + 2*$brad1;
if($ltdn) {
  echo "<a xlink:href='$ltdn' xlink:title='$ltdnt'>";
}
echo "<circle class='btnbg'$btnbg cx='$posx' cy='$posy' r='$brad2'/>";
if($ltdn) {
  echo "<path class='btnfg'$btnfg d='M33 -27.5a8.5 8.5 0 0 1 12.5 7.5v40a8.5 8.5 0 0 1 -12.5 7.5l-37.5 -20v25a8.5 8.5 0 0 1 -8.5 8.5h-14a8.5 8.5 0 0 1 -8.5 -8.5v-65a8.5 8.5 0 0 1 8.5 -8.5h14a8.5 8.5 0 0 1 8.5 8.5v25z' transform='translate($posx $posy) scale(".($brad2/79.5).")'/>";
  echo "</a>";
}


$posx = $width - $bwidth/2;
$posy = $height/2;

if($rght) { echo "<a xlink:href='$rght' xlink:title='$rghtt'>"; }
echo "<circle class='btnbg'$btnbg cx='$posx' cy='$posy' r='$brad1'/>";
echo "<path class='btnfg'$btnfg d='M-19 55a17 17 0 0 1 -25 -15v-80a17 17 0 0 1 25 -15l75 40a17 17 0 0 1 0 30z' transform='translate($posx $posy) scale(".($brad1/79.5).")'/>";
if($rght) { echo "</a>"; }

$posx = $width - $bwidth/2;
$posy = $height/2 - 2*$brad1;
if($rtup) {
  echo "<a xlink:href='$rtup' xlink:title='$rtupt'>";
}
echo "<circle class='btnbg'$btnbg cx='$posx' cy='$posy' r='$brad2'/>";
if($rtup) {
  echo "<path class='btnfg'$btnfg d='M-33 27.5a8.5 8.5 0 0 1 -12.5 -7.5v-40a8.5 8.5 0 0 1 12.5 -7.5l37.5 20v-25a8.5 8.5 0 0 1 8.5 -8.5h14a8.5 8.5 0 0 1 8.5 8.5v65a8.5 8.5 0 0 1 -8.5 8.5h-14a8.5 8.5 0 0 1 -8.5 -8.5v-25z' transform='translate($posx $posy) scale(".($brad2/79.5).")'/>";
  echo "</a>";
}
$posx = $width - $bwidth/2;
$posy = $height/2 + 2*$brad1;
if($rtdn) {
  echo "<a xlink:href='$rtdn' xlink:title='$rtdnt'>";
}
echo "<circle class='btnbg'$btnbg cx='$posx' cy='$posy' r='$brad2'/>";
if($rtdn) {
  echo "<path class='btnfg'$btnfg d='M-33 27.5a8.5 8.5 0 0 1 -12.5 -7.5v-40a8.5 8.5 0 0 1 12.5 -7.5l37.5 20v-25a8.5 8.5 0 0 1 8.5 -8.5h14a8.5 8.5 0 0 1 8.5 8.5v65a8.5 8.5 0 0 1 -8.5 8.5h-14a8.5 8.5 0 0 1 -8.5 -8.5v-25z' transform='translate($posx $posy) scale(".($brad2/79.5).")'/>";
  echo "</a>";
}

if($home) {
  $posx = ($homepos & 1)*($width-$bwidth) + $bwidth/2;
  $posy = ($homepos & 2)*($height-2*$bwidth)/2 + $bwidth;
  echo "<a xlink:href='$home' xlink:title='$thome' target='_top'>";
  echo "<path class='btnbg'$btnbg d='M-40 10l40 -50l40 50h-10v20h-13v-15h-8v15h-39v-20z' transform='translate($posx $posy) scale(".($brad1/40).")'/>";
  echo "<path class='btnfg'$btnfg style='stroke-width:1px;' d='M-25 15h8v8h-8z' transform='translate($posx $posy) scale(".($brad1/40).")'/>";
  echo "</a>";
}

if($here) {
  $posx = ($permalinkpos & 1)*($width-$bwidth) + $bwidth/2;
  $posy = ($permalinkpos & 2)*($height-2*$bwidth)/2 + $bwidth;
  echo "<a xlink:href='$herelinkxml' xlink:title='$heretitle' xlink:rel='http://www.w3.org/1999/xhtml/vocab#bookmark' target='_top'>";
  echo "<rect class='btnbg'$btnbg x='".($posx-$brad1)."' y='".($posy-$brad1)."' width='".(2*$brad1)."' height='".(2*$brad1)."' rx='".(0.5*$brad1)."' ry='".(0.5*$brad1)."'/>";
  echo "<path class='btnfg'$btnfg d='M-9 1l-41 -41 49 31 41 -41 -31 49 41 41 -49 -31 -41 41z' transform='translate($posx $posy) scale(".($brad1/79.5).")'/>";
  echo "</a>";
}

if($source) {
	$posx = ($sourcepos & 1)*($width-$bwidth) + $bwidth/2;
	$posy = ($sourcepos & 2)*($height-2*$bwidth)/2 + $bwidth;
	echo "<a xlink:href='$sourcelink' xlink:title='$sourcet' target='_top'>";
	echo "<rect x='".($posx-$brad1)."' y='".($posy-$brad1)."' width='".($brad1*2)."' height='".($brad1*2)."' visibility='hidden' pointer-events='fill'/>";
	echo "<ellipse class='btnbg'$btnbg cx='0' cy='29' rx='34' ry='12' transform='translate($posx $posy) scale(".($brad1/40).")'/>";
	echo "<path class='btnfg'$btnfg style='stroke-width:1px;' d='M0 19q12 -84 24 -48c8 24 -2 8 -7 2s-11 7 -17 7s-12 -13 -17 -7s-15 22 -7 -2q12 -36 24 48z' transform='translate($posx $posy) scale(".($brad1/40).")'/>";
	echo "<path class='btnfg'$btnfg style='stroke-width:1px;' d='M-16 25a20 15 0 0 1 32 0a34 17 0 0 1 -32 0z' transform='translate($posx $posy) scale(".($brad1/40).")'/>";
	echo "</a>";
}
echo "</g>";
if($ifile) {
  echo "<image xlink:href='$ipath$ifile' x='$ileft' y='$itop' width='$iwidth' height='$iheight' preserveAspectRatio='xMidYMin'/>";
}
if ($text) {
  echo "<g fill='#fff' stroke='#000'>";
  if ($ifile) {
    for($k = 0; $k < $N; $k++) {
      $s = brad($k/$N);
      $dx = 30*(-($N-$k)/$N + 0.5)*($N-$k)/$N;
      $dy = 1-$s;
      echo "<ellipse cx='".($rleft+$rwidth-$ehsp+$dx)."' cy='".($rtop+$rheight+$evsp+$bdist*$dy)."' rx='".(1-$s+$ehr*$s)."' ry='".(1-$s+$evr*$s)."'/>";
    }
  }
  echo "<ellipse cx='".($rleft+$rwidth-$ehsp)."' cy='".($rtop+$rheight+$evsp)."' rx='$ehr' ry='$evr'/>";
  echo "<rect x='$rleft' y='$rtop' width='$rwidth' height='$rheight' rx='$hr' ry='$vr'/>";
  echo "<ellipse cx='".($rleft+$ehsp)."' cy='".($rtop-$evsp)."' rx='$ehr' ry='$evr'/>";
  echo "</g>";

  $texty += $fsize;
  echo "<text font-size='{$fsize}px' font-family='sans-serif' xml:space='preserve' x='$textx' y='$texty'>";
  foreach ($text as $line) {
    if($line) {
      $line = str_replace('<', '&lt;', preg_replace('/\&(?!\#x?[0-9a-fA-F]+\;|amp\;)/', '&amp;', $line));
      echo "<tspan x='$textx' y='$texty' text-anchor='middle'> $line </tspan>";
    }
    $texty += $tspace;
  }
  echo "</text>";
}

echo "</svg>";
if($inline) {
	echo "</div></body></html>";
}

?>