function preCalculate(&$map)
 {
     wm_debug("Link " . $this->name . ": Calculating geometry.\n");
     // don't bother doing anything if it's a template
     if ($this->isTemplate()) {
         return;
     }
     $points = array();
     list($dx, $dy) = WMUtility::calculateOffset($this->a_offset, $this->a->width, $this->a->height);
     $points[] = new WMPoint($this->a->x + $dx, $this->a->y + $dy);
     foreach ($this->vialist as $via) {
         wm_debug("VIALIST...\n");
         // if the via has a third element, the first two are relative to that node
         if (isset($via[2])) {
             $relativeTo = $map->getNode($via[2]);
             wm_debug("Relative to {$relativeTo}\n");
             $point = new WMPoint($relativeTo->x + $via[0], $relativeTo->y + $via[1]);
         } else {
             $point = new WMPoint($via[0], $via[1]);
         }
         wm_debug("Adding {$point}\n");
         $points[] = $point;
     }
     list($dx, $dy) = WMUtility::calculateOffset($this->b_offset, $this->b->width, $this->b->height);
     $points[] = new WMPoint($this->b->x + $dx, $this->b->y + $dy);
     if ($points[0]->closeEnough($points[1]) && sizeof($this->vialist) == 0) {
         wm_warn("Zero-length link " . $this->name . " skipped. [WMWARN45]");
         $this->geometry = null;
         return;
     }
     $widths = array($this->width, $this->width);
     // for bulging animations, modulate the width with the percentage value
     if ($map->widthmod || $map->get_hint('link_bulge') == 1) {
         // a few 0.1s and +1s to fix div-by-zero, and invisible links
         $widths[0] = ($widths[0] * $this->percentUsages[IN] * 1.5 + 0.1) / 100 + 1;
         $widths[1] = ($widths[1] * $this->percentUsages[OUT] * 1.5 + 0.1) / 100 + 1;
     }
     $style = $this->viastyle;
     // don't bother with any curve stuff if there aren't any Vias defined, even if the style is 'curved'
     if (count($this->vialist) == 0) {
         $style = "angled";
     }
     $this->geometry = WMLinkGeometryFactory::create($style);
     $this->geometry->Init($this, $points, $widths, $this->linkstyle == 'oneway' ? 1 : 2, $this->splitpos, $this->arrowstyle);
 }
 function preRender($im, &$map)
 {
     // don't bother drawing if it's a template
     if ($this->isTemplate()) {
         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.
     $labelBoundingBox = new WMBoundingBox();
     $labelBoundingBox->addWMPoint($this->getPosition());
     $iconBoundingBox = new WMBoundingBox();
     $iconBoundingBox->addWMPoint($this->getPosition());
     $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;
     list($labelFillColour, $iconFillColour) = $this->calculateColours($map);
     // figure out a bounding rectangle for the label
     if ($this->label != '') {
         $padding = 4.0;
         $padFactor = 1.0;
         $this->processedLabel = $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->processedLabel = WMUtility::stringAnonymise($this->processedLabel);
         }
         list($stringWidth, $stringHeight) = $map->myimagestringsize($this->labelfont, $this->processedLabel);
         if ($this->labelangle == 90 || $this->labelangle == 270) {
             $boxWidth = $stringHeight * $padFactor + $padding;
             $boxHeight = $stringWidth * $padFactor + $padding;
         } else {
             $boxWidth = $stringWidth * $padFactor + $padding;
             $boxHeight = $stringHeight * $padFactor + $padding;
         }
         $halfWidth = $boxWidth / 2;
         $halfHeight = $boxHeight / 2;
         $label_x1 = $this->x - $halfWidth;
         $label_y1 = $this->y - $halfHeight;
         $label_x2 = $this->x + $halfWidth;
         $label_y2 = $this->y + $halfHeight;
         $labelBoundingBox->addPoint($this->x - $halfWidth, $this->y - $halfHeight);
         $labelBoundingBox->addPoint($this->x + $halfWidth, $this->y + $halfHeight);
         wm_debug("Node->pre_render: " . $this->name . " Label Metrics are: {$stringWidth} x {$stringHeight} -> {$boxWidth} x {$boxHeight}\n");
         if ($this->labelangle == 90) {
             $txt_x = $this->x + $stringHeight / 2;
             $txt_y = $this->y + $stringWidth / 2;
         }
         if ($this->labelangle == 270) {
             $txt_x = $this->x - $stringHeight / 2;
             $txt_y = $this->y - $stringWidth / 2;
         }
         if ($this->labelangle == 0) {
             $txt_x = $this->x - $stringWidth / 2;
             $txt_y = $this->y + $stringHeight / 2;
         }
         if ($this->labelangle == 180) {
             $txt_x = $this->x + $stringWidth / 2;
             $txt_y = $this->y - $stringHeight / 2;
         }
         $this->width = $boxWidth;
         $this->height = $boxHeight;
     }
     // figure out a bounding rectangle for the icon
     if ($this->iconfile != '') {
         $iconImageRef = 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
             $iconImageRef = imagecreatetruecolor($this->iconscalew, $this->iconscaleh);
             imageSaveAlpha($iconImageRef, true);
             $nothing = imagecolorallocatealpha($iconImageRef, 128, 0, 0, 127);
             imagefill($iconImageRef, 0, 0, $nothing);
             $fill = null;
             $ink = null;
             $aiconFillColour = $this->aiconfillcolour;
             $aiconInkColour = $this->aiconoutlinecolour;
             // if useiconscale isn't set, then use the static colour defined, or copy the colour from the label
             if ($this->useiconscale == "none") {
                 if ($aiconFillColour->isCopy() && !$labelFillColour->isNone()) {
                     $fill = $labelFillColour;
                 } else {
                     if ($aiconFillColour->isRealColour()) {
                         $fill = $aiconFillColour;
                     }
                 }
             } else {
                 // if useiconscale IS defined, use that to figure out the fill colour
                 $fill = $iconFillColour;
             }
             if (!$this->aiconoutlinecolour->isNone()) {
                 $ink = $aiconInkColour;
             }
             wm_debug("AICON colours are {$ink} and {$fill}\n");
             if ($this->iconfile == 'box') {
                 $this->drawAIconBox($iconImageRef, $fill, $ink);
             }
             if ($this->iconfile == 'rbox') {
                 $this->drawAIconRoundedBox($iconImageRef, $fill, $ink);
             }
             if ($this->iconfile == 'round') {
                 $this->drawAIconRound($iconImageRef, $fill, $ink);
             }
             if ($this->iconfile == 'nink') {
                 $this->drawAIconNINK($iconImageRef, $ink);
             }
             // XXX - needs proper colours
             if ($this->iconfile == 'inpie' || $this->iconfile == 'outpie') {
                 $this->drawAIconPie($iconImageRef, $fill, $ink);
             }
             if ($this->iconfile == 'gauge') {
                 wm_warn('gauge AICON not implemented yet [WMWARN99]');
             }
         } else {
             $realiconfile = $map->ProcessString($this->iconfile, $this);
             if (is_readable($realiconfile)) {
                 imagealphablending($im, true);
                 // draw the supplied icon, instead of the labelled box
                 $iconImageRef = imagecreatefromfile($realiconfile);
                 if (true === isset($iconFillColour)) {
                     $this->colourizeImage($iconImageRef, $iconFillColour);
                 }
                 if ($iconImageRef) {
                     $icon_w = imagesx($iconImageRef);
                     $icon_h = imagesy($iconImageRef);
                     if ($this->iconscalew * $this->iconscaleh > 0) {
                         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");
                         imagealphablending($iconImageRef, 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, $iconImageRef, 0, 0, 0, 0, $new_width, $new_height, $icon_w, $icon_h);
                         imagedestroy($iconImageRef);
                         $iconImageRef = $scaled;
                     }
                 } else {
                     wm_warn("Couldn't open ICON: '" . $realiconfile . "' - is it a PNG, JPEG or GIF? [WMWARN37]\n");
                 }
             } else {
                 if ($realiconfile != 'none') {
                     wm_warn("ICON '" . $realiconfile . "' does not exist, or is not readable. Check path and permissions. [WMARN38]\n");
                 }
             }
         }
         if ($iconImageRef) {
             $icon_w = imagesx($iconImageRef);
             $icon_h = imagesy($iconImageRef);
             $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;
             $this->width = imagesx($iconImageRef);
             $this->height = imagesy($iconImageRef);
             $this->boundingboxes[] = array($icon_x1, $icon_y1, $icon_x2, $icon_y2);
         }
     }
     // do any offset calculations
     $deltaX = 0;
     $deltaY = 0;
     if ($this->labeloffset != '' && $this->iconfile != '') {
         $this->labeloffsetx = 0;
         $this->labeloffsety = 0;
         list($deltaX, $deltaY) = WMUtility::calculateOffset($this->labeloffset, $icon_w + $boxWidth - 1, $icon_h + $boxHeight);
     }
     $label_x1 += $this->labeloffsetx + $deltaX;
     $label_x2 += $this->labeloffsetx + $deltaX;
     $label_y1 += $this->labeloffsety + $deltaY;
     $label_y2 += $this->labeloffsety + $deltaY;
     if ($this->label != '') {
         $this->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;
     // 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);
     $label_x1 -= $bbox_x1;
     $label_x2 -= $bbox_x1;
     $label_y1 -= $bbox_y1;
     $label_y2 -= $bbox_y1;
     $icon_x1 -= $bbox_x1;
     $icon_y1 -= $bbox_y1;
     // Draw the icon, if any
     if (isset($iconImageRef)) {
         imagecopy($node_im, $iconImageRef, $icon_x1, $icon_y1, 0, 0, imagesx($iconImageRef), imagesy($iconImageRef));
         imagedestroy($iconImageRef);
     }
     // Draw the label, if any
     if ($this->label != '') {
         $txt_x -= $bbox_x1;
         $txt_x += $this->labeloffsetx + $deltaX;
         $txt_y -= $bbox_y1;
         $txt_y += $this->labeloffsety + $deltaY;
         // if there's an icon, then you can choose to have no background
         if (!$this->labelbgcolour->isNone()) {
             imagefilledrectangle($node_im, $label_x1, $label_y1, $label_x2, $label_y2, $labelFillColour->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...
             imagerectangle($node_im, $label_x1 + 1, $label_y1 + 1, $label_x2 - 1, $label_y2 - 1, $map->selected);
         } else {
             // $label_outline_colour = $this->labeloutlinecolour;
             if ($this->labeloutlinecolour->isRealColour()) {
                 imagerectangle($node_im, $label_x1, $label_y1, $label_x2, $label_y2, $this->labeloutlinecolour->gdallocate($node_im));
             }
         }
         // $shcol = $this->labelfontshadowcolour;
         if ($this->labelfontshadowcolour->isRealColour()) {
             $map->myimagestring($node_im, $this->labelfont, $txt_x + 1, $txt_y + 1, $this->processedLabel, $this->labelfontshadowcolour->gdallocate($node_im), $this->labelangle);
         }
         $txcol = $this->labelfontcolour;
         if ($txcol->isContrast()) {
             if ($labelFillColour->isRealColour()) {
                 $txcol = $labelFillColour->getContrastingColour();
             } else {
                 wm_warn("You can't make a contrast with 'none'. [WMWARN43]\n");
                 $txcol = new WMColour(0, 0, 0);
             }
         }
         $map->myimagestring($node_im, $this->labelfont, $txt_x, $txt_y, $this->processedLabel, $txcol->gdAllocate($node_im), $this->labelangle);
     }
     $this->centre_x = $this->x - $bbox_x1;
     $this->centre_y = $this->y - $bbox_y1;
     $this->image = $node_im;
 }
 function preRender($im, &$map)
 {
     // don't bother drawing if it's a template
     if ($this->isTemplate()) {
         return;
     }
     // apparently, some versions of the gd extension will crash if we continue...
     if ($this->label == '' && $this->iconfile == '') {
         return;
     }
     $iconObj = null;
     $labelObj = null;
     $labelFillColour = $this->calculateFillColour();
     $iconFillColour = $this->calculateIconFillColour();
     // 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;
     // figure out a bounding rectangle for the label
     if ($this->label != '') {
         $labelObj = new WMNodeLabel($this);
         $this->processedLabel = $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->processedLabel = WMUtility::stringAnonymise($this->processedLabel);
         }
         $labelObj->calculateGeometry($this->processedLabel, $this->labelfont);
         $labelObj->preRender($labelFillColour, $this->labeloutlinecolour, $this->labelfontshadowcolour, $this->labelfontcolour);
         //            $padding = 4.0;
         //            $padFactor = 1.0;
         //
         //
         //            list($stringWidth, $stringHeight) = $map->myimagestringsize($this->labelfont, $this->processedLabel);
         //
         //            if ($this->labelangle == 90 || $this->labelangle == 270) {
         //                $boxWidth = ($stringHeight * $padFactor) + $padding;
         //                $boxHeight = ($stringWidth * $padFactor) + $padding;
         //            } else {
         //                $boxWidth = ($stringWidth * $padFactor) + $padding;
         //                $boxHeight = ($stringHeight * $padFactor) + $padding;
         //            }
         //
         //            $halfWidth = $boxWidth / 2;
         //            $halfHeight = $boxHeight / 2;
         //
         //            $label_x1 = $this->x - $halfWidth;
         //            $label_y1 = $this->y - $halfHeight;
         //
         //            $label_x2 = $this->x + $halfWidth;
         //            $label_y2 = $this->y + $halfHeight;
         //
         //            wm_debug("Node->pre_render: " . $this->name . " Label Metrics are: $stringWidth x $stringHeight -> $boxWidth x $boxHeight\n");
         //
         //            if ($this->labelangle == 90) {
         //                $txt_x = $this->x + ($stringHeight / 2);
         //                $txt_y = $this->y + ($stringWidth / 2);
         //            }
         //
         //            if ($this->labelangle == 270) {
         //                $txt_x = $this->x - ($stringHeight / 2);
         //                $txt_y = $this->y - ($stringWidth / 2);
         //            }
         //
         //            if ($this->labelangle == 0) {
         //                $txt_x = $this->x - ($stringWidth / 2);
         //                $txt_y = $this->y + ($stringHeight / 2);
         //            }
         //
         //            if ($this->labelangle == 180) {
         //                $txt_x = $this->x + ($stringWidth / 2);
         //                $txt_y = $this->y - ($stringHeight / 2);
         //            }
         //
         //            $this->width = $boxWidth;
         //            $this->height = $boxHeight;
     }
     // figure out a bounding rectangle for the icon
     if ($this->iconfile != '') {
         $iconImageRef = null;
         $icon_w = 0;
         $icon_h = 0;
         //            $artificialIconNames = array('rbox', 'round', 'box', 'inpie', 'outpie', 'gauge', 'nink');
         //if (in_array($this->iconfile, $artificialIconNames)) {
         if (WMNodeArtificialIcon::isAICONName($this->iconfile)) {
             $iconObj = new WMNodeArtificialIcon($this, $aiconInkColour, $aiconFillColour, $iconFillColour, $aiconOutlineColour, $labelFillColour);
         } else {
             $iconObj = new WMNodeImageIcon($this);
         }
         $iconObj->calculateGeometry();
         $iconObj->preRender();
         $iconImageRef = $iconObj->getImageRef();
         if ($iconImageRef) {
             $icon_w2 = imagesx($iconImageRef) / 2;
             $icon_h2 = imagesy($iconImageRef) / 2;
             $iconRect = new WMRectangle(-$icon_w2, -$icon_h2, $icon_w2, $icon_h2);
             $iconRect->translate($this->x, $this->y);
             $icon_w = imagesx($iconImageRef);
             $icon_h = imagesy($iconImageRef);
             $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;
             $this->width = imagesx($iconImageRef);
             $this->height = imagesy($iconImageRef);
             $this->boundingboxes[] = array($icon_x1, $icon_y1, $icon_x2, $icon_y2);
         }
     }
     // do any offset calculations
     $deltaX = 0;
     $deltaY = 0;
     if ($this->labeloffset != '' && $this->iconfile != '') {
         $this->labeloffsetx = 0;
         $this->labeloffsety = 0;
         list($deltaX, $deltaY) = WMUtility::calculateOffset($this->labeloffset, $icon_w + $boxWidth - 1, $icon_h + $boxHeight);
     }
     $label_x1 += $this->labeloffsetx + $deltaX;
     $label_x2 += $this->labeloffsetx + $deltaX;
     $label_y1 += $this->labeloffsety + $deltaY;
     $label_y2 += $this->labeloffsety + $deltaY;
     if ($this->label != '') {
         $this->boundingboxes[] = array($label_x1, $label_y1, $label_x2, $label_y2);
     }
     // work out the bounding box of the whole thing
     $totalBoundingBox = new WMBoundingBox();
     //        $totalBoundingBox->addRectangle();
     //        $totalBoundingBox->addRectangle();
     $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;
     // 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);
     $label_x1 -= $bbox_x1;
     $label_x2 -= $bbox_x1;
     $label_y1 -= $bbox_y1;
     $label_y2 -= $bbox_y1;
     $icon_x1 -= $bbox_x1;
     $icon_y1 -= $bbox_y1;
     $labelObj->translate(-$bbox_x1 + $deltaX + $this->labeloffsetx, -$bbox_y1 + $deltaY + $this->labeloffsety);
     // Draw the icon, if any
     if (isset($iconImageRef)) {
         $iconObj->draw($node_im);
         //            imagecopy($node_im, $iconImageRef, $icon_x1, $icon_y1, 0, 0, imagesx($iconImageRef), imagesy($iconImageRef));
         //            imagedestroy($iconImageRef);
     }
     // Draw the label, if any
     if ($this->label != '') {
         $labelObj->draw($node_im);
     }
     $this->centre_x = $this->x - $bbox_x1;
     $this->centre_y = $this->y - $bbox_y1;
     $this->image = $node_im;
 }
 function preRender($im, &$map)
 {
     // don't bother drawing if it's a template
     if ($this->isTemplate()) {
         return;
     }
     // apparently, some versions of the gd extension will crash if we continue...
     if ($this->label == '' && $this->iconfile == '') {
         return;
     }
     $iconObj = null;
     $labelObj = null;
     $labelFillColour = $this->calculateFillColour();
     $iconFillColour = $this->calculateIconFillColour();
     // 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;
     // figure out a bounding rectangle for the label
     if ($this->label != '') {
         $labelObj = new WMNodeLabel($this);
         $this->processedLabel = $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->processedLabel = WMUtility::stringAnonymise($this->processedLabel);
         }
         $labelObj->calculateGeometry($this->processedLabel, $this->labelfont);
         $labelObj->preRender($labelFillColour, $this->labeloutlinecolour, $this->labelfontshadowcolour, $this->labelfontcolour);
     }
     // figure out a bounding rectangle for the icon
     if ($this->iconfile != '') {
         $iconImageRef = null;
         $icon_w = 0;
         $icon_h = 0;
         if (WMNodeArtificialIcon::isAICONName($this->iconfile)) {
             $aiconFillColour = $this->aiconfillcolour;
             $aiconInkColour = $this->aiconoutlinecolour;
             // if useiconscale isn't defined, use the static colours defined by AICONFILLCOLOR and AICONOUTLINECOLOR
             // (or copy the colour from the label fill colour)
             if ($this->useiconscale == 'none') {
                 if ($aiconFillColour->isCopy() && !$labelFillColour->isNone()) {
                     $aiconFillColour = $labelFillColour;
                 }
             } else {
                 // if useiconscale IS defined, use that to figure out the file colour
                 $aiconFillColour = $this->calculateIconFillColour();
             }
             $iconObj = new WMNodeArtificialIcon($this, $aiconInkColour, $aiconFillColour, $iconFillColour, $labelFillColour);
         } else {
             $iconObj = new WMNodeImageIcon($this);
         }
         $iconObj->calculateGeometry();
         $iconObj->preRender();
         $iconImageRef = $iconObj->getImageRef();
         if ($iconImageRef) {
             $icon_w2 = imagesx($iconImageRef) / 2;
             $icon_h2 = imagesy($iconImageRef) / 2;
             $iconRect = new WMRectangle(-$icon_w2, -$icon_h2, $icon_w2, $icon_h2);
             $iconRect->translate($this->x, $this->y);
             $icon_w = imagesx($iconImageRef);
             $icon_h = imagesy($iconImageRef);
             $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;
             $this->width = imagesx($iconImageRef);
             $this->height = imagesy($iconImageRef);
             $this->boundingboxes[] = array($icon_x1, $icon_y1, $icon_x2, $icon_y2);
         }
     }
     // do any offset calculations
     $deltaX = 0;
     $deltaY = 0;
     if ($this->labeloffset != '' && $this->iconfile != '') {
         $this->labeloffsetx = 0;
         $this->labeloffsety = 0;
         list($deltaX, $deltaY) = WMUtility::calculateOffset($this->labeloffset, $icon_w + $boxWidth - 1, $icon_h + $boxHeight);
     }
     $label_x1 += $this->labeloffsetx + $deltaX;
     $label_x2 += $this->labeloffsetx + $deltaX;
     $label_y1 += $this->labeloffsety + $deltaY;
     $label_y2 += $this->labeloffsety + $deltaY;
     if ($this->label != '') {
         $this->boundingboxes[] = array($label_x1, $label_y1, $label_x2, $label_y2);
     }
     // work out the bounding box of the whole thing
     $totalBoundingBox = new WMBoundingBox();
     //        $totalBoundingBox->addRectangle();
     //        $totalBoundingBox->addRectangle();
     $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;
     // 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);
     $label_x1 -= $bbox_x1;
     $label_x2 -= $bbox_x1;
     $label_y1 -= $bbox_y1;
     $label_y2 -= $bbox_y1;
     $icon_x1 -= $bbox_x1;
     $icon_y1 -= $bbox_y1;
     // Draw the icon, if any
     if (isset($iconImageRef)) {
         $iconObj->draw($node_im, $icon_x1, $icon_y1);
         //            imagecopy($node_im, $iconImageRef, $icon_x1, $icon_y1, 0, 0, imagesx($iconImageRef), imagesy($iconImageRef));
         //            imagedestroy($iconImageRef);
     }
     // Draw the label, if any
     if ($this->label != '') {
         $labelObj->translate(-$bbox_x1 + $deltaX + $this->labeloffsetx, -$bbox_y1 + $deltaY + $this->labeloffsety);
         $labelObj->draw($node_im);
     }
     $this->centre_x = $this->x - $bbox_x1;
     $this->centre_y = $this->y - $bbox_y1;
     $this->image = $node_im;
 }
 public function testWeathermapInternals()
 {
     $this->assertEquals(array(0, 0), WMUtility::calculateOffset("donkey", 10, 20));
     $this->assertEquals(array(0, 0), WMUtility::calculateOffset("", 10, 20));
     $this->assertEquals(array(0, 0), WMUtility::calculateOffset("C", 10, 20));
     // +Y is down (i.e. South)
     $this->assertEquals(array(0, -10), WMUtility::calculateOffset("N", 10, 20));
     $this->assertEquals(array(0, 10), WMUtility::calculateOffset("S", 10, 20));
 }