function pre_render($im, &$map)
 {
     // don't bother drawing if there's no position - it's a template
     if (is_null($this->x)) {
         return;
     }
     if (is_null($this->y)) {
         return;
     }
     // apparently, some versions of the gd extension will crash
     // if we continue...
     if ($this->label == '' && $this->iconfile == '') {
         return;
     }
     // start these off with sensible values, so that bbox
     // calculations are easier.
     $icon_x1 = $this->x;
     $icon_x2 = $this->x;
     $icon_y1 = $this->y;
     $icon_y2 = $this->y;
     $label_x1 = $this->x;
     $label_x2 = $this->x;
     $label_y1 = $this->y;
     $label_y2 = $this->y;
     $boxwidth = 0;
     $boxheight = 0;
     $icon_w = 0;
     $icon_h = 0;
     $col = new Colour(-1, -1, -1);
     # print $col->as_string();
     // if a target is specified, and you haven't forced no background, then the background will
     // come from the SCALE in USESCALE
     if (!empty($this->targets) && $this->usescale != 'none') {
         $pc = 0;
         if ($this->scalevar == 'in') {
             $pc = $this->inpercent;
             $col = $this->colours[IN];
         }
         if ($this->scalevar == 'out') {
             $pc = $this->outpercent;
             $col = $this->colours[OUT];
         }
     } elseif ($this->labelbgcolour != array(-1, -1, -1)) {
         // $col=myimagecolorallocate($node_im, $this->labelbgcolour[0], $this->labelbgcolour[1], $this->labelbgcolour[2]);
         $col = new Colour($this->labelbgcolour);
     }
     $colicon = null;
     if (!empty($this->targets) && $this->useiconscale != 'none') {
         wm_debug("Colorising the icon\n");
         $pc = 0;
         $val = 0;
         if ($this->iconscalevar == 'in') {
             $pc = $this->inpercent;
             $col = $this->colours[IN];
             $val = $this->bandwidth_in;
         }
         if ($this->iconscalevar == 'out') {
             $pc = $this->outpercent;
             $col = $this->colours[OUT];
             $val = $this->bandwidth_out;
         }
         if ($this->iconscaletype == 'percent') {
             list($colicon, $node_iconscalekey, $icontag) = $map->NewColourFromPercent($pc, $this->useiconscale, $this->name);
         } else {
             // use the absolute value if we aren't doing percentage scales.
             list($colicon, $node_iconscalekey, $icontag) = $map->NewColourFromPercent($val, $this->useiconscale, $this->name, FALSE);
         }
     }
     // figure out a bounding rectangle for the label
     if ($this->label != '') {
         $padding = 4.0;
         $padfactor = 1.0;
         $this->proclabel = $map->ProcessString($this->label, $this, TRUE, TRUE);
         // if screenshot_mode is enabled, wipe any letters to X and wipe any IP address to 127.0.0.1
         // hopefully that will preserve enough information to show cool stuff without leaking info
         if ($map->get_hint('screenshot_mode') == 1) {
             $this->proclabel = screenshotify($this->proclabel);
         }
         list($strwidth, $strheight) = $map->myimagestringsize($this->labelfont, $this->proclabel);
         if ($this->labelangle == 90 || $this->labelangle == 270) {
             $boxwidth = $strheight * $padfactor + $padding;
             $boxheight = $strwidth * $padfactor + $padding;
             wm_debug("Node->pre_render: " . $this->name . " Label Metrics are: {$strwidth} x {$strheight} -> {$boxwidth} x {$boxheight}\n");
             $label_x1 = $this->x - $boxwidth / 2;
             $label_y1 = $this->y - $boxheight / 2;
             $label_x2 = $this->x + $boxwidth / 2;
             $label_y2 = $this->y + $boxheight / 2;
             if ($this->labelangle == 90) {
                 $txt_x = $this->x + $strheight / 2;
                 $txt_y = $this->y + $strwidth / 2;
             }
             if ($this->labelangle == 270) {
                 $txt_x = $this->x - $strheight / 2;
                 $txt_y = $this->y - $strwidth / 2;
             }
         }
         if ($this->labelangle == 0 || $this->labelangle == 180) {
             $boxwidth = $strwidth * $padfactor + $padding;
             $boxheight = $strheight * $padfactor + $padding;
             wm_debug("Node->pre_render: " . $this->name . " Label Metrics are: {$strwidth} x {$strheight} -> {$boxwidth} x {$boxheight}\n");
             $label_x1 = $this->x - $boxwidth / 2;
             $label_y1 = $this->y - $boxheight / 2;
             $label_x2 = $this->x + $boxwidth / 2;
             $label_y2 = $this->y + $boxheight / 2;
             $txt_x = $this->x - $strwidth / 2;
             $txt_y = $this->y + $strheight / 2;
             if ($this->labelangle == 180) {
                 $txt_x = $this->x + $strwidth / 2;
                 $txt_y = $this->y - $strheight / 2;
             }
             # $this->width = $boxwidth;
             # $this->height = $boxheight;
         }
         $map->nodes[$this->name]->width = $boxwidth;
         $map->nodes[$this->name]->height = $boxheight;
         # print "TEXT at $txt_x , $txt_y\n";
     }
     // figure out a bounding rectangle for the icon
     if ($this->iconfile != '') {
         $icon_im = NULL;
         $icon_w = 0;
         $icon_h = 0;
         if ($this->iconfile == 'rbox' || $this->iconfile == 'box' || $this->iconfile == 'round' || $this->iconfile == 'inpie' || $this->iconfile == 'outpie' || $this->iconfile == 'gauge' || $this->iconfile == 'nink') {
             wm_debug("Artificial Icon type " . $this->iconfile . " for {$this->name}\n");
             // this is an artificial icon - we don't load a file for it
             $icon_im = imagecreatetruecolor($this->iconscalew, $this->iconscaleh);
             imageSaveAlpha($icon_im, TRUE);
             $nothing = imagecolorallocatealpha($icon_im, 128, 0, 0, 127);
             imagefill($icon_im, 0, 0, $nothing);
             $fill = NULL;
             $ink = NULL;
             $aifill = new Colour($this->aiconfillcolour);
             $aiink = new Colour($this->aiconoutlinecolour);
             if ($aifill->is_copy() && !$col->is_none()) {
                 $fill = $col;
             } else {
                 if ($aifill->is_real()) {
                     $fill = $aifill;
                 }
             }
             if ($this->aiconoutlinecolour != array(-1, -1, -1)) {
                 $ink = $aiink;
             }
             if ($this->iconfile == 'box') {
                 if ($fill !== NULL && !$fill->is_none()) {
                     imagefilledrectangle($icon_im, 0, 0, $this->iconscalew - 1, $this->iconscaleh - 1, $fill->gdallocate($icon_im));
                 }
                 if ($ink !== NULL && !$ink->is_none()) {
                     imagerectangle($icon_im, 0, 0, $this->iconscalew - 1, $this->iconscaleh - 1, $ink->gdallocate($icon_im));
                 }
             }
             if ($this->iconfile == 'rbox') {
                 if ($fill !== NULL && !$fill->is_none()) {
                     imagefilledroundedrectangle($icon_im, 0, 0, $this->iconscalew - 1, $this->iconscaleh - 1, 4, $fill->gdallocate($icon_im));
                 }
                 if ($ink !== NULL && !$ink->is_none()) {
                     imageroundedrectangle($icon_im, 0, 0, $this->iconscalew - 1, $this->iconscaleh - 1, 4, $ink->gdallocate($icon_im));
                 }
             }
             if ($this->iconfile == 'round') {
                 $rx = $this->iconscalew / 2 - 1;
                 $ry = $this->iconscaleh / 2 - 1;
                 if ($fill !== NULL && !$fill->is_none()) {
                     imagefilledellipse($icon_im, $rx, $ry, $rx * 2, $ry * 2, $fill->gdallocate($icon_im));
                 }
                 if ($ink !== NULL && !$ink->is_none()) {
                     imageellipse($icon_im, $rx, $ry, $rx * 2, $ry * 2, $ink->gdallocate($icon_im));
                 }
             }
             if ($this->iconfile == 'nink') {
                 // print "NINK **************************************************************\n";
                 $rx = $this->iconscalew / 2 - 1;
                 $ry = $this->iconscaleh / 2 - 1;
                 $size = $this->iconscalew;
                 $quarter = $size / 4;
                 $col1 = $this->colours[OUT];
                 $col2 = $this->colours[IN];
                 assert('!is_null($col1)');
                 assert('!is_null($col2)');
                 imagefilledarc($icon_im, $rx - 1, $ry, $size, $size, 270, 90, $col1->gdallocate($icon_im), IMG_ARC_PIE);
                 imagefilledarc($icon_im, $rx + 1, $ry, $size, $size, 90, 270, $col2->gdallocate($icon_im), IMG_ARC_PIE);
                 imagefilledarc($icon_im, $rx - 1, $ry + $quarter, $quarter * 2, $quarter * 2, 0, 360, $col1->gdallocate($icon_im), IMG_ARC_PIE);
                 imagefilledarc($icon_im, $rx + 1, $ry - $quarter, $quarter * 2, $quarter * 2, 0, 360, $col2->gdallocate($icon_im), IMG_ARC_PIE);
                 if ($ink !== NULL && !$ink->is_none()) {
                     // XXX - need a font definition from somewhere for NINK text
                     $font = 1;
                     $instr = $map->ProcessString("{node:this:bandwidth_in:%.1k}", $this);
                     $outstr = $map->ProcessString("{node:this:bandwidth_out:%.1k}", $this);
                     list($twid, $thgt) = $map->myimagestringsize($font, $instr);
                     $map->myimagestring($icon_im, $font, $rx - $twid / 2, $ry - $quarter + $thgt / 2, $instr, $ink->gdallocate($icon_im));
                     list($twid, $thgt) = $map->myimagestringsize($font, $outstr);
                     $map->myimagestring($icon_im, $font, $rx - $twid / 2, $ry + $quarter + $thgt / 2, $outstr, $ink->gdallocate($icon_im));
                     imageellipse($icon_im, $rx, $ry, $rx * 2, $ry * 2, $ink->gdallocate($icon_im));
                     // imagearc($icon_im, $rx,$ry,$quarter*4,$quarter*4, 0,360, $ink->gdallocate($icon_im));
                 }
                 // print "NINK ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n";
             }
             // XXX - needs proper colours
             if ($this->iconfile == 'inpie' || $this->iconfile == 'outpie') {
                 # list($colpie,$node_iconscalekey,$icontag) = $map->NewColourFromPercent($pc, $this->useiconscale,$this->name);
                 if ($this->iconfile == 'inpie') {
                     $segment_angle = $this->inpercent / 100 * 360;
                 }
                 if ($this->iconfile == 'outpie') {
                     $segment_angle = $this->outpercent / 100 * 360;
                 }
                 $rx = $this->iconscalew / 2 - 1;
                 $ry = $this->iconscaleh / 2 - 1;
                 if ($fill !== NULL && !$fill->is_none()) {
                     imagefilledellipse($icon_im, $rx, $ry, $rx * 2, $ry * 2, $fill->gdallocate($icon_im));
                 }
                 if ($ink !== NULL && !$ink->is_none()) {
                     // imagefilledarc  ( resource $image  , int $cx  , int $cy  , int $width  , int $height  , int $start  , int $end  , int $color  , int $style  )
                     imagefilledarc($icon_im, $rx, $ry, $rx * 2, $ry * 2, 0, $segment_angle, $ink->gdallocate($icon_im), IMG_ARC_PIE);
                 }
                 if ($fill !== NULL && !$fill->is_none()) {
                     imageellipse($icon_im, $rx, $ry, $rx * 2, $ry * 2, $fill->gdallocate($icon_im));
                 }
                 // warn('inpie AICON not implemented yet [WMWARN99]');
             }
             // if($this->iconfile=='outpie') { warn('outpie AICON not implemented yet [WMWARN99]'); }
             if ($this->iconfile == 'gauge') {
                 wm_warn('gauge AICON not implemented yet [WMWARN99]');
             }
         } else {
             $this->iconfile = $map->ProcessString($this->iconfile, $this);
             if (is_readable($this->iconfile)) {
                 imagealphablending($im, true);
                 // draw the supplied icon, instead of the labelled box
                 $icon_im = imagecreatefromfile($this->iconfile);
                 # $icon_im = imagecreatefrompng($this->iconfile);
                 if (function_exists("imagefilter") && isset($colicon) && $this->get_hint("use_imagefilter") == 1) {
                     imagefilter($icon_im, IMG_FILTER_COLORIZE, $colicon->r, $colicon->g, $colicon->b);
                 } else {
                     if (isset($colicon)) {
                         // debug("Skipping unavailable imagefilter() call.\n");
                         imagecolorize($icon_im, $colicon->r, $colicon->g, $colicon->b);
                     }
                 }
                 wm_debug("If this is the last thing in your logs, you probably have a buggy GD library. Get > 2.0.33 or use PHP builtin.\n");
                 if ($icon_im) {
                     $icon_w = imagesx($icon_im);
                     $icon_h = imagesy($icon_im);
                     if ($this->iconscalew * $this->iconscaleh > 0) {
                         imagealphablending($icon_im, true);
                         wm_debug("SCALING ICON here\n");
                         if ($icon_w > $icon_h) {
                             $scalefactor = $icon_w / $this->iconscalew;
                         } else {
                             $scalefactor = $icon_h / $this->iconscaleh;
                         }
                         $new_width = $icon_w / $scalefactor;
                         $new_height = $icon_h / $scalefactor;
                         $scaled = imagecreatetruecolor($new_width, $new_height);
                         imagealphablending($scaled, false);
                         imagecopyresampled($scaled, $icon_im, 0, 0, 0, 0, $new_width, $new_height, $icon_w, $icon_h);
                         imagedestroy($icon_im);
                         $icon_im = $scaled;
                     }
                 } else {
                     wm_warn("Couldn't open ICON: '" . $this->iconfile . "' - is it a PNG, JPEG or GIF? [WMWARN37]\n");
                 }
             } else {
                 if ($this->iconfile != 'none') {
                     wm_warn("ICON '" . $this->iconfile . "' does not exist, or is not readable. Check path and permissions. [WMARN38]\n");
                 }
             }
         }
         if ($icon_im) {
             $icon_w = imagesx($icon_im);
             $icon_h = imagesy($icon_im);
             $icon_x1 = $this->x - $icon_w / 2;
             $icon_y1 = $this->y - $icon_h / 2;
             $icon_x2 = $this->x + $icon_w / 2;
             $icon_y2 = $this->y + $icon_h / 2;
             $map->nodes[$this->name]->width = imagesx($icon_im);
             $map->nodes[$this->name]->height = imagesy($icon_im);
             // $map->imap->addArea("Rectangle", "NODE:" . $this->name . ':0', '', array($icon_x1, $icon_y1, $icon_x2, $icon_y2));
             $map->nodes[$this->name]->boundingboxes[] = array($icon_x1, $icon_y1, $icon_x2, $icon_y2);
         }
     }
     // do any offset calculations
     $dx = 0;
     $dy = 0;
     if ($this->labeloffset != '' && $this->iconfile != '') {
         $this->labeloffsetx = 0;
         $this->labeloffsety = 0;
         list($dx, $dy) = calc_offset($this->labeloffset, $icon_w + $boxwidth - 1, $icon_h + $boxheight);
         #$this->labeloffsetx = $dx;
         #$this->labeloffsety = $dy;
     }
     $label_x1 += $this->labeloffsetx + $dx;
     $label_x2 += $this->labeloffsetx + $dx;
     $label_y1 += $this->labeloffsety + $dy;
     $label_y2 += $this->labeloffsety + $dy;
     if ($this->label != '') {
         // $map->imap->addArea("Rectangle", "NODE:" . $this->name .':1', '', array($label_x1, $label_y1, $label_x2, $label_y2));
         $map->nodes[$this->name]->boundingboxes[] = array($label_x1, $label_y1, $label_x2, $label_y2);
     }
     // work out the bounding box of the whole thing
     $bbox_x1 = min($label_x1, $icon_x1);
     $bbox_x2 = max($label_x2, $icon_x2) + 1;
     $bbox_y1 = min($label_y1, $icon_y1);
     $bbox_y2 = max($label_y2, $icon_y2) + 1;
     #           imagerectangle($im,$bbox_x1,$bbox_y1,$bbox_x2,$bbox_y2,$map->selected);
     #         imagerectangle($im,$label_x1,$label_y1,$label_x2,$label_y2,$map->black);
     #       imagerectangle($im,$icon_x1,$icon_y1,$icon_x2,$icon_y2,$map->black);
     // create TWO imagemap entries - one for the label and one for the icon
     // (so we can have close-spaced icons better)
     $temp_width = $bbox_x2 - $bbox_x1;
     $temp_height = $bbox_y2 - $bbox_y1;
     // create an image of that size and draw into it
     $node_im = imagecreatetruecolor($temp_width, $temp_height);
     // ImageAlphaBlending($node_im, FALSE);
     imageSaveAlpha($node_im, TRUE);
     $nothing = imagecolorallocatealpha($node_im, 128, 0, 0, 127);
     imagefill($node_im, 0, 0, $nothing);
     #$col = $col->gdallocate($node_im);
     // imagefilledrectangle($node_im,0,0,$temp_width,$temp_height,  $nothing);
     $label_x1 -= $bbox_x1;
     $label_x2 -= $bbox_x1;
     $label_y1 -= $bbox_y1;
     $label_y2 -= $bbox_y1;
     $icon_x1 -= $bbox_x1;
     $icon_x2 -= $bbox_x1;
     $icon_y1 -= $bbox_y1;
     $icon_y2 -= $bbox_y1;
     // Draw the icon, if any
     if (isset($icon_im)) {
         imagecopy($node_im, $icon_im, $icon_x1, $icon_y1, 0, 0, imagesx($icon_im), imagesy($icon_im));
         imagedestroy($icon_im);
     }
     // Draw the label, if any
     if ($this->label != '') {
         $txt_x -= $bbox_x1;
         $txt_x += $this->labeloffsetx + $dx;
         $txt_y -= $bbox_y1;
         $txt_y += $this->labeloffsety + $dy;
         #       print "FINAL TEXT at $txt_x , $txt_y\n";
         // if there's an icon, then you can choose to have no background
         if (!$col->is_none()) {
             imagefilledrectangle($node_im, $label_x1, $label_y1, $label_x2, $label_y2, $col->gdallocate($node_im));
         }
         if ($this->selected) {
             imagerectangle($node_im, $label_x1, $label_y1, $label_x2, $label_y2, $map->selected);
             // would be nice if it was thicker, too...
             wimagerectangle($node_im, $label_x1 + 1, $label_y1 + 1, $label_x2 - 1, $label_y2 - 1, $map->selected);
         } else {
             $olcol = new Colour($this->labeloutlinecolour);
             if ($olcol->is_real()) {
                 imagerectangle($node_im, $label_x1, $label_y1, $label_x2, $label_y2, $olcol->gdallocate($node_im));
             }
         }
         #}
         $shcol = new Colour($this->labelfontshadowcolour);
         if ($shcol->is_real()) {
             $map->myimagestring($node_im, $this->labelfont, $txt_x + 1, $txt_y + 1, $this->proclabel, $shcol->gdallocate($node_im), $this->labelangle);
         }
         $txcol = new Colour($this->labelfontcolour[0], $this->labelfontcolour[1], $this->labelfontcolour[2]);
         #$col=myimagecolorallocate($node_im, $this->labelfontcolour[0], $this->labelfontcolour[1],
         #	$this->labelfontcolour[2]);
         if ($txcol->is_contrast()) {
             if ($col->is_real()) {
                 $txcol = $col->contrast();
             } else {
                 wm_warn("You can't make a contrast with 'none'. [WMWARN43]\n");
                 $txcol = new Colour(0, 0, 0);
             }
         }
         $map->myimagestring($node_im, $this->labelfont, $txt_x, $txt_y, $this->proclabel, $txcol->gdallocate($node_im), $this->labelangle);
         //$map->myimagestring($node_im, $this->labelfont, $txt_x, $txt_y, $this->proclabel, $txcol->gdallocate($node_im),90);
     }
     # imagerectangle($node_im,$label_x1,$label_y1,$label_x2,$label_y2,$map->black);
     # imagerectangle($node_im,$icon_x1,$icon_y1,$icon_x2,$icon_y2,$map->black);
     $map->nodes[$this->name]->centre_x = $this->x - $bbox_x1;
     $map->nodes[$this->name]->centre_y = $this->y - $bbox_y1;
     if (1 == 0) {
         imageellipse($node_im, $this->centre_x, $this->centre_y, 8, 8, $map->selected);
         foreach (array("N", "S", "E", "W", "NE", "NW", "SE", "SW") as $corner) {
             list($dx, $dy) = calc_offset($corner, $this->width, $this->height);
             imageellipse($node_im, $this->centre_x + $dx, $this->centre_y + $dy, 5, 5, $map->selected);
         }
     }
     # $this->image = $node_im;
     $map->nodes[$this->name]->image = $node_im;
 }
 function Draw($im, &$map)
 {
     // Get the positions of the end-points
     $x1 = $map->nodes[$this->a->name]->x;
     $y1 = $map->nodes[$this->a->name]->y;
     $x2 = $map->nodes[$this->b->name]->x;
     $y2 = $map->nodes[$this->b->name]->y;
     if (is_null($x1)) {
         wm_warn("LINK " . $this->name . " uses a NODE with no POSITION! [WMWARN35]\n");
         return;
     }
     if (is_null($y1)) {
         wm_warn("LINK " . $this->name . " uses a NODE with no POSITION! [WMWARN35]\n");
         return;
     }
     if (is_null($x2)) {
         wm_warn("LINK " . $this->name . " uses a NODE with no POSITION! [WMWARN35]\n");
         return;
     }
     if (is_null($y2)) {
         wm_warn("LINK " . $this->name . " uses a NODE with no POSITION! [WMWARN35]\n");
         return;
     }
     if ($this->linkstyle == 'twoway' && $this->labeloffset_in < $this->labeloffset_out && intval($map->get_hint("nowarn_bwlabelpos")) == 0) {
         wm_warn("LINK " . $this->name . " probably has it's BWLABELPOSs the wrong way around [WMWARN50]\n");
     }
     list($dx, $dy) = calc_offset($this->a_offset, $map->nodes[$this->a->name]->width, $map->nodes[$this->a->name]->height);
     $x1 += $dx;
     $y1 += $dy;
     list($dx, $dy) = calc_offset($this->b_offset, $map->nodes[$this->b->name]->width, $map->nodes[$this->b->name]->height);
     $x2 += $dx;
     $y2 += $dy;
     if ($x1 == $x2 && $y1 == $y2 && sizeof($this->vialist) == 0) {
         wm_warn("Zero-length link " . $this->name . " skipped. [WMWARN45]");
         return;
     }
     $outlinecol = new Colour($this->outlinecolour);
     $commentcol = new Colour($this->commentfontcolour);
     $outline_colour = $outlinecol->gdallocate($im);
     $xpoints = array();
     $ypoints = array();
     $xpoints[] = $x1;
     $ypoints[] = $y1;
     # warn("There are VIAs.\n");
     foreach ($this->vialist as $via) {
         # imagearc($im, $via[0],$via[1],20,20,0,360,$map->selected);
         if (isset($via[2])) {
             $xpoints[] = $map->nodes[$via[2]]->x + $via[0];
             $ypoints[] = $map->nodes[$via[2]]->y + $via[1];
         } else {
             $xpoints[] = $via[0];
             $ypoints[] = $via[1];
         }
     }
     $xpoints[] = $x2;
     $ypoints[] = $y2;
     # list($link_in_colour,$link_in_scalekey, $link_in_scaletag) = $map->NewColourFromPercent($this->inpercent,$this->usescale,$this->name);
     # list($link_out_colour,$link_out_scalekey, $link_out_scaletag) = $map->NewColourFromPercent($this->outpercent,$this->usescale,$this->name);
     $link_in_colour = $this->colours[IN];
     $link_out_colour = $this->colours[OUT];
     $gd_in_colour = $link_in_colour->gdallocate($im);
     $gd_out_colour = $link_out_colour->gdallocate($im);
     //	$map->links[$this->name]->inscalekey = $link_in_scalekey;
     //	$map->links[$this->name]->outscalekey = $link_out_scalekey;
     $link_width = $this->width;
     // these will replace the one above, ultimately.
     $link_in_width = $this->width;
     $link_out_width = $this->width;
     // for bulging animations
     if ($map->widthmod || $map->get_hint('link_bulge') == 1) {
         // a few 0.1s and +1s to fix div-by-zero, and invisible links
         $link_width = ($link_width * $this->inpercent * 1.5 + 0.1) / 100 + 1;
         // these too
         $link_in_width = ($link_in_width * $this->inpercent * 1.5 + 0.1) / 100 + 1;
         $link_out_width = ($link_out_width * $this->outpercent * 1.5 + 0.1) / 100 + 1;
     }
     // If there are no vias, treat this as a 2-point angled link, not curved
     if (sizeof($this->vialist) == 0 || $this->viastyle == 'angled') {
         // Calculate the spine points - the actual not a curve really, but we
         // need to create the array, and calculate the distance bits, otherwise
         // things like bwlabels won't know where to go.
         $this->curvepoints = calc_straight($xpoints, $ypoints);
         // then draw the "curve" itself
         draw_straight($im, $this->curvepoints, array($link_in_width, $link_out_width), $outline_colour, array($gd_in_colour, $gd_out_colour), $this->name, $map, $this->splitpos, $this->linkstyle == 'oneway' ? TRUE : FALSE);
     } elseif ($this->viastyle == 'curved') {
         // Calculate the spine points - the actual curve
         $this->curvepoints = calc_curve($xpoints, $ypoints);
         // then draw the curve itself
         draw_curve($im, $this->curvepoints, array($link_in_width, $link_out_width), $outline_colour, array($gd_in_colour, $gd_out_colour), $this->name, $map, $this->splitpos, $this->linkstyle == 'oneway' ? TRUE : FALSE);
     }
     if (!$commentcol->is_none()) {
         if ($commentcol->is_contrast()) {
             $commentcol_in = $link_in_colour->contrast();
             $commentcol_out = $link_out_colour->contrast();
         } else {
             $commentcol_in = $commentcol;
             $commentcol_out = $commentcol;
         }
         $comment_colour_in = $commentcol_in->gdallocate($im);
         $comment_colour_out = $commentcol_out->gdallocate($im);
         $this->DrawComments($im, array($comment_colour_in, $comment_colour_out), array($link_in_width * 1.1, $link_out_width * 1.1));
     }
     $curvelength = $this->curvepoints[count($this->curvepoints) - 1][2];
     // figure out where the labels should be, and what the angle of the curve is at that point
     list($q1_x, $q1_y, $junk, $q1_angle) = find_distance_coords_angle($this->curvepoints, $this->labeloffset_out / 100 * $curvelength);
     list($q3_x, $q3_y, $junk, $q3_angle) = find_distance_coords_angle($this->curvepoints, $this->labeloffset_in / 100 * $curvelength);
     # imageline($im, $q1_x+20*cos(deg2rad($q1_angle)),$q1_y-20*sin(deg2rad($q1_angle)), $q1_x-20*cos(deg2rad($q1_angle)), $q1_y+20*sin(deg2rad($q1_angle)), $this->owner->selected );
     # imageline($im, $q3_x+20*cos(deg2rad($q3_angle)),$q3_y-20*sin(deg2rad($q3_angle)), $q3_x-20*cos(deg2rad($q3_angle)), $q3_y+20*sin(deg2rad($q3_angle)), $this->owner->selected );
     # warn("$q1_angle $q3_angle\n");
     if (!is_null($q1_x)) {
         $outbound = array($q1_x, $q1_y, 0, 0, $this->outpercent, $this->bandwidth_out, $q1_angle, OUT);
         $inbound = array($q3_x, $q3_y, 0, 0, $this->inpercent, $this->bandwidth_in, $q3_angle, IN);
         if ($map->sizedebug) {
             $outbound[5] = $this->max_bandwidth_out;
             $inbound[5] = $this->max_bandwidth_in;
         }
         if ($this->linkstyle == 'oneway') {
             $tasks = array($outbound);
         } else {
             $tasks = array($inbound, $outbound);
         }
         foreach ($tasks as $task) {
             $thelabel = "";
             $thelabel = $map->ProcessString($this->bwlabelformats[$task[7]], $this);
             if ($thelabel != '') {
                 wm_debug("Bandwidth for label is " . $task[5] . "\n");
                 $padding = intval($this->get_hint('bwlabel_padding'));
                 // if screenshot_mode is enabled, wipe any letters to X and wipe any IP address to 127.0.0.1
                 // hopefully that will preserve enough information to show cool stuff without leaking info
                 if ($map->get_hint('screenshot_mode') == 1) {
                     $thelabel = screenshotify($thelabel);
                 }
                 if ($this->labelboxstyle == 'angled') {
                     $angle = $task[6];
                 } else {
                     $angle = 0;
                 }
                 $map->DrawLabelRotated($im, $task[0], $task[1], $angle, $thelabel, $this->bwfont, $padding, $this->name, $this->bwfontcolour, $this->bwboxcolour, $this->bwoutlinecolour, $map, $task[7]);
                 // imagearc($im, $task[0], $task[1], 10,10,0,360,$map->selected);
             }
         }
     }
 }
function DrawTitle($im, $font, $colour)
{
	$string = $this->ProcessString($this->title,$this);
	
	if($this->get_hint('screenshot_mode')==1)  $string= screenshotify($string);

	list($boxwidth, $boxheight)=$this->myimagestringsize($font, $string);

	$x=10;
	$y=$this->titley - $boxheight;

	if (($this->titlex >= 0) && ($this->titley >= 0))
	{
		$x=$this->titlex;
		$y=$this->titley;
	}

	$this->myimagestring($im, $font, $x, $y, $string, $colour);

	$this->imap->addArea("Rectangle", "TITLE", '', array($x, $y, $x + $boxwidth, $y - $boxheight));
}