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;
 }
 /**
  * @param $iconImageRef
  * @param $fill
  * @param $ink
  */
 protected function drawAIconRoundedBox($iconImageRef, $fill, $ink)
 {
     if ($fill !== null && !$fill->isNone()) {
         imagefilledroundedrectangle($iconImageRef, 0, 0, $this->iconscalew - 1, $this->iconscaleh - 1, 4, $fill->gdAllocate($iconImageRef));
     }
     if ($ink !== null && !$ink->isNone()) {
         imageroundedrectangle($iconImageRef, 0, 0, $this->iconscalew - 1, $this->iconscaleh - 1, 4, $ink->gdallocate($iconImageRef));
     }
 }