public function render($ge)
 {
     //            BpRectangle::render($ge);
     $sx = $ge->tx($this->sx());
     $sy = $ge->ty($this->sy());
     $ex = $ge->tx($this->ex());
     $ey = $ge->ty($this->ey());
     $width = $ex - $sx - $this->margin() * 2;
     $height = $ey - $sy - $this->margin() * 2;
     $lines = array();
     $cur_words = array();
     $cur_width = 0;
     $cur_line = '';
     if ($this->fontSize() !== '') {
         $font_size = $this->fontSize();
         $line_height = BpFontMetrics::getLineHeightFromFontSize($this->font(), $this->string(), $this->fontSize());
     } else {
         $font_size = BpFontMetrics::getFontSizeFromLineHeight($this->font(), $this->string(), $this->lineHeight());
         $line_height = $this->lineHeight();
     }
     $words = explode(' ', $this->string());
     foreach ($words as $word) {
         $my_words = $cur_words;
         $my_words[] = $word;
         $cur_width = BpFontMetrics::getWidth($this->font(), implode(' ', $my_words), $font_size);
         if ($cur_width <= $height) {
             $cur_words[] = $word;
         } else {
             $lines[] = implode(' ', $cur_words);
             $cur_words = array($word);
         }
     }
     $lines[] = implode(' ', $cur_words);
     $cur_pos = $sx + $this->margin();
     $centre = $sy + ($ey - $sy) / 2;
     $rounded = ceil($line_height);
     $texts = array();
     foreach ($lines as $line) {
         $metrics = new BpFontMetrics($this->font(), $line, 90);
         $metrics->constrainYCentre($centre);
         $metrics->constrainLeft($cur_pos);
         $metrics->constrainRight($cur_pos + $line_height);
         $metrics->maxFontSize($font_size);
         $cur_text = new BpText($this->z, $this->textColour(), $metrics);
         $texts[] = $cur_text;
         $cur_pos += $rounded;
     }
     if ($cur_pos > $this->ex) {
         $this->ex = $cur_pos + $this->margin();
     }
     BpRectangle::render($ge);
     foreach ($texts as $cur_text) {
         $cur_text->render($ge);
     }
 }
 public function render($ge)
 {
     //BpRectangle::render($ge);
     $sx = $ge->tx($this->sx());
     $sy = $ge->ty($this->sy());
     $ex = $ge->tx($this->ex());
     $ey = $ge->ty($this->ey());
     $width = $ex - $sx - $this->margin * 2;
     $height = $ey - $sy - $this->margin * 2;
     $lines = array();
     $cur_words = array();
     $cur_width = 0;
     $cur_line = '';
     if ($this->font_size) {
         $font_size = $this->font_size;
         $line_height = BpFontMetrics::getLineHeightFromFontSize($this->font, $this->string, $this->font_size);
     } else {
         $font_size = BpFontMetrics::getFontSizeFromLineHeight($this->font, $this->string, $this->line_height);
         $line_height = $this->line_height;
     }
     $words = explode(' ', $this->string);
     foreach ($words as $word) {
         $my_words = $cur_words;
         $my_words[] = $word;
         $cur_width = BpFontMetrics::getWidth($this->font, implode(' ', $my_words), $font_size);
         if ($cur_width <= $width) {
             $cur_words[] = $word;
         } else {
             $lines[] = implode(' ', $cur_words);
             $cur_words = array($word);
         }
     }
     $lines[] = implode(' ', $cur_words);
     $cur_pos = $sy + $this->margin;
     switch ($this->alignment) {
         case BpTextBox::CENTRE:
             $constraint = $sx + ($ex - $sx) / 2;
             break;
         case BpTextBox::LEFT:
             $constraint = $sx;
             break;
         case BpTextBox::RIGHT:
             throw new Exception('unimplemented BpTextBox::RIGHT in BpTextBox::render()');
             break;
         default:
             throw new Exception('Invalid alignment: ' . $this->alignment);
             break;
     }
     $rounded = $line_height;
     //ceil($line_height);
     $texts = array();
     foreach ($lines as $line) {
         $metrics = new BpFontMetrics($this->font, $line, 0);
         switch ($this->alignment) {
             case BpTextBox::CENTRE:
                 $metrics->constrainXCentre($constraint);
                 break;
             case BpTextBox::LEFT:
                 $metrics->constrainLeft($constraint);
                 break;
             case BpTextBox::RIGHT:
                 throw new Exception('unimplemented BpTextBox::RIGHT in BpTextBox::render()');
                 break;
             default:
                 throw new Exception('Invalid alignment: ' . $this->alignment);
                 break;
         }
         $metrics->constrainTop($cur_pos);
         $metrics->constrainBottom($cur_pos + $line_height);
         $metrics->maxFontSize($font_size);
         $cur_text = new BpText($this->z, $this->text_colour, $metrics);
         $texts[] = $cur_text;
         $cur_pos += $rounded;
     }
     if ($cur_pos > $this->ey) {
         $this->ey = $cur_pos + $this->margin;
     }
     BpRectangle::render($ge);
     foreach ($texts as $cur_text) {
         $cur_text->render($ge);
     }
 }
 private function constrainFromBounds()
 {
     if ($this->top !== '' && $this->bottom !== '') {
         $line_height = $this->bottom - $this->top;
         $font_size = BpFontMetrics::getFontSizeFromLineHeight($this->font, $this->text, $line_height);
         $this->font_size = $font_size;
         $size = imagettfbbox($font_size, 0, $this->font, $this->text);
         $width = abs($size[2]) + abs($size[0]);
         $height = abs($size[7]);
         //abs($size[1]) + abs($size[7]);
         if ($this->left !== '') {
             $sx = $this->left;
             $ex = $this->left + $width * cos(deg2rad($this->angle));
             $sy = $this->top + $height;
             $ey = $sy + $height;
             //$this->bottom;
         } else {
             if ($this->right !== '') {
                 $sx = $this->right - $width * cos(deg2rad($this->angle));
                 $sy = $this->top + $height;
                 $ex = $this->right;
                 $ey = $this->bottom;
             }
         }
     } else {
         if ($this->left !== '' && $this->right !== '') {
             die('Constraint with left and right and top or bottom has not been implemented yet in constrainFromBounds()');
         }
     }
     $ret = array('sx' => $sx, 'sy' => $sy, 'ex' => $ex, 'ey' => $ey);
     return $ret;
 }
 protected function origin()
 {
     $metrics = new BpFontMetrics('Activa', '0', 0);
     $metrics->constrainTop($this->height() - $this->horizMargin() + $this->vertMargin() / 4);
     $metrics->constrainBottom($this->height() - $this->horizMargin() + $this->vertMargin() / 2);
     $metrics->constrainXCentre($this->horizMargin() / 3 * 2);
     $ret = new BpText(0, 'black', $metrics);
     return $ret;
 }