Report problems to ATLAS LXR Team (with time and IP address indicated)

The LXR Cross Referencer

source navigation ]
diff markup ]
identifier search ]
general search ]
 
 
Architecture: linux ]
Version: head ] [ nightly ] [ GaudiDev ]
  Links to LXR source navigation pages for stable releases [ 12.*.* ]   [ 13.*.* ]   [ 14.*.* ] 

001 package atlantis.canvas;
002 
003 //Charles A. Loomis, Jr., and University of California, Santa Cruz,
004 //Copyright (c) 2000
005 
006 import atlantis.graphics.AAbstractGraphics2D;
007 import java.awt.BasicStroke;
008 import java.awt.Color;
009 import java.awt.Component;
010 import java.awt.Font;
011 import java.awt.Graphics;
012 import java.awt.Graphics2D;
013 import java.awt.Insets;
014 import java.awt.Rectangle;
015 import java.awt.Stroke;
016 import java.awt.Image;
017 import java.awt.geom.AffineTransform;
018 import java.awt.geom.GeneralPath;
019 import java.awt.geom.NoninvertibleTransformException;
020 import java.awt.geom.Point2D;
021 
022 import javax.swing.border.Border;
023 
024 import atlantis.graphics.ALegoDraw;
025 import atlantis.graphics.APSGraphics2D;
026 import atlantis.gui.APreferencesControl;
027 import atlantis.parameters.AEnumeratorParameter;
028 import atlantis.parameters.ALinkParameter;
029 import atlantis.parameters.APar;
030 import atlantis.parameters.AParameter;
031 import atlantis.projection.AProjection;
032 import atlantis.projection.AProjectionLegoPlot;
033 import atlantis.projection.AProjectionTrackResidual;
034 import atlantis.gui.ACursorFactory;
035 import atlantis.utils.AMath;
036 import java.awt.RenderingHints;
037 
038 /**
039  * This class implements a Border in which the left and bottom sides contain
040  * numerical scales.
041  *
042  * @author Charles Loomis, Sebastian Boeser
043  * @version $Id: AScaleBorder.java,v 1.26 2008/07/31 12:00:56 adavison Exp $
044  */
045 public class AScaleBorder implements Border
046 {
047     /**
048      * Constant giving the unicode value of a capital Greek delta.
049      */
050     final static private int SELECTED = 2;
051 
052     /**
053      * Constant giving the unicode value of a capital Greek delta.
054      */
055     final static private String DELTA = "\u0394";
056 
057     /**
058      * Constant giving the unicode value of a prime symbol.
059      */
060     final static private String PRIME = "\u00b4";
061 
062     /**
063      * Constant giving the unicode value of a middle dot.
064      */
065     final static private String DOT = "\u00b7";
066 
067     /**
068      * A constant giving the horizontal index of the data arrays.
069      */
070     final static private int HORIZONTAL = 0;
071 
072     /**
073      * A constant giving the vertical index of the data arrays.
074      */
075     final static private int VERTICAL = 1;
076 
077     /**
078      * Constant describing a transform in which the transformed x and y axes are
079      * parallel (or antiparallel) to the original axes.
080      */
081     final static public int TYPE_PARALLEL_TRANSFORM = 0;
082 
083     /**
084      * Constant describing a transform in which the transformed x and y axes are
085      * parallel (or antiparallel) to the original y and x axes, respectively.
086      */
087     final static public int TYPE_SWITCHED_TRANSFORM = 1;
088 
089     /**
090      * Constant describing a transform in which the transformed x-axis is
091      * parallel (or antiparallel) to the original x-axis and the transformed
092      * y-axis forms a non-zero angle with the original one.
093      */
094     final static public int TYPE_X_SKEW_TRANSFORM = 2;
095 
096     /**
097      * Constant describing a transform in which the transformed y-axis is
098      * parallel (or antiparallel) to the original y-axis and the transformed
099      * x-axis forms a non-zero angle with the original one.
100      */
101     final static public int TYPE_Y_SKEW_TRANSFORM = 3;
102 
103     /**
104      * Constant describing a transform in which the transformed x-axis is
105      * parallel (or antiparallel) to the original y-axis and the transformed
106      * y-axis forms a non-zero angle with the original x-axis.
107      */
108     final static public int TYPE_SWITCHED_X_SKEW_TRANSFORM = 4;
109 
110     /**
111      * Constant describing a transform in which the transformed y-axis is
112      * parallel (or antiparallel) to the original x-axis and the transformed
113      * x-axis forms a non-zero angle with the original y-axis.
114      */
115     final static public int TYPE_SWITCHED_Y_SKEW_TRANSFORM = 5;
116 
117     /**
118      * Constant describing a transform which does not fall into one of the other
119      * categories.
120      */
121     final static public int TYPE_GENERAL_TRANSFORM = 6;
122 
123     /**
124      * Constant indicating that a string should be aligned vertically with the
125      * baseline of the text. This is the default in drawString calls which do
126      * not specify an alignment.
127      */
128     public static final int TEXT_BASELINE = 0;
129 
130     /**
131      * Constant indicating that a string should be aligned vertically with the
132      * top of the text.
133      */
134     public static final int TEXT_TOP = 1;
135 
136     /**
137      * Constant indicating that a string should be aligned vertically with the
138      * bottom of the text.
139      */
140     public static final int TEXT_BOTTOM = 3;
141 
142     /**
143      * Constant indicating that a string should be aligned by the center. This
144      * is used for both horizontal and vertical alignment.
145      */
146     public static final int TEXT_CENTER = 2;
147 
148     /**
149      * Constant indicating that a string should be aligned horizontally with the
150      * left side of the text. This is the default for drawString calls which do
151      * not specify an alignment.
152      */
153     public static final int TEXT_LEFT = 1;
154 
155     /**
156      * Constant indicating that the string should be aligned horizontally with
157      * the right side of the text.
158      */
159     public static final int TEXT_RIGHT = 3;
160 
161     /**
162      * Paths describing the primary tick marks for the two axes.
163      */
164     private GeneralPath[] pTicks = new GeneralPath[2];
165 
166     /**
167      * Paths describing the secondary tick marks for the two axes.
168      */
169     private GeneralPath[] sTicks = new GeneralPath[2];
170 
171     /**
172      * String giving the axis labels.
173      */
174     private String[] axisLabels = new String[2];
175 
176     /**
177      * String giving the axis units.
178      */
179     private String[] axisUnits = new String[2];
180 
181     /**
182      * The labels for the horizontal and vertical axes.
183      */
184     private String[][] labels;
185 
186     /**
187      * The positions of each of the axis labels.
188      */
189     private double[][] positions;
190 
191     /**
192      * The initial font size for labeling.
193      */
194     private int fontSize = 12;
195 
196     /**
197      * The initial font to use.
198      */
199     private Font labelFont = new Font("SansSerif", Font.BOLD, 12);
200 
201     /**
202      * The width of the line used for the secondary tick marks.
203      */
204     final static private Stroke thinStroke = new BasicStroke(1.f);
205 
206     /**
207      * The width of the line used for the primary tick marks.
208      */
209     final static private Stroke thickStroke = new BasicStroke(2.f);
210 
211     /**
212      * An array to hold temporary point values for transformation.
213      */
214     private double[] axisPts = new double[6];
215 
216     /**
217      * Flag to indicate that the scale has changed and that it needs to be
218      * redrawn.
219      */
220     private boolean scaleChanged;
221 
222 
223     /**
224      * The current width of the horizontal scale.
225      */
226     private int currentWidth;
227 
228     /**
229      * The current width of the vertical scale.
230      */
231     private int currentHeight;
232 
233     /**
234      * Minimum value on the horizontal axis.
235      */
236     private double minHoriz;
237 
238     /**
239      * Maximum value of the horizontal axis.
240      */
241     private double maxHoriz;
242 
243     /**
244      * Minimum value of the vertical axis.
245      */
246     private double minVert;
247 
248     /**
249      * Maximum value on the vertical axis.
250      */
251     private double maxVert;
252 
253     /**
254      * The calculated Insets for this border.
255      */
256     private Insets insets;
257 
258     private boolean selected;
259     
260     /** 
261      * Wether to draw the scales for this window or not
262      */
263     private boolean drawScaleBorder;
264     
265     /**
266      * The window this scale is drawn in.
267      */
268     private AWindow aWindow;
269 
270     /**
271      * Constructs a AScaleBorder that belongs to theWindow
272      */
273     public AScaleBorder(AWindow theWindow)
274     {
275         aWindow = theWindow;
276 
277         // Give default values for the size of the axes.
278         minHoriz = 0.;
279         maxHoriz = 0.;
280         minVert = 0.;
281         maxVert = 0.;
282 
283         // Make the new insets.
284         resetInsets();
285 
286         // Make the paths which will hold the axes.
287         pTicks[HORIZONTAL] = new GeneralPath();
288         pTicks[VERTICAL] = new GeneralPath();
289         sTicks[HORIZONTAL] = new GeneralPath();
290         sTicks[VERTICAL] = new GeneralPath();
291 
292         // Make the labels and positions.
293         labels = new String[2][3];
294         positions = new double[2][3];
295 
296         // Set the current width and height.
297         currentWidth = 0;
298         currentHeight = 0;
299         scaleChanged = false;
300 
301         selected = false;
302         drawScaleBorder = true;
303     }
304 
305     public void forceDraw()
306     {
307         scaleChanged = true;
308     }
309 
310     public void toggleScale()
311     {
312         drawScaleBorder = !drawScaleBorder;
313         scaleChanged = true;
314         resetInsets();
315     }
316 
317     public boolean getScaleStatus()
318     {
319         return drawScaleBorder;
320     }
321 
322     /**
323      * Set the font for the labels.
324      */
325     public void setLabelFont(Font labelFont)
326     {
327         this.labelFont = labelFont;
328         fontSize = labelFont.getSize();
329         resetInsets();
330     }
331 
332     public void setSelected()
333     {
334         selected = true;
335     }
336 
337     public void setDeselected()
338     {
339         selected = false;
340     }
341 
342     /**
343      * Get the current font for the labels.
344      */
345     public Font getLabelFont()
346     {
347         return labelFont;
348     }
349 
350     /**
351      * Set the horizontal and vertical limits for the scales.
352      */
353     public void setLimits(double minHoriz, double maxHoriz, double minVert, double maxVert)
354     {
355         this.minHoriz = minHoriz;
356         this.maxHoriz = maxHoriz;
357         this.minVert = minVert;
358         this.maxVert = maxVert;
359         scaleChanged = true;
360     }
361 
362     /**
363      * Set the axis labels.
364      */
365     public void setAxisLabels(String horizontalLabel, String verticalLabel)
366     {
367         axisLabels[HORIZONTAL] = horizontalLabel;
368         axisLabels[VERTICAL] = verticalLabel;
369     }
370 
371     public String getHorizontalAxisLabel()
372     {
373         return axisLabels[HORIZONTAL];
374     }
375 
376     public String getVerticalAxisLabel()
377     {
378         return axisLabels[VERTICAL];
379     }
380 
381     /**
382      * Set the axis units.
383      */
384     public void setAxisUnits(String horizontalUnits, String verticalUnits)
385     {
386         if (horizontalUnits != null)
387         {
388             axisUnits[HORIZONTAL] = horizontalUnits;
389         }
390         else
391         {
392             axisUnits[HORIZONTAL] = "";
393         }
394 
395         if (verticalUnits != null)
396         {
397             axisUnits[VERTICAL] = verticalUnits;
398         }
399         else
400         {
401             axisUnits[VERTICAL] = "";
402         }
403     }
404 
405     /**
406      * Returns the insets of this border.
407      */
408     public Insets getBorderInsets(Component c)
409     {
410         return (Insets) insets.clone();
411     }
412 
413     /**
414      * Returns whether or not the border is opaque. This always returns true.
415      */
416     public boolean isBorderOpaque()
417     {
418         return true;
419     }
420     
421     /**
422      * Paints the border and window decorations for the specified component with the specified graphics
423      * context, position, and size.
424      */
425     public void paintBorder(Component c, Graphics g, int x, int y, int width, int height)
426     {
427         //Get the graphics context
428         Graphics2D vg = (Graphics2D) g;
429         //Sanity check
430         if (vg==null) return;
431         
432         //Now check which projection we have
433         AProjection p = aWindow.getProjection();
434   
435         //Check if we shall draw the border
436         if (drawScaleBorder)
437         {   
438             //If we have a lego projection, the scale is just a frame
439             if (p instanceof AProjectionLegoPlot)
440             {
441                 //Select background, forground and frame colors
442                 Color bg = ALegoDraw.getBackgroundColor();
443                 Color fg = bg;
444 
445                 //Paint the border frame
446                 paintBorderFrame(vg,fg,bg,width,height);
447             }
448             else
449             {                
450                 //Select background, forground and frame colors
451                 Color bg = AWindow.BORDER_BACKGROUND_COLOR ;
452                 Color fg = AWindow.BORDER_FOREGROUND_COLOR;
453                 //Highlight by colors if selected
454                 if (selected){
455                     fg = AWindow.BORDER_SELECTED_FOREGROUND_COLOR;
456                     bg = AWindow.BORDER_SELECTED_BACKGROUND_COLOR;
457                 }
458 
459                 //Paint the border frame
460                 paintBorderFrame(vg,fg,bg,width,height);                
461               
462                 // Set the flag indicating that the scales must be remade.
463                 scaleChanged = (scaleChanged || width != currentWidth || height != currentHeight);
464                
465                 //set the Scales 
466                 setScales(p.getXLabel(), p.getYLabel(), p.getXUnits(), p.getYUnits(), makeTransform(aWindow.getUserCorners()), aWindow.getWidth(), aWindow.getHeight());
467 
468                 //Paint the grid if there is one for this projection
469                 paintGrid(vg,p,width,height);
470        
471                 //Paint the scales themselves
472                 paintScales(vg,p,width,height);
473        
474 
475                  // Reset the current width and height.
476                 currentWidth = width;
477                 currentHeight = height;
478                 scaleChanged = false;
479             }
480         }
481         
482 
483         //Check wether Window Title needs to be drawn
484         if(APreferencesControl.getWindowTitleMenuItem())
485             paintWindowTitle(g, width, height);
486         
487         //Check wether FishEye Indicator needs to be drawn
488         if(APreferencesControl.getFisheyeIndicatorMenuItem())
489             paintFishEyeIndicator(g, false, width, height);
490     }
491 
492     /**
493      * Paints the part of the border that appears when the window is printed
494      */
495     public void printBorder(Component c, Graphics g, int x, int y, int width, int height)
496     {
497         //Get the graphics context
498         Graphics2D vg = (Graphics2D) g;
499         //Sanity check
500         if (vg==null) return;
501         
502         //Now check which projection we have
503         AProjection p = aWindow.getProjection();
504   
505         //Check if we shall draw the scales
506         if (drawScaleBorder)
507         {   
508             //If we have a lego projection, the scale is just a frame
509             if (p instanceof AProjectionLegoPlot)
510             {
511                 //Select background, forground and frame colors
512                 Color bg = ALegoDraw.getBackgroundColor();
513 
514                 //Paint the border frame
515                 printBorderFrame(vg,bg,width,height);
516             }
517             else
518             {                
519                 //Select background colors (ignore selection)
520                 Color bg = AWindow.BORDER_BACKGROUND_COLOR ;
521  
522                 //Paint the border frame
523                 printBorderFrame(vg,bg,width,height);                
524               
525                 // Set the flag indicating that the scales must be remade.
526                 scaleChanged = (scaleChanged || width != currentWidth || height != currentHeight);
527                
528                 //set the Scales 
529                 setScales(p.getXLabel(), p.getYLabel(), p.getXUnits(), p.getYUnits(), makeTransform(aWindow.getUserCorners()), aWindow.getWidth(), aWindow.getHeight());
530 
531                 //Paint the grid if there is one for this projection
532                 printGrid(vg,p,width,height);
533        
534                 //Paint the scales themselves
535                 printScales(vg,p,width,height);
536        
537                  // Reset the current width and height.
538                 currentWidth = width;
539                 currentHeight = height;
540                 scaleChanged = false;
541             }
542         }
543         
544         //Check wether Window Title needs to be drawn
545         if(APreferencesControl.getWindowTitleMenuItem())
546             paintWindowTitle(g, width, height);
547         
548         //Check wether FishEye Indicator needs to be drawn
549         if(APreferencesControl.getFisheyeIndicatorMenuItem())
550             printFishEyeIndicator(g, width, height);
551     }
552 
553  
554     /**
555      * Draw the part of the scales that shows up in printing
556      */
557     private void printScales(Graphics2D g, AProjection p, int width, int height){
558 
559         // Make our own graphics contex, so we don't cause trouble elsewhere
560         Graphics2D svg = (Graphics2D) g.create();
561      
562         // Get the horizontal scale.
563         if (scaleChanged)
564         {
565             AScale.calculateScale(minHoriz, maxHoriz, width - (insets.left + insets.right), 3, 7, AScale.RIGHT_TICKS,
566                     pTicks[HORIZONTAL], sTicks[HORIZONTAL], labels[HORIZONTAL], positions[HORIZONTAL], HORIZONTAL, p);
567         }
568 
569         svg.translate(insets.left, height - insets.bottom + 2);
570 
571         // Set the color and font.
572         if (selected)
573             svg.setColor(aWindow.BORDER_SELECTED_FOREGROUND_COLOR);
574         else
575             svg.setColor(aWindow.BORDER_FOREGROUND_COLOR);
576         svg.setFont(new Font("SansSerif", Font.BOLD, 12));
577 
578         // Draw the primary and secondary tick marks.
579         svg.setStroke(thickStroke);
580         svg.draw(pTicks[HORIZONTAL]);
581         svg.setStroke(thinStroke);
582         svg.draw(sTicks[HORIZONTAL]);
583 
584         // gary quick ugly mod to add m->cm->mm->um autoscaling
585         double factorH = 1.0;
586         String unitsH = axisUnits[HORIZONTAL];
587         double deltaH = Math.abs(maxHoriz - minHoriz);
588         double maxH = Math.max(Math.abs(maxHoriz), Math.abs(minHoriz));
589         if (unitsH.equals("(cm)"))
590         {
591             if (maxH > 200.)
592             {
593                 factorH = 0.01;
594                 unitsH = "(m) ";
595             }
596             else if (maxH > 2.)
597             {
598                 factorH = 1.0;
599                 unitsH = "(cm)";
600             }
601             else if (maxH > .2)
602             {
603                 factorH = 10.;
604                 unitsH = "(mm)";
605             }
606             else
607             {
608                 factorH = 10000.;
609                 unitsH = "(" + AMath.MICRO + "m)";
610             }
611         }
612 
613         double factorV = 1.0;
614         String unitsV = axisUnits[VERTICAL];
615         double deltaV = Math.abs(maxVert - minVert);
616         double maxV = Math.max(Math.abs(maxVert), Math.abs(minVert));
617         if (unitsV.equals("(cm)"))
618         {
619             if (maxV > 200.)
620             {
621                 factorV = 0.01;
622                 unitsV = "(m) ";
623             }
624             else if (maxV > 2.)
625             {
626                 factorV = 1.0;
627                 unitsV = "(cm)";
628             }
629             else if (maxV > .2)
630             {
631                 factorV = 10.;
632                 unitsV = "(mm)";
633             }
634             else
635             {
636                 factorV = 10000.;
637                 unitsV = "(" + AMath.MICRO + "m)";
638             }
639         }
640 
641         // Paint the tick labels.
642         for (int i = 0; i < 3; i++)
643         {
644             if (labels[HORIZONTAL][i] != null)
645             {
646                 drawString(svg, "" + trim(java.lang.Double.parseDouble(labels[HORIZONTAL][i]) * factorH, deltaH * factorH),
647                         (float) positions[HORIZONTAL][i], AScale.getPrimaryTickSize() + 0.2f * fontSize, TEXT_CENTER, TEXT_TOP, width - insets.left - insets.right);
648             }
649         }
650 
651         // Paint the axis label. The third position is always set
652         // so that the axis label should be between this position
653         // and one of the other two.
654         float axisPosition;
655 
656         // 0.99 stops label position from flickering
657         if (Math.abs(positions[HORIZONTAL][2] - positions[HORIZONTAL][1]) > 0.99 * Math.abs(positions[HORIZONTAL][2] - positions[HORIZONTAL][0]))
658         {
659             axisPosition = (float) (0.5 * (positions[HORIZONTAL][2] + positions[HORIZONTAL][1]));
660         }
661         else
662         {
663             axisPosition = (float) (0.5 * (positions[HORIZONTAL][2] + positions[HORIZONTAL][0]));
664         }
665         drawString(svg, axisLabels[HORIZONTAL] + " " + unitsH, axisPosition, AScale.getPrimaryTickSize() + 0.2f * fontSize, TEXT_CENTER, TEXT_TOP, width - insets.left - insets.right);
666 
667         // End this context.
668         svg.dispose();
669 
670         // Now create a new graphics context for the vertical axis.
671         svg = (Graphics2D) (g.create());
672 
673         // Create the vertical scale.
674         if (scaleChanged)
675         {
676             AScale.calculateScale(minVert, maxVert, height - (insets.top + insets.bottom), 3, 7, AScale.LEFT_TICKS,
677                     pTicks[VERTICAL], sTicks[VERTICAL], labels[VERTICAL], positions[VERTICAL], VERTICAL, p);
678         }
679 
680         svg.translate(insets.left - 2, height - insets.bottom);
681         svg.rotate(-Math.PI / 2.);
682 
683         // Set the color and font.
684         if (selected)
685             svg.setColor(aWindow.BORDER_SELECTED_FOREGROUND_COLOR);
686         else
687             svg.setColor(aWindow.BORDER_FOREGROUND_COLOR);
688         svg.setFont(new Font("SansSerif", Font.BOLD, 12));
689 
690         // Draw the primary and secondary tick marks.
691         svg.setStroke(thickStroke);
692         svg.draw(pTicks[VERTICAL]);
693         svg.setStroke(thinStroke);
694         svg.draw(sTicks[VERTICAL]);
695 
696         // Paint the tick labels.
697         for (int i = 0; i < 3; i++)
698         {
699             if (labels[VERTICAL][i] != null)
700             {
701                 String tick = "" + trim(java.lang.Double.parseDouble(labels[VERTICAL][i]) * factorV, deltaV * factorV);
702                 if(p instanceof AProjectionTrackResidual && APar.get("TrackResidual", "Scale").getI() == 1)
703                 {
704                     if(!tick.equals("0"))
705                     {
706                         long tmp = Math.round(((AProjectionTrackResidual)p).getResidual().getLogMagnitudeMin() + Math.abs(Double.parseDouble(tick)));
707                         if(tick.indexOf("-") == -1) //positive
708                             tick = "1E" + tmp;
709                         else
710                             tick = "-1E" + tmp;
711                     }
712                 }
713                 drawString(svg, tick, (float) positions[VERTICAL][i], -(AScale.getPrimaryTickSize() + 0.2f * fontSize), TEXT_CENTER, TEXT_BOTTOM, height - insets.top - insets.bottom);
714             }
715         }
716 
717         // Paint the axis label. The third position is always set
718         // so that the axis label should be between this position
719         // and one of the other two.
720 
721         // 0.99 stops label position from flickering
722         if (Math.abs(positions[VERTICAL][2] - positions[VERTICAL][1]) > 0.99 * Math.abs(positions[VERTICAL][2] - positions[VERTICAL][0]))
723         {
724             axisPosition = (float) (0.5 * (positions[VERTICAL][2] + positions[VERTICAL][1]));
725         }
726         else
727         {
728             axisPosition = (float) (0.5 * (positions[VERTICAL][2] + positions[VERTICAL][0]));
729         }
730         drawString(svg, axisLabels[VERTICAL] + " " + unitsV, axisPosition, -(AScale.getPrimaryTickSize() + 0.2f * fontSize), TEXT_CENTER, TEXT_BOTTOM, height - insets.top - insets.bottom);
731 
732         // End this context.
733         svg.dispose();
734 
735     }
736     
737     private void paintScales(Graphics2D g, AProjection p, int width, int height){
738         //Currently same for on-screen and printing
739         printScales(g,p,width,height);
740     }
741     
742     /** 
743      * Draw the grid for the V-Plot
744      **/
745     private void printGrid(Graphics2D g, AProjection p, int width, int height){
746         
747         // Make our own graphics contex, so we don't cause trouble elsewhere
748         Graphics2D svg = (Graphics2D) g.create();
749  
750         // next part draws the grid for the V-plot
751         if (p.getName().equals("VP"))
752         {
753             //Set color for grid lines
754             svg.setColor(Color.LIGHT_GRAY);
755             
756             // eta grid projections values - these particular values
757             // will be useful for calo people to see the eta grid lines at
758             float[] etaGridPositions = { -4.9f, -3.2f, -2.5f, -1.375f, -0.8f,
759                                          0.8f, 1.375f, 2.5f, 3.2f, 4.9f };
760 
761             for(int i = 0; i < etaGridPositions.length; i++)
762             {
763                 Point2D.Double startp = aWindow.calculateDisplay(etaGridPositions[i],minVert);
764                 Point2D.Double endp = aWindow.calculateDisplay(etaGridPositions[i],maxVert);
765                 svg.drawLine((int)startp.x,(int)startp.y,(int)endp.x,(int)endp.y);
766             }
767 
768             /* old symetetric definition of eta values grid lines, to remove
769                when people are happy with the above
770             for (int i = -5; i <= 5; i += 2)
771             {
772                 if (i > minHoriz && i <= maxHoriz)
773                 {
774                     xmin = (int) (insets.right + (i - minHoriz) * xScale);
775                     svg.drawLine(ymin, xmin, ymax, xmin);
776                 }
777             }
778             */
779 
780             for (int i = (int)Math.ceil(minVert/90.)*90; i <= maxVert; i += 90)
781             {
782                 Point2D.Double startp = aWindow.calculateDisplay(minHoriz,i);
783                 Point2D.Double endp = aWindow.calculateDisplay(maxHoriz,i);
784                 if (Math.abs(i) % 360 == 0) {
785                     svg.setColor(Color.WHITE);
786                     svg.setStroke(thickStroke);
787                 } else {
788                     svg.setColor(Color.LIGHT_GRAY);
789                     svg.setStroke(thinStroke);
790                 }
791                 svg.drawLine((int)startp.x,(int)startp.y,(int)endp.x,(int)endp.y);
792             }
793         }
794         
795         // There is no projection with the name EG
796         // CLEANUP ! S.B.
797         /*
798         else if (p.getName().equals("EG"))
799         {
800             //Color ccol = svg.getColor();
801             svg.setColor(Color.lightGray);
802             double yScale = (height - insets.top - insets.bottom) / (maxVert - minVert);
803             double xScale = (width - insets.right - insets.left) / (maxHoriz - minHoriz);
804             int numPoints = 46;
805             int[][][] hv = new int[2][1][numPoints];
806             int j;
807             for (double phi = 0; phi <= 360; phi += 90)
808             {
809                 for (j = 0; j < numPoints; j++)
810                 {
811                     double lamTmp = j * (180.) / (numPoints - 1) - 90.;
812                     hv[0][0][j] = (int) (insets.right + (lamTmp - minHoriz) * xScale);
813                     hv[1][0][j] = (int) ((AMath.eggphil(phi * AMath.DEGREES_TO_RADIANS, lamTmp * AMath.DEGREES_TO_RADIANS) - minVert) * yScale);
814                 }
815                 svg.drawPolyline(hv[1][0], hv[0][0], numPoints);
816                 int ymax = height;
817                 int ymin = 0;
818                 int xmin = insets.right;
819                 for (int i = -90; i <= 90; i += 30)
820                 {
821                     if (i > minHoriz && i <= maxHoriz)
822                     {
823                         ymin = (int) ((AMath.eggphil(0, (double) i * AMath.DEGREES_TO_RADIANS) - minVert) * yScale);
824                         ymax = (int) ((AMath.eggphil(360 * AMath.DEGREES_TO_RADIANS, (double) i * AMath.DEGREES_TO_RADIANS) - minVert) * yScale);
825                         xmin = (int) (insets.right + (i - minHoriz) * xScale);
826                         svg.drawLine(ymin, xmin, ymax, xmin);
827                     }
828                 }
829             }
830         } // end of grid drawing
831         */
832         svg.dispose();
833         
834     }
835     
836     /**
837      * Grid is the same for printed and screen versions
838      */
839     private void paintGrid(Graphics2D g, AProjection p, int width, int height){
840         printGrid(g,p, width, height);
841     }
842     
843     /**
844      * This bit of the frame that is drawn when printing (appart from scales)
845      */
846     private void printBorderFrame(Graphics2D g, Color bg, int width, int height){
847    
848         // Make our own graphics contex, so we don't cause trouble elsewhere
849         Graphics2D svg = (Graphics2D) g.create();
850  
851         svg.setColor(bg);
852         //simply draw rectangles all around window
853         svg.fillRect(0, 0, width, insets.top);
854         // Added -insets.bottom because sometimes this stuff is transparent -Adam
855         svg.fillRect(0, 0, insets.left, height - insets.bottom);
856         svg.fillRect(width - insets.right, 0, insets.right, height);
857         svg.fillRect(0, height - insets.bottom, width, insets.bottom);
858         
859         svg.dispose();
860     }
861     
862     /** 
863      * Paint the Frame of the border with the given colors
864      */
865     private void paintBorderFrame(Graphics2D g, Color fg, Color bg, int width, int height){
866         //Draw the frame same as for printing
867         printBorderFrame(g,bg,width,height);
868         
869        // Make our own graphics contex, so we don't cause trouble elsewhere
870         Graphics2D svg = (Graphics2D) g.create();
871         
872         // Add a bit of GUI-look-and-feel frame
873         if (selected){
874             g.setColor(aWindow.BORDER_SELECTED_FRAME_COLOR);
875             g.drawLine(0, 0, width-1, 0);
876             g.drawLine(0, 0, 0, height-10);
877             g.drawLine(width-1, 0, width-1, height-1);
878             g.drawLine(10, height-1, width-1, height-1);
879             g.drawLine(0, height-10, 9, height-1);
880             g.setColor(aWindow.BORDER_SELECTED_FRAMELIGHT_COLOR);
881             g.drawLine(10, height-2, width-2, height-2);
882             g.drawLine(1, 1, 1, height-10);
883             g.drawLine(1, height-11, 10, height-2);
884             g.setColor(aWindow.BORDER_BACKGROUND_COLOR);
885             int xp[]={0,0,8,0};
886             int yp[]={height-9,height-1,height-1,height-9};
887             g.fillPolygon(xp,yp,4);
888         }
889         
890         svg.dispose();
891     }
892     
893     /**
894      * Paint a small box at the top of each window to describe what is on the window
895      */
896     private void paintWindowTitle(Graphics g, int width, int height)
897     {
898         // Make our own graphics contex, so we don't cause trouble elsewhere
899         Graphics2D svg = (Graphics2D) g.create();
900         //Get Mode parameter
901         String s=aWindow.getProjection().getName();
902         APar.selectWindowParameters(aWindow.getName());
903         AParameter param=APar.get(s, "Mode");
904         int mode=param.getI();
905         s=aWindow.getProjection().getScreenName();
906         s+=" Projection";
907         //Add mode text if not on standard view 
908         if (param != null)
909         {
910             if(mode != 0)
911             {
912                 s+=" viewing: ";
913                 if(param instanceof ALinkParameter){
914                     s+=((ALinkParameter) param).getCurrentText();
915                 }else{
916                     s+=((AEnumeratorParameter) param).getCurrentText();
917                 }
918             }
919         }
920         APar.restoreWindowParameters();
921         //Offset if indicator to window frame
922         int Offset=2;
923         
924         int boxsize,y;
925         if (svg instanceof APSGraphics2D)
926         {
927             //Estimate text width from font size
928             boxsize =(int) Math.round(aWindow.getFontMetrics(svg.getFont()).stringWidth(s)*(1.25)+Offset*2);
929             //Get y position from offset
930             y = Offset+svg.getFont().getSize();
931         }
932         else
933         {
934             // get the width of the text
935             boxsize = svg.getFontMetrics().stringWidth(s)+Offset*2;        
936             //Get y position from offset
937             y = Offset+svg.getFontMetrics().getHeight();
938         }
939         //Get the x position from width of window
940         int x = insets.left + (int) Math.round(((width-insets.left-boxsize)/2.0));
941         //Draw background box and set text color
942         if (svg instanceof APSGraphics2D)
943         {
944             //Box is too wide as can only estimate text width
945             svg.setColor(AWindow.BORDER_BACKGROUND_COLOR);
946             svg.fillRect(x, 0, boxsize, y);
947             svg.setColor(AWindow.BORDER_FOREGROUND_COLOR);
948         }
949         else if(selected)
950         {
951             //If selected and not printing eps 
952             //add a bit of GUI-look-and-feel frame
953             svg.setColor(AWindow.BORDER_SELECTED_BACKGROUND_COLOR);
954             svg.fillRect(x-2, 1, boxsize+4, y+1);
955             svg.setColor(aWindow.BORDER_SELECTED_FRAME_COLOR);
956             svg.fillRect(x-1, 0, boxsize+2, y+1);
957             svg.setColor(aWindow.BORDER_SELECTED_FRAMELIGHT_COLOR);
958             svg.fillRect(x, 1, boxsize, y-1);
959             svg.setColor(AWindow.BORDER_SELECTED_BACKGROUND_COLOR);
960             svg.fillRect(x+1, 1, boxsize-1, y-2);
961             svg.setColor(AWindow.BORDER_SELECTED_FOREGROUND_COLOR);
962         }
963         else
964         {
965             //If not selected draw background box
966             svg.setColor(AWindow.BORDER_BACKGROUND_COLOR);
967             svg.fillRect(x-2, 0, boxsize+4, y+2);
968             svg.setColor(AWindow.BORDER_FOREGROUND_COLOR);
969         }
970         //Draw text
971         svg.drawString(s, x+Offset, y-3);
972         //cleanup
973         svg.dispose();
974     }
975 
976     /**
977      * In printing mode, FishEye indicator is forced to text
978      */
979     private void printFishEyeIndicator(Graphics g, int width, int height){
980         //Force to text mode
981         paintFishEyeIndicator(g,true, width, height);
982     }
983 
984      /**
985      * Paint a small FishEye Indicator in top left corner in case FishEye projection is active
986      */
987     private void paintFishEyeIndicator(Graphics g, boolean forceText, int width, int height){
988     /** At the moment, the indicator is drawn in the top right corner of the canvas.
989      *  One might as well put it in on the scale. Eventually, if the scales shows
990      *  proper fisheyed coordinates, it might not be needed anymore at all.
991      **/
992  
993         // Make our own graphics contex, so we don't cause trouble elsewhere
994         Graphics2D svg = (Graphics2D) g.create();
995         
996         //Get FishEye parameter
997         AParameter fishEyePar = APar.get(aWindow.getProjection().getName(), "FishEye");
998         
999         if (fishEyePar != null)
1000           //Check if FishEye is on
1001           if (fishEyePar.getStatus()){
1002             //Offset if indicator to window frame
1003             int Offset=4;
1004             //Check if we have custom cursors - only then use indicator image
1005             if (ACursorFactory.getInstance().getCustomCursors() && !forceText ){
1006               //FishEye indicator image is provided by ACursorFactory as it is the same
1007               //as the cursor used in FishEye transformation.
1008               Image IndicatorImg = ACursorFactory.getInstance().getFishEyeIndicator();
1009               //Get the x position from width of window and width of image
1010               int x = width-Offset-IndicatorImg.getWidth(null);
1011               //Get y position from offset
1012               int y = Offset;
1013               //Draw an fisheye indicator in top right corner with some space
1014               svg.drawImage(IndicatorImg,x,y,null);
1015             } else {
1016               int x,y;
1017               if (svg instanceof APSGraphics2D){
1018                 //Estimate text width from font size
1019                 int textsize =(int) Math.round(aWindow.getFontMetrics(svg.getFont()).stringWidth("FishEye")*(1.25));
1020                 x = width-Offset-textsize;
1021                 //Get y position from offset
1022                 y = Offset+svg.getFont().getSize();
1023               } else {
1024                 //Get the x position from width of window and width of image
1025                 x = width-Offset-svg.getFontMetrics().stringWidth("FishEye");
1026                 //Get y position from offset
1027                 y = Offset+svg.getFontMetrics().getHeight();
1028               }
1029               //Set color to red
1030               svg.setColor(Color.red);
1031               //Use small label to indicate fisheye
1032               svg.drawString("FishEye",x,y);
1033             }
1034           }
1035         
1036         //cleanup
1037         svg.dispose();
1038     }
1039 
1040     /**
1041      * Recalculate the insets based on the current font size.
1042      */
1043     private void resetInsets()
1044     {
1045         int lb = (int) (2 + 2 + AScale.getPrimaryTickSize() + 1.5 * fontSize);
1046         // int tr = (int) (2+2+AScale.getPrimaryTickSize());
1047         int tr = SELECTED;
1048 
1049         if (drawScaleBorder)
1050             insets = new Insets(tr, lb, lb, tr);
1051         else
1052             insets = new Insets(tr, tr, tr, tr);
1053     }
1054 
1055     /**
1056      * Set the scale labels taking into account the given linear transformation.
1057      */
1058     public void setScales(String horizLabel, String vertLabel, String horizUnits, String vertUnits, AffineTransform transform, int panelWidth, int panelHeight)
1059     {
1060 
1061         // Determine the type of the tranform.
1062         int type = classifyTransform(transform);
1063 
1064         switch (type)
1065         {
1066             case TYPE_PARALLEL_TRANSFORM:
1067                 setAxisLabels(horizLabel, vertLabel);
1068                 setAxisUnits(horizUnits, vertUnits);
1069                 break;
1070 
1071             case TYPE_SWITCHED_TRANSFORM:
1072                 setAxisLabels(vertLabel, horizLabel);
1073                 setAxisUnits(vertUnits, horizUnits);
1074                 break;
1075 
1076             case TYPE_Y_SKEW_TRANSFORM:
1077                 setAxisLabels(horizLabel + PRIME, DELTA + vertLabel);
1078                 if (horizUnits.equals(vertUnits))
1079                 {
1080                     setAxisUnits(horizUnits, vertUnits);
1081                 }
1082                 else
1083                 {
1084                     setAxisUnits(horizUnits + DOT + vertUnits, vertUnits);
1085                 }
1086                 break;
1087 
1088             case TYPE_X_SKEW_TRANSFORM:
1089                 setAxisLabels(DELTA + horizLabel, vertLabel + PRIME);
1090                 if (vertUnits.equals(horizUnits))
1091                 {
1092                     setAxisUnits(horizUnits, vertUnits);
1093                 }
1094                 else
1095                 {
1096                     setAxisUnits(horizUnits, vertUnits + DOT + horizUnits);
1097                 }
1098                 break;
1099 
1100             case TYPE_SWITCHED_Y_SKEW_TRANSFORM:
1101                 setAxisLabels(vertLabel + PRIME, DELTA + horizLabel);
1102                 if (vertUnits.equals(horizUnits))
1103                 {
1104                     setAxisUnits(vertUnits, horizUnits);
1105                 }
1106                 else
1107                 {
1108                     setAxisUnits(vertUnits + DOT + horizUnits, horizUnits);
1109                 }
1110                 break;
1111 
1112             case TYPE_SWITCHED_X_SKEW_TRANSFORM:
1113                 setAxisLabels(DELTA + vertLabel, horizLabel + PRIME);
1114                 if (horizUnits.equals(vertUnits))
1115                 {
1116                     setAxisUnits(vertUnits, horizUnits);
1117                 }
1118                 else
1119                 {
1120                     setAxisUnits(vertUnits, horizUnits + DOT + vertUnits);
1121                 }
1122                 break;
1123 
1124             default:
1125                 setAxisLabels(horizLabel + PRIME, vertLabel + PRIME);
1126                 if (horizUnits.equals(vertUnits))
1127                 {
1128                     setAxisUnits(horizUnits, vertUnits);
1129                 }
1130                 else
1131                 {
1132                     setAxisUnits(horizUnits + DOT + vertUnits, vertUnits + DOT + horizUnits);
1133                 }
1134                 break;
1135         }
1136 
1137         // Get the size of the scales.
1138         axisPts[0] = 0.;
1139         axisPts[1] = panelHeight;
1140         axisPts[2] = 0.;
1141         axisPts[3] = panelHeight;
1142         axisPts[4] = panelWidth;
1143         axisPts[5] = 0.;
1144         try
1145         {
1146             // Avoid using the following call because of a bug in
1147             // AffineTransform. Instead create the inverse matrix
1148             // explicitly as done below.
1149             // transform.inverseTransform(physicsPt,0,physicsPt,0,3);
1150             AffineTransform ixform = transform.createInverse();
1151 
1152             ixform.transform(axisPts, 0, axisPts, 0, 1);
1153             ixform.deltaTransform(axisPts, 2, axisPts, 2, 2);
1154 
1155             // Calculate the values for the vertical axis and the distance.
1156             double vdy = axisPts[3];
1157             double vdx = axisPts[2];
1158             double vdist = Math.sqrt(vdx * vdx + vdy * vdy);
1159 
1160             // Calculate the values for the horizontal axis and the distance.
1161             double hdy = axisPts[5];
1162             double hdx = axisPts[4];
1163             double hdist = Math.sqrt(hdx * hdx + hdy * hdy);
1164 
1165             // Initialize the endpoints of the axes.
1166             double vmin = 0.;
1167             double vmax = 0.;
1168             double hmin = 0.;
1169             double hmax = 0.;
1170 
1171             // Do what is necessary for the different types of transformations.
1172             switch (type)
1173             {
1174                 case (TYPE_PARALLEL_TRANSFORM):
1175                 {
1176                     double vsign = (vdy < 0.) ? 1. : -1.;
1177 
1178                     vmin = axisPts[1];
1179                     vmax = axisPts[1] + vsign * vdist;
1180 
1181                     double hsign = (hdx > 0.) ? 1. : -1.;
1182 
1183                     hmin = axisPts[0];
1184                     hmax = axisPts[0] + hsign * hdist;
1185                     break;
1186                 }
1187 
1188                 case (TYPE_SWITCHED_TRANSFORM):
1189                 {
1190                     double hsign = (hdy > 0.) ? 1. : -1.;
1191 
1192                     hmin = axisPts[1];
1193                     hmax = axisPts[1] + hsign * hdist;
1194 
1195                     double vsign = (vdx < 0.) ? 1. : -1.;
1196 
1197                     vmin = axisPts[0];
1198                     vmax = axisPts[0] + vsign * vdist;
1199                     break;
1200                 }
1201 
1202                 case (TYPE_Y_SKEW_TRANSFORM):
1203                 {
1204                     double vsign = (vdy > 0.) ? 1. : -1.;
1205 
1206                     vmax = -vsign * vdist / 2.;
1207                     vmin = -vmax;
1208 
1209                     hmin = 0.;
1210                     hmax = hdist;
1211                     break;
1212                 }
1213 
1214                 case (TYPE_X_SKEW_TRANSFORM):
1215                 {
1216                     double hsign = (hdx > 0.) ? 1. : -1.;
1217 
1218                     hmax = hsign * hdist / 2.;
1219                     hmin = -hmax;
1220 
1221                     vmin = 0.;
1222                     vmax = vdist;
1223                     break;
1224                 }
1225 
1226                 case (TYPE_SWITCHED_Y_SKEW_TRANSFORM):
1227                 {
1228                     double vsign = (vdx > 0.) ? 1. : -1.;
1229 
1230                     vmax = -vsign * vdist / 2.;
1231                     vmin = -vmax;
1232 
1233                     hmin = 0.;
1234                     hmax = hdist;
1235                     break;
1236                 }
1237 
1238                 case (TYPE_SWITCHED_X_SKEW_TRANSFORM):
1239                 {
1240                     double hsign = (hdy > 0.) ? 1. : -1.;
1241 
1242                     hmax = hsign * hdist / 2.;
1243                     hmin = -hmax;
1244 
1245                     vmin = 0.;
1246                     vmax = vdist;
1247                     break;
1248                 }
1249 
1250                 default:
1251                 {
1252                     vmin = 0.;
1253                     vmax = vdist;
1254                     hmin = 0.;
1255                     hmax = hdist;
1256                     break;
1257                 }
1258             }
1259 
1260             // Actually set the limits.
1261             setLimits(hmin, hmax, vmin, vmax);
1262         }
1263         catch (NoninvertibleTransformException e)
1264         {
1265             setLimits(0., 0., 0., 0.);
1266         }
1267     }
1268 
1269     /**
1270      * This is a protected utility method which classifies the given transform
1271      * into seven categories: parallel, switched, x-skew, y-skew, switched
1272      * x-skew, switched y-skew, and general. The parallel category describes
1273      * transformations in which the transformed x and y axes are parallel or
1274      * antiparallel to the original x and y axes, respectively. The switched
1275      * category describes transformations in which the transformed x and y axes
1276      * are parallel or antiparallel to the original y and x axes, respectively.
1277      * That is, the x and y axes have been switched. The x-skew describes
1278      * transformations in which the transformed x-axis is parallel (or
1279      * antiparallel) to the original one while the transformed y-axis forms some
1280      * non-zero angle to the original one. The y-skew is similar; the switch
1281      * skews are just rotated (counter)clockwise by 90 degrees. The general
1282      * category encompasses all transforms not falling into one of the other
1283      * categories.
1284      */
1285     static protected int classifyTransform(AffineTransform xform)
1286     {
1287         // Set the default return type to a general matrix.
1288         int category = TYPE_GENERAL_TRANSFORM;
1289 
1290         // Get the four non-translation quantities from the transformation.
1291         double sx = xform.getScaleX();
1292         double sy = xform.getScaleY();
1293         double kx = xform.getShearX();
1294         double ky = xform.getShearY();
1295 
1296         // Check the type.
1297         if (kx == 0. && ky == 0.)
1298         {
1299             category = TYPE_PARALLEL_TRANSFORM;
1300         }
1301         else if (sx == 0. && sy == 0.)
1302         {
1303             category = TYPE_SWITCHED_TRANSFORM;
1304         }
1305         else if (kx == 0.)
1306         {
1307             category = TYPE_Y_SKEW_TRANSFORM;
1308         }
1309         else if (ky == 0.)
1310         {
1311             category = TYPE_X_SKEW_TRANSFORM;
1312         }
1313         else if (sx == 0.)
1314         {
1315             category = TYPE_SWITCHED_Y_SKEW_TRANSFORM;
1316         }
1317         else if (sy == 0.)
1318         {
1319             category = TYPE_SWITCHED_X_SKEW_TRANSFORM;
1320         }
1321 
1322         // Return the transformtion type.
1323         return category;
1324     }
1325 
1326     /**
1327      * A utility which makes an AffineTransform given three corner
1328      * points. The first point must be the upper, left-hand corner
1329      * point, the second, the upper, right-hand corner point, and the
1330      * third, the lower, right-hand corner point.
1331      *
1332      * @return AffineTransform which does the appropriate mapping */
1333     protected AffineTransform makeTransform(Point2D.Double[] corners)
1334     {
1335         double x0 = corners[0].x;
1336         double y0 = corners[0].y;
1337         double x1 = corners[1].x;
1338         double y1 = corners[1].y;
1339         double x2 = corners[2].x;
1340         double y2 = corners[2].y;
1341 
1342         double sx = 0.;
1343         double kx = 0.;
1344         double tx = 0.;
1345         double sy = 0.;
1346         double ky = 0.;
1347         double ty = 0.;
1348 
1349         double delta = (x2 * (y1 - y0) - x1 * (y2 - y0) + x0 * (y2 - y1));
1350 
1351         if (delta == 0)
1352         {
1353             // cannot successfully create an AffineTransform
1354             System.err.println("Fatal Error: AffineTransform creating failed.");
1355             System.err.println("Possible cause: wrong user corner values are set.");
1356             System.exit(1);
1357             return null;
1358         }
1359         else
1360         {
1361             delta = 1. / delta;
1362 
1363             double w = aWindow.getWidth();
1364             double h = aWindow.getHeight();
1365 
1366             sx = -(delta * w) * (y2 - y1);
1367             kx = (delta * w) * (x2 - x1);
1368             tx = -(x0 * sx + y0 * kx);
1369 
1370             ky = (delta * h) * (y1 - y0);
1371             sy = -(delta * h) * (x1 - x0);
1372             ty = -(x0 * ky + y0 * sy);
1373 
1374             return new AffineTransform(sx, ky, kx, sy, tx, ty);
1375         }
1376 
1377     }
1378 
1379     public void drawString(Graphics2D g, String str, double x, double y, int horizontal, int vertical, int maxSize)
1380     {
1381         drawString(g, str, x, y, horizontal, vertical, false, null, 0, false, null, maxSize);
1382     }
1383 
1384     private void drawString(Graphics2D g, String str, double x, double y, int horizontal, int vertical, boolean framed, Color frameColor, double frameWidth, boolean banner, Color bannerColor, int maxSize)
1385     {
1386         Font sf = g.getFont();
1387         int width = sf.getSize();
1388         int descent = 0;
1389         int height = sf.getSize();
1390         int adjustment = 0;
1391 
1392         // The metrics stuff did not work, so I made a work around and now
1393         // even ps-printing works (CT 27/7/2004)
1394         double xx = Math.min(x, maxSize - width / 2);
1395         Rectangle textSize = new Rectangle(0, descent - height, width, height);
1396         Point2D textUL = drawFrameAndBanner(xx, y, textSize, adjustment, framed, frameColor, frameWidth, banner, bannerColor, horizontal, vertical);
1397 
1398         if (g instanceof AAbstractGraphics2D) {
1399             // No antialiasing support needed for EPS output.
1400             g.drawString(str, (int) textUL.getX(), (int) textUL.getY());
1401         } else {
1402             // For pixel graphics, switch on antialiasing for text.
1403             g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
1404             g.drawString(str, (int) textUL.getX(), (int) textUL.getY());
1405             g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
1406         }
1407     }
1408 
1409     /** Draws frame and banner around a string. The method calculates and returns
1410      *  the point to which the text curser should be set before drawing the string. */
1411     private Point2D drawFrameAndBanner(double x, double y, Rectangle textSize, int adjustment, boolean framed, Color frameColor, double frameWidth, boolean banner, Color bannerColor, int horizontal, int vertical)
1412     {
1413         double descent = textSize.y + textSize.height;
1414         x = getXalignment(x, textSize.width, horizontal);
1415         y = getYalignment(y, textSize.height, (int) descent, vertical);
1416         return new Point2D.Double(x, y);
1417     }
1418 
1419     private static double getYalignment(double y, int ascent, int descent, int alignment)
1420     {
1421         // vertical alignment
1422         switch (alignment)
1423         {
1424             case TEXT_TOP:
1425                 y = y + ascent - descent;
1426                 break;
1427 
1428             case TEXT_CENTER:
1429                 y = y + ((ascent + descent) / 2) - descent;
1430                 break;
1431 
1432             case TEXT_BOTTOM:
1433                 y = y - descent;
1434                 break;
1435 
1436             case TEXT_BASELINE:
1437             default:
1438                 break;
1439         }
1440         return y;
1441     }
1442 
1443     private static double getXalignment(double x, int width, int alignment)
1444     {
1445         // horizontal alignment
1446         switch (alignment)
1447         {
1448             case TEXT_CENTER:
1449                 x = x - (width / 2);
1450                 break;
1451 
1452             case TEXT_RIGHT:
1453                 x = x - width;
1454                 break;
1455 
1456             case TEXT_LEFT:
1457             default:
1458                 break;
1459         }
1460         return x;
1461     }
1462 
1463     private String trim(double v, double ratio)
1464     {
1465         double r = 2.;
1466         double f = 1.;
1467         while (r > ratio)
1468         {
1469             r /= 10.;
1470             f = f * 10.;
1471         }
1472         if (f == 1.)
1473             return "" + Math.round(v);
1474         else
1475             return "" + Math.round(v * f) / f;
1476     }
1477 
1478 }

source navigation ] diff markup ] identifier search ] general search ]

Due to the LXR bug, the updates fail sometimes to remove references to deleted files. The Saturday's full rebuilds fix these problems
This page was automatically generated by the LXR engine. Valid HTML 4.01!