hide=$aHide; } public function SetHColMargin($aXMarg) { $this->xmargin = $aXMarg; } public function SetVColMargin($aSpacing) { $this->ylinespacing = $aSpacing ; } public function SetLeftMargin($aXMarg) { $this->xlmargin = $aXMarg; } // Synonym public function SetLineSpacing($aSpacing) { $this->ylinespacing = $aSpacing ; } public function SetShadow($aShow='gray', $aWidth=4) { if (is_string($aShow)) { $this->shadow_color = $aShow; $this->shadow=true; } else { $this->shadow = $aShow; } $this->shadow_width = $aWidth; } public function SetMarkAbsSize($aSize) { $this->mark_abs_vsize = $aSize ; $this->mark_abs_hsize = $aSize ; } public function SetMarkAbsVSize($aSize) { $this->mark_abs_vsize = $aSize ; } public function SetMarkAbsHSize($aSize) { $this->mark_abs_hsize = $aSize ; } public function SetLineWeight($aWeight) { $this->weight = $aWeight; } public function SetFrameWeight($aWeight) { $this->frameweight = $aWeight; } public function SetLayout($aDirection=LEGEND_VERT) { $this->layout_n = $aDirection==LEGEND_VERT ? 1 : 99 ; } public function SetColumns($aCols) { $this->layout_n = $aCols ; } public function SetReverse($f=true) { $this->reverse = $f ; } // Set color on frame around box public function SetColor($aFontColor, $aColor='black') { $this->font_color=$aFontColor; $this->color=$aColor; } public function SetFont($aFamily, $aStyle=FS_NORMAL, $aSize=10) { $this->font_family = $aFamily; $this->font_style = $aStyle; $this->font_size = $aSize; } public function SetPos($aX, $aY, $aHAlign='right', $aVAlign='top') { $this->Pos($aX, $aY, $aHAlign, $aVAlign); } public function SetAbsPos($aX, $aY, $aHAlign='right', $aVAlign='top') { $this->xabspos=$aX; $this->yabspos=$aY; $this->halign=$aHAlign; $this->valign=$aVAlign; } public function Pos($aX, $aY, $aHAlign='right', $aVAlign='top') { if (!($aX<1 && $aY<1)) { JpGraphError::RaiseL(25120);//(" Position for legend must be given as percentage in range 0-1"); } $this->xpos=$aX; $this->ypos=$aY; $this->halign=$aHAlign; $this->valign=$aVAlign; } public function SetFillColor($aColor) { $this->fill_color=$aColor; } public function Clear() { $this->txtcol = array(); } public function Add($aTxt, $aColor, $aPlotmark='', $aLinestyle=0, $csimtarget='', $csimalt='', $csimwintarget='') { $this->txtcol[]=array($aTxt,$aColor,$aPlotmark,$aLinestyle,$csimtarget,$csimalt,$csimwintarget); } public function GetCSIMAreas() { return $this->csimareas; } public function SetBackgroundGradient($aFrom='navy', $aTo='silver', $aGradType=2) { $this->bkg_gradtype=$aGradType; $this->bkg_gradfrom = $aFrom; $this->bkg_gradto = $aTo; } public function HasItems() { return (boolean)(count($this->txtcol)); } public function Stroke($aImg) { // Constant $fillBoxFrameWeight=1; if ($this->hide) { return; } $aImg->SetFont($this->font_family, $this->font_style, $this->font_size); if ($this->reverse) { $this->txtcol = array_reverse($this->txtcol); } $n=count($this->txtcol); if ($n == 0) { return; } // Find out the max width and height of each column to be able // to size the legend box. $numcolumns = ($n > $this->layout_n ? $this->layout_n : $n); for ($i=0; $i < $numcolumns; ++$i) { $colwidth[$i] = $aImg->GetTextWidth($this->txtcol[$i][0]) + 2*$this->xmargin + 2*$this->mark_abs_hsize; $colheight[$i] = 0; } // Find our maximum height in each row $rows = 0 ; $rowheight[0] = 0; for ($i=0; $i < $n; ++$i) { $h = max($this->mark_abs_vsize, $aImg->GetTextHeight($this->txtcol[$i][0]))+$this->ylinespacing; // Makes sure we always have a minimum of 1/4 (1/2 on each side) of the mark as space // between two vertical legend entries //$h = round(max($h,$this->mark_abs_vsize+$this->ymargin)); //echo "Textheight #$i: tetxheight=".$aImg->GetTextHeight($this->txtcol[$i][0]).', '; //echo "h=$h ({$this->mark_abs_vsize},{$this->ymargin})
"; if ($i % $numcolumns == 0) { $rows++; $rowheight[$rows-1] = 0; } $rowheight[$rows-1] = max($rowheight[$rows-1], $h)+1; } $abs_height = 0; for ($i=0; $i < $rows; ++$i) { $abs_height += $rowheight[$i] ; } // Make sure that the height is at least as high as mark size + ymargin $abs_height = max($abs_height, $this->mark_abs_vsize); $abs_height += $this->ybottom_margin; // Find out the maximum width in each column for ($i=$numcolumns; $i < $n; ++$i) { $colwidth[$i % $numcolumns] = max( $aImg->GetTextWidth($this->txtcol[$i][0])+2*$this->xmargin+2*$this->mark_abs_hsize, $colwidth[$i % $numcolumns] ); } // Get the total width $mtw = 0; for ($i=0; $i < $numcolumns; ++$i) { $mtw += $colwidth[$i] ; } // remove the last rows interpace margin (since there is no next row) $abs_height -= $this->ylinespacing; // Find out maximum width we need for legend box $abs_width = $mtw+$this->xlmargin+($numcolumns-1)*$this->mark_abs_hsize; if ($this->xabspos === -1 && $this->yabspos === -1) { $this->xabspos = $this->xpos*$aImg->width ; $this->yabspos = $this->ypos*$aImg->height ; } // Positioning of the legend box if ($this->halign == 'left') { $xp = $this->xabspos; } elseif ($this->halign == 'center') { $xp = $this->xabspos - $abs_width/2; } else { $xp = $aImg->width - $this->xabspos - $abs_width; } $yp=$this->yabspos; if ($this->valign == 'center') { $yp-=$abs_height/2; } elseif ($this->valign == 'bottom') { $yp-=$abs_height; } // Stroke legend box $aImg->SetColor($this->color); $aImg->SetLineWeight($this->frameweight); $aImg->SetLineStyle('solid'); if ($this->shadow) { $aImg->ShadowRectangle( $xp, $yp, $xp+$abs_width+$this->shadow_width+2, $yp+$abs_height+$this->shadow_width+2, $this->fill_color, $this->shadow_width+2, $this->shadow_color ); } else { $aImg->SetColor($this->fill_color); $aImg->FilledRectangle($xp, $yp, $xp+$abs_width, $yp+$abs_height); $aImg->SetColor($this->color); $aImg->Rectangle($xp, $yp, $xp+$abs_width, $yp+$abs_height); } if ($this->bkg_gradtype >= 0) { $grad = new Gradient($aImg); $grad->FilledRectangle( $xp+1, $yp+1, $xp+$abs_width-3, $yp+$abs_height-3, $this->bkg_gradfrom, $this->bkg_gradto, $this->bkg_gradtype ); } // x1,y1 is the position for the legend marker + text // The vertical position is the baseline position for the text // and every marker is adjusted acording to that. // For multiline texts this get more complicated. $x1 = $xp + $this->xlmargin; $y1 = $yp + $rowheight[0] - $this->ylinespacing + 2 ; // The ymargin is included in rowheight // Now, y1 is the bottom vertical position of the first legend, i.e if // the legend has multiple lines it is the bottom line. $grad = new Gradient($aImg); $patternFactory = null; // Now stroke each legend in turn // Each plot has added the following information to the legend // p[0] = Legend text // p[1] = Color, // p[2] = For markers a reference to the PlotMark object // p[3] = For lines the line style, for gradient the negative gradient style // p[4] = CSIM target // p[5] = CSIM Alt text $i = 1 ; $row = 0; foreach ($this->txtcol as $p) { // STROKE DEBUG BOX if (_JPG_DEBUG) { $aImg->SetLineWeight(1); $aImg->SetColor('red'); $aImg->SetLineStyle('solid'); $aImg->Rectangle($x1, $y1, $xp+$abs_width-1, $y1-$rowheight[$row]); } $aImg->SetLineWeight($this->weight); $x1 = round($x1)+1; // We add one to not collide with the border $y1=round($y1); // This is the center offset up from the baseline which is // considered the "center" of the marks. This gets slightly complicated since // we need to consider if the text is a multiline paragraph or if it is only // a single line. The reason is that for single line the y1 corresponds to the baseline // and that is fine. However for a multiline paragraph there is no single baseline // and in that case the y1 corresponds to the lowest y for the bounding box. In that // case we center the mark in the middle of the paragraph if (!preg_match('/\n/', $p[0])) { // Single line $marky = ceil($y1-$this->mark_abs_vsize/2)-1; } else { // Paragraph $marky = $y1 - $aImg->GetTextHeight($p[0])/2; // echo "y1=$y1, p[o]={$p[0]}, marky=$marky
"; } //echo "
Mark #$i: marky=$marky
"; $x1 += $this->mark_abs_hsize; if (!empty($p[2]) && $p[2]->GetType() > -1) { // Make a plot mark legend. This is constructed with a mark which // is run through with a line // First construct a bit of the line that looks exactly like the // line in the plot $aImg->SetColor($p[1]); if (is_string($p[3]) || $p[3]>0) { $aImg->SetLineStyle($p[3]); $aImg->StyleLine($x1-$this->mark_abs_hsize, $marky, $x1+$this->mark_abs_hsize, $marky); } // Stroke a mark using image if ($p[2]->GetType() == MARK_IMG) { $p[2]->Stroke($aImg, $x1, $marky); } // Stroke a mark with the standard size // (As long as it is not an image mark ) if ($p[2]->GetType() != MARK_IMG) { // Clear any user callbacks since we ont want them called for // the legend marks $p[2]->iFormatCallback = ''; $p[2]->iFormatCallback2 = ''; // Since size for circles is specified as the radius // this means that we must half the size to make the total // width behave as the other marks if ($p[2]->GetType() == MARK_FILLEDCIRCLE || $p[2]->GetType() == MARK_CIRCLE) { $p[2]->SetSize(min($this->mark_abs_vsize, $this->mark_abs_hsize)/2); $p[2]->Stroke($aImg, $x1, $marky); } else { $p[2]->SetSize(min($this->mark_abs_vsize, $this->mark_abs_hsize)); $p[2]->Stroke($aImg, $x1, $marky); } } } elseif (!empty($p[2]) && (is_string($p[3]) || $p[3]>0)) { // Draw a styled line $aImg->SetColor($p[1]); $aImg->SetLineStyle($p[3]); $aImg->StyleLine($x1-$this->mark_abs_hsize, $marky, $x1+$this->mark_abs_hsize, $marky); $aImg->StyleLine($x1-$this->mark_abs_hsize, $marky+1, $x1+$this->mark_abs_hsize, $marky+1); } else { // Draw a colored box $color = $p[1] ; // We make boxes slightly larger to better show $boxsize = max($this->mark_abs_vsize, $this->mark_abs_hsize) + 2 ; $ym = $marky-ceil($boxsize/2) ; // Marker y-coordinate // We either need to plot a gradient or a // pattern. To differentiate we use a kludge. // Patterns have a p[3] value of < -100 if ($p[3] < -100) { // p[1][0] == iPattern, p[1][1] == iPatternColor, p[1][2] == iPatternDensity if ($patternFactory == null) { $patternFactory = new RectPatternFactory(); } $prect = $patternFactory->Create($p[1][0], $p[1][1], 1); $prect->SetBackground($p[1][3]); $prect->SetDensity($p[1][2]+1); $prect->SetPos(new Rectangle($x1, $ym, $boxsize, $boxsize)); $prect->Stroke($aImg); $prect=null; } else { if (is_array($color) && count($color)==2) { // The client want a gradient color $grad->FilledRectangle( $x1-$boxsize/2, $ym, $x1+$boxsize/2, $ym+$boxsize, $color[0], $color[1], -$p[3] ); } else { $aImg->SetColor($p[1]); $aImg->FilledRectangle($x1-$boxsize/2, $ym, $x1+$boxsize/2, $ym+$boxsize); } // Draw a plot frame line $aImg->SetColor($this->color); $aImg->SetLineWeight($fillBoxFrameWeight); $aImg->Rectangle( $x1-$boxsize/2, $ym, $x1+$boxsize/2, $ym+$boxsize ); } } $aImg->SetColor($this->font_color); $aImg->SetFont($this->font_family, $this->font_style, $this->font_size); $aImg->SetTextAlign('left', 'baseline'); $debug=false; $aImg->StrokeText( $x1+$this->mark_abs_hsize+$this->xmargin, $y1, $p[0], 0, 'left', $debug ); // Add CSIM for Legend if defined if (!empty($p[4])) { $xs = $x1 - $this->mark_abs_hsize ; $ys = $y1 + 1 ; $xe = $x1 + $aImg->GetTextWidth($p[0]) + $this->mark_abs_hsize + $this->xmargin ; $ye = $y1-$rowheight[$row]+1; $coords = "$xs,$ys,$xe,$y1,$xe,$ye,$xs,$ye"; if (! empty($p[4])) { $this->csimareas .= "csimareas .= " target=\"".$p[6]."\""; } if (!empty($p[5])) { $tmp=sprintf($p[5], $p[0]); $this->csimareas .= " title=\"$tmp\" alt=\"$tmp\" "; } $this->csimareas .= " />\n"; } } if ($i >= $this->layout_n) { $x1 = $xp+$this->xlmargin; $row++; if (!empty($rowheight[$row])) { $y1 += $rowheight[$row]; } $i = 1; } else { $x1 += $colwidth[($i-1) % $numcolumns] ; ++$i; } } } } // Class