From 925845cff949ea926013d297e95fb6be0977513b Mon Sep 17 00:00:00 2001 From: Max Schenkelberg Date: Tue, 29 May 2012 15:00:42 -0500 Subject: [PATCH] Issue #665 Made MPEGageResource use bulk rendering for strings and points for faster shared display rendering Change-Id: I7a734784895d406ba769f558d4b321dfe3b8dbf9 Former-commit-id: fe9de50746ebe9e46e39affc687db28b8cbdc283 [formerly 34a71dbee8957ada0450dbb2ae51466b40777a90] [formerly fe9de50746ebe9e46e39affc687db28b8cbdc283 [formerly 34a71dbee8957ada0450dbb2ae51466b40777a90] [formerly c28a586d842822c6283a69bc60e672ab5821842f [formerly 18ca6f058d810781d93ea2d0bad9b2daa161fa3a]]] Former-commit-id: c28a586d842822c6283a69bc60e672ab5821842f Former-commit-id: ddfb7e038aeb817ad5fb7fe4471827bfb35b1bf3 [formerly 2cde39bc6354f8d53d4513a1ef060d550ff6b0e7] Former-commit-id: e3ad0855017f7b69a5b91db1054f62935370cb67 --- .../viz/core/gl/internal/GLTarget.java | 19 +- ...PEFontManager.java => MPEFontFactory.java} | 59 ++-- .../viz/mpe/ui/rsc/MPEGageResource.java | 310 ++++++++---------- .../viz/mpe/ui/rsc/MPELegendResource.java | 9 +- .../mpe/ui/rsc/PointFreezePlotResource.java | 13 +- .../mpe/ui/rsc/PointPrecipPlotResource.java | 11 +- .../viz/mpe/ui/rsc/PointTempPlotResource.java | 9 +- 7 files changed, 202 insertions(+), 228 deletions(-) rename cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/{MPEFontManager.java => MPEFontFactory.java} (62%) diff --git a/cave/com.raytheon.viz.core.gl/src/com/raytheon/viz/core/gl/internal/GLTarget.java b/cave/com.raytheon.viz.core.gl/src/com/raytheon/viz/core/gl/internal/GLTarget.java index b94e176ee2..7e0de4b005 100644 --- a/cave/com.raytheon.viz.core.gl/src/com/raytheon/viz/core/gl/internal/GLTarget.java +++ b/cave/com.raytheon.viz.core.gl/src/com/raytheon/viz/core/gl/internal/GLTarget.java @@ -2467,6 +2467,7 @@ public class GLTarget implements IGLTarget { // function ends up calling begin/end rendering lots which slows it down // to the speed of a not bulk operation TextRenderer textRenderer = null; + boolean lastXOr = false; pushGLState(); gl.glMatrixMode(GL.GL_MODELVIEW); @@ -2642,9 +2643,15 @@ public class GLTarget implements IGLTarget { } float alpha = Math.min(dString.basics.alpha, 1.0f); - if (dString.basics.xOrColors) { - gl.glEnable(GL.GL_COLOR_LOGIC_OP); - gl.glLogicOp(GL.GL_XOR); + if (lastXOr != dString.basics.xOrColors) { + lastXOr = dString.basics.xOrColors; + textRenderer.flush(); + if (lastXOr) { + gl.glEnable(GL.GL_COLOR_LOGIC_OP); + gl.glLogicOp(GL.GL_XOR); + } else { + gl.glDisable(GL.GL_COLOR_LOGIC_OP); + } } for (int c = 0; c < dString.getText().length; c++) { @@ -2717,9 +2724,6 @@ public class GLTarget implements IGLTarget { yPos -= textBounds.getHeight() * getScaleY(); } } - if (dString.basics.xOrColors) { - gl.glDisable(GL.GL_COLOR_LOGIC_OP); - } if (rotatedPoint != null) { textRenderer.flush(); @@ -2732,6 +2736,9 @@ public class GLTarget implements IGLTarget { if (textRenderer != null) { textRenderer.end3DRendering(); } + if (lastXOr) { + gl.glDisable(GL.GL_COLOR_LOGIC_OP); + } gl.glDisable(GL.GL_TEXTURE_2D); gl.glDisable(GL.GL_BLEND); diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/MPEFontManager.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/MPEFontFactory.java similarity index 62% rename from cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/MPEFontManager.java rename to cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/MPEFontFactory.java index 54ec1ab4aa..c27f8e26e6 100644 --- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/MPEFontManager.java +++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/MPEFontFactory.java @@ -28,7 +28,7 @@ import com.raytheon.viz.mpe.ui.rsc.MPEGageResource; import com.raytheon.viz.mpe.ui.rsc.MPELegendResource; /** - * MPE Font manager, uses preferences to retrieve fonts. Fonts are shared + * MPE Font factory, uses preference ids to create fonts for a target * *
  * 
@@ -44,7 +44,7 @@ import com.raytheon.viz.mpe.ui.rsc.MPELegendResource;
  * @version 1.0
  */
 
-public class MPEFontManager {
+public class MPEFontFactory {
 
     private static final String DEFAULT_ID = "com.raytheon.viz.mpe.ui.defaultFont";
 
@@ -54,36 +54,45 @@ public class MPEFontManager {
         idMap.put(MPEGageResource.class, MPEGageResource.class.getName());
     }
 
-    private static Map fontMap = new HashMap();
+    private Map fontMap;
+
+    private IGraphicsTarget target;
+
+    private String baseId = DEFAULT_ID;
+
+    public MPEFontFactory(IGraphicsTarget target, Object referenceObject) {
+        this.target = target;
+        this.fontMap = new HashMap();
+        if (referenceObject != null) {
+            String id = idMap.get(referenceObject.getClass());
+            if (id != null) {
+                this.baseId = id;
+            }
+        }
+    }
+
+    public void dispose() {
+        for (IFont font : fontMap.values()) {
+            font.dispose();
+        }
+        fontMap.clear();
+    }
 
     /**
-     * Get the font using preference store values. If no preference value is
-     * defined for the object, the default mpe font will be used. WARNING: These
-     * fonts are shared, changes to them will result in changes to others using
-     * them
+     * Get the IFont with the font name, fonts are cached and should not be
+     * disposed of directly but through {@link #dispose()}
      * 
-     * @param obj
-     * @param name
-     * @param target
+     * @param fontName
      * @return
      */
-    public static IFont getFont(Object obj, String name, IGraphicsTarget target) {
-        String id = null;
-        if (obj == null) {
-            id = DEFAULT_ID + "." + name;
-        } else {
-            String clazzId = idMap.get(obj.getClass());
-            if (clazzId == null) {
-                clazzId = DEFAULT_ID;
-            }
-            id = clazzId + "." + name;
-        }
-
-        IFont font = fontMap.get(id);
+    public IFont getMPEFont(String fontName) {
+        IFont font = fontMap.get(fontName);
         if (font == null) {
-            font = target.initializeFont(id);
-            fontMap.put(id, font);
+            String fontId = baseId + "." + fontName;
+            font = target.initializeFont(fontId);
+            fontMap.put(fontName, font);
         }
         return font;
     }
+
 }
diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/MPEGageResource.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/MPEGageResource.java
index ff0c179eca..f13a4175c3 100644
--- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/MPEGageResource.java
+++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/MPEGageResource.java
@@ -41,6 +41,7 @@ import javax.measure.unit.SI;
 import org.eclipse.swt.events.DisposeEvent;
 import org.eclipse.swt.events.DisposeListener;
 import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.Rectangle;
 import org.eclipse.ui.PlatformUI;
 import org.eclipse.ui.commands.ICommandService;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
@@ -55,7 +56,10 @@ import com.raytheon.uf.common.status.UFStatus;
 import com.raytheon.uf.common.status.UFStatus.Priority;
 import com.raytheon.uf.viz.core.DrawableCircle;
 import com.raytheon.uf.viz.core.DrawableString;
+import com.raytheon.uf.viz.core.IExtent;
 import com.raytheon.uf.viz.core.IGraphicsTarget;
+import com.raytheon.uf.viz.core.IGraphicsTarget.HorizontalAlignment;
+import com.raytheon.uf.viz.core.IGraphicsTarget.VerticalAlignment;
 import com.raytheon.uf.viz.core.RGBColors;
 import com.raytheon.uf.viz.core.drawables.ColorMapParameters;
 import com.raytheon.uf.viz.core.drawables.IFont;
@@ -70,9 +74,9 @@ import com.raytheon.viz.core.rsc.jts.JTSCompiler;
 import com.raytheon.viz.mpe.core.MPEDataManager;
 import com.raytheon.viz.mpe.core.MPEDataManager.MPEGageData;
 import com.raytheon.viz.mpe.ui.MPEDisplayManager;
+import com.raytheon.viz.mpe.ui.MPEDisplayManager.GageColor;
 import com.raytheon.viz.mpe.ui.MPEDisplayManager.GageDisplay;
-import com.raytheon.viz.mpe.ui.MPEDisplayManager.GageMissingOptions;
-import com.raytheon.viz.mpe.ui.MPEFontManager;
+import com.raytheon.viz.mpe.ui.MPEFontFactory;
 import com.raytheon.viz.mpe.ui.dialogs.Display7x7Dialog;
 import com.raytheon.viz.ui.input.EditableManager;
 import com.vividsolutions.jts.geom.Coordinate;
@@ -103,9 +107,7 @@ public class MPEGageResource extends AbstractMPEInputResource {
 
     private static final String GAGE_TRIANGLES = "GAGETRIANGLES%sz";
 
-    private static final int IMAGE_WIDTH = 10;
-
-    private static final int IMAGE_HEIGHT = 10;
+    private static final double POINT_RADIUS = 2;
 
     private final SimpleDateFormat sdf;
 
@@ -119,12 +121,6 @@ public class MPEGageResource extends AbstractMPEInputResource {
 
     private final RGB triangleColor = RGBColors.getRGBColor("YELLOW");
 
-    private double scaleWidthValue = 0.0;
-
-    private double scaleHeightValue = 0.0;
-
-    private MPEGageData gageData = null;
-
     private DataMappingPreferences dmPref;
 
     private ColorMap colorMap;
@@ -133,12 +129,10 @@ public class MPEGageResource extends AbstractMPEInputResource {
 
     private Date lastDate = null;
 
-    private DrawableCircle point;
-
-    private DrawableString string;
-
     private IWireframeShape gageTriangles;
 
+    private MPEFontFactory fontFactory;
+
     /**
      * @param resourceData
      * @param loadProperties
@@ -153,11 +147,9 @@ public class MPEGageResource extends AbstractMPEInputResource {
     @Override
     protected void initInternal(IGraphicsTarget target) throws VizException {
         super.initInternal(target);
-        point = new DrawableCircle();
-        point.filled = true;
-        string = new DrawableString("", null);
         displayMgr = MPEDisplayManager.getInstance(descriptor
                 .getRenderableDisplay());
+        fontFactory = new MPEFontFactory(target, this);
         loadColors();
         lastDate = displayMgr.getCurrentDate();
         addPoints(MPEDataManager.getInstance().readGageData(lastDate));
@@ -168,6 +160,7 @@ public class MPEGageResource extends AbstractMPEInputResource {
         if (gageTriangles != null) {
             gageTriangles.dispose();
         }
+        fontFactory.dispose();
     }
 
     /**
@@ -196,14 +189,12 @@ public class MPEGageResource extends AbstractMPEInputResource {
         if (gageTriangles != null) {
             gageTriangles = null;
         }
+        lastDate = null;
     }
 
     @Override
     protected void paintInternal(IGraphicsTarget target,
             PaintProperties paintProps) throws VizException {
-        setScaleWidth(paintProps);
-        setScaleHeight(paintProps);
-
         // set the plot draw or no draw values
         Set gd = displayMgr.getGageDisplay();
         if (gd.isEmpty()) {
@@ -219,30 +210,9 @@ public class MPEGageResource extends AbstractMPEInputResource {
             }
         }
 
-        // Fonts are shared and cached, no need to init or dispose
-        IFont font = MPEFontManager.getFont(this, displayMgr.getFontState(),
-                target);
-        font.setSmoothing(false);
-        string.font = font;
-
         if (gd.contains(GageDisplay.Ids) || gd.contains(GageDisplay.Values)) {
-            Iterator iter = dataMap.keySet().iterator();
-            while (iter.hasNext()) {
-                try {
-                    Coordinate c = iter.next();
-                    double[] pixel = descriptor.worldToPixel(new double[] {
-                            c.x, c.y });
-                    if (paintProps.getView().getExtent().contains(pixel)) {
-                        paintPlotInfo(target, paintProps, c, dataMap.get(c),
-                                gd.contains(GageDisplay.Ids),
-                                gd.contains(GageDisplay.Values));
-                    }
-                } catch (Exception e) {
-                    statusHandler.handle(Priority.PROBLEM,
-                            "Error painting gages: " + e.getLocalizedMessage(),
-                            e);
-                }
-            }
+            paintPlotInfo(target, paintProps, gd.contains(GageDisplay.Ids),
+                    gd.contains(GageDisplay.Values));
         }
 
         try {
@@ -311,132 +281,129 @@ public class MPEGageResource extends AbstractMPEInputResource {
     /**
      * Draws the plot information
      * 
-     * @param c
-     * @param gageData
-     * @throws VizException
+     * @param target
+     * @param paintProps
+     * @param isGageIdsDisplayed
+     * @param isGageValuesDisplayed
      */
     private void paintPlotInfo(IGraphicsTarget target,
-            PaintProperties paintProps, Coordinate c, MPEGageData gageData,
-            boolean isGageIdsDisplayed, boolean isGageValuesDisplayed)
-            throws VizException {
-        RGB gageColor = new RGB(255, 255, 255);
-        double[] centerpixels = descriptor
-                .worldToPixel(new double[] { c.x, c.y });
+            PaintProperties paintProps, boolean isGageIdsDisplayed,
+            boolean isGageValuesDisplayed) throws VizException {
+        Rectangle bounds = paintProps.getCanvasBounds();
+        IExtent extent = paintProps.getView().getExtent();
+        double screenToWorldWidthRatio = bounds.width / extent.getWidth();
+
+        List strings = new ArrayList(
+                dataMap.size());
+        List points = new ArrayList(
+                dataMap.size());
+
+        // Fonts are shared and cached, no need to init or dispose
+        IFont font = fontFactory.getMPEFont(displayMgr.getFontState());
+        font.setSmoothing(false);
 
         MPEDisplayManager.GageMissingOptions gm = displayMgr.getGageMissing();
+        boolean xor = displayMgr.getGageColor() == GageColor.Contrast;
 
-        boolean isReportedMissing = gageData.isReported_missing();
-        boolean isMissing = ((gageData.getGval() == -999.f || gageData
-                .getGval() == -9999.f) ? true : false);
-        if (gageData.isManedit() == true
-                && gageData.getEdit().equalsIgnoreCase("m")) {
-            isMissing = true;
+        for (Coordinate point : dataMap.keySet()) {
+            if (extent.contains(new double[] { point.x, point.y })) {
+                MPEGageData gageData = dataMap.get(point);
+                RGB gageColor = getGageColor(gageData);
+
+                boolean isReportedMissing = gageData.isReported_missing();
+                boolean isMissing = ((gageData.getGval() == -999.f || gageData
+                        .getGval() == -9999.f) ? true : false);
+                if (gageData.isManedit() == true
+                        && gageData.getEdit().equalsIgnoreCase("m")) {
+                    isMissing = true;
+                }
+
+                switch (gm) {
+                case MissingNone:
+                    if (isMissing) {
+                        break;
+                    }
+
+                case MissingReported:
+                    if ((isMissing) && (!isReportedMissing)) {
+                        break;
+                    }
+
+                case MissingAll:
+                    String gageValue = "";
+                    String gageId = "";
+                    if (isGageValuesDisplayed) {
+                        gageValue = "m";
+                        if (!isMissing) {
+                            gageValue = String.format("%5.2f",
+                                    gageData.getGval());
+                        }
+
+                        // draw the value
+                        if (!gageData.isManedit()) {
+                            if (gageData.getId().contains("PSEUDO")) {
+                                UnitConverter conv = SI.MILLIMETER
+                                        .getConverterTo(NonSI.INCH);
+                                gageValue = String.format("%5.2f",
+                                        conv.convert(gageData.getGval()));
+                            }
+                        } else {
+                            if (gageData.getId().contains("PSEUDO")
+                                    && !isMissing) {
+                                UnitConverter conv = SI.MILLIMETER
+                                        .getConverterTo(NonSI.INCH);
+                                gageValue = String.format("%5.2f",
+                                        conv.convert(gageData.getGval()));
+                            }
+                        }
+                    }
+                    if (isGageIdsDisplayed) {
+                        gageId = gageData.getId();
+
+                        DrawableCircle circle = new DrawableCircle();
+                        circle.radius = POINT_RADIUS / screenToWorldWidthRatio;
+                        circle.filled = true;
+                        circle.numberOfPoints = 8;
+                        circle.setCoordinates(point.x, point.y);
+                        circle.basics.color = gageColor;
+                        circle.basics.xOrColors = xor;
+                        points.add(circle);
+                    }
+
+                    if (isGageIdsDisplayed || isGageValuesDisplayed) {
+                        DrawableString string = new DrawableString(
+                                new String[] { gageValue, gageId, }, gageColor);
+                        string.font = font;
+                        string.basics.xOrColors = xor;
+                        string.horizontalAlignment = HorizontalAlignment.LEFT;
+                        string.verticallAlignment = VerticalAlignment.BOTTOM;
+
+                        string.setCoordinates(
+                                point.x
+                                        + (POINT_RADIUS / screenToWorldWidthRatio),
+                                point.y
+                                        + (POINT_RADIUS / screenToWorldWidthRatio));
+                        strings.add(string);
+                    }
+                }
+            }
         }
 
-        String val = null;
-
-        switch (gm) {
-        case MissingNone:
-            if (isMissing) {
-                break;
-            }
-
-        case MissingReported:
-            if ((isMissing) && (!isReportedMissing)) {
-                break;
-            }
-
-        case MissingAll:
-
-            if (gm.equals(GageMissingOptions.MissingNone)) {
-                // System.out.println(gageData.getGval()); // TODO : REMOVE
-                gageColor = setGageColor(gageData);
-            } else {
-                gageColor = RGBColors.getRGBColor("SandyBrown");
-            }
-
-            if (isGageValuesDisplayed) {
-                Coordinate stageCoor = new Coordinate(centerpixels[0]
-                        + scaleWidthValue / 3, centerpixels[1]
-                        + scaleHeightValue);
-                if (!isMissing) {
-                    val = String.format("%5.2f", gageData.getGval());
-                } else {
-                    val = "m";
-                }
-
-                string.setCoordinates(stageCoor.x, stageCoor.y);
-
-                // draw the value
-                if (!gageData.isManedit()) {
-                    if (gageData.getId().contains("PSEUDO")) {
-                        UnitConverter conv = SI.MILLIMETER
-                                .getConverterTo(NonSI.INCH);
-                        val = String.format("%5.2f",
-                                conv.convert(gageData.getGval()));
-                    }
-                    string.setText(val, gageColor);
-                    target.drawStrings(string);
-                } else {
-                    if (gageData.getId().contains("PSEUDO") && !isMissing) {
-                        UnitConverter conv = SI.MILLIMETER
-                                .getConverterTo(NonSI.INCH);
-                        val = String.format("%5.2f",
-                                conv.convert(gageData.getGval()));
-                    }
-                    string.setText(val + "e", gageColor);
-                    target.drawStrings(string);
-                }
-            }
-
-            // draw the ID
-            if (isGageIdsDisplayed) {
-                Coordinate idCoor = new Coordinate(centerpixels[0]
-                        + scaleWidthValue / 3, centerpixels[1]
-                        - scaleHeightValue);
-
-                // System.out.println(gageData.getId()); // TODO : remove
-
-                string.setText(gageData.getId(), gageColor);
-                string.setCoordinates(idCoor.x, idCoor.y);
-
-                target.drawStrings(string);
-                double[] coords = descriptor.worldToPixel(new double[] { c.x,
-                        c.y });
-                point.setCoordinates(coords[0], coords[1]);
-                point.radius = scaleWidthValue / 3;
-                if (point.basics.color == null) {
-                    setGageColor(gageData);
-                }
-                target.drawCircle(point);
-            }
-        }
+        target.drawCircle(points.toArray(new DrawableCircle[points.size()]));
+        target.drawStrings(strings);
     }
 
-    private RGB setGageColor(MPEGageData gageData) throws VizException {
+    private RGB getGageColor(MPEGageData gageData) {
         RGB gageColor = new RGB(255, 255, 255);
         if (!displayMgr.getGageDisplay().isEmpty()) {
             MPEDisplayManager.GageColor gc = displayMgr.getGageColor();
-            string.basics.xOrColors = false;
-            point.basics.xOrColors = false;
             switch (gc) {
-
             case Solid:
                 gageColor = RGBColors.getRGBColor("SandyBrown");
                 break;
 
             case Contrast:
-
-                // RGB xoc = RGBColors.getRGBColor("SandyBrown");
-                // gageColor = getXOR(bg, xoc);
                 gageColor = RGBColors.getRGBColor("SandyBrown");
-                string.basics.xOrColors = true;
-                point.basics.xOrColors = true;
-                // if (bg.equals(xmcolor)) {
-                // gageColor = getContrast(bg);
-                // } else {
-                // gageColor = getContrast(xmcolor);
-                // }
                 break;
 
             case ByQC:
@@ -468,7 +435,6 @@ public class MPEGageResource extends AbstractMPEInputResource {
             }
         }
 
-        point.basics.color = gageColor;
         return gageColor;
     }
 
@@ -478,20 +444,22 @@ public class MPEGageResource extends AbstractMPEInputResource {
      * @param gages
      */
     private void addPoints(List gages) {
-        gageData = new MPEDataManager.MPEGageData();
         dataMap = new Hashtable();
         strTree = new STRtree();
 
         if (!gages.isEmpty()) {
             for (ListIterator it = gages.listIterator(); it
                     .hasNext();) {
-                gageData = it.next();
+                MPEGageData gageData = it.next();
                 Coordinate xy = gageData.getLatLon();
+                double[] pixel = descriptor.worldToPixel(new double[] { xy.x,
+                        xy.y });
+                xy = new Coordinate(pixel[0], pixel[1]);
                 dataMap.put(xy, gageData);
 
                 /* Create a small envelope around the point */
-                Coordinate p1 = new Coordinate(xy.x + .05, xy.y + .05);
-                Coordinate p2 = new Coordinate(xy.x - .05, xy.y - .05);
+                Coordinate p1 = new Coordinate(xy.x + 10, xy.y + 10);
+                Coordinate p2 = new Coordinate(xy.x - 10, xy.y - 10);
                 Envelope env = new Envelope(p1, p2);
                 ArrayList data = new ArrayList();
                 data.add(xy);
@@ -555,28 +523,6 @@ public class MPEGageResource extends AbstractMPEInputResource {
         }
     }
 
-    /**
-     * Set the width scalar
-     * 
-     * @param props
-     */
-    private void setScaleWidth(PaintProperties props) {
-        double screenToWorldWidthRatio = props.getCanvasBounds().width
-                / props.getView().getExtent().getWidth();
-        scaleWidthValue = (IMAGE_WIDTH / 2.0) / screenToWorldWidthRatio;
-    }
-
-    /**
-     * Set the height scalar
-     * 
-     * @param props
-     */
-    private void setScaleHeight(PaintProperties props) {
-        double screenToWorldHeightRatio = props.getCanvasBounds().height
-                / props.getView().getExtent().getHeight();
-        scaleHeightValue = (IMAGE_HEIGHT / 2.0) / screenToWorldHeightRatio;
-    }
-
     /**
      * Inspect method called when moused over while inspect is enabled
      * 
@@ -620,10 +566,10 @@ public class MPEGageResource extends AbstractMPEInputResource {
             double testdist;
             MPEGageData bestData = null;
             // Find closest gage...
-            for (Coordinate ll : dataMap.keySet()) {
-                MPEGageData data = dataMap.get(ll);
-                float lon = (float) ll.x;
-                float lat = (float) ll.y;
+            for (MPEGageData data : dataMap.values()) {
+                Coordinate latLon = data.getLatLon();
+                float lon = (float) latLon.x;
+                float lat = (float) latLon.y;
                 testdist = Math.pow((coord.x - lon), 2)
                         + Math.pow((coord.y - lat), 2);
                 testdist = Math.pow(testdist, .5);
diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/MPELegendResource.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/MPELegendResource.java
index 85504bdb0a..7715b3fd7c 100644
--- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/MPELegendResource.java
+++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/MPELegendResource.java
@@ -56,7 +56,7 @@ import com.raytheon.uf.viz.core.sampling.ISamplingResource;
 import com.raytheon.viz.mpe.core.MPEDataManager;
 import com.raytheon.viz.mpe.ui.DisplayFieldData;
 import com.raytheon.viz.mpe.ui.MPEDisplayManager;
-import com.raytheon.viz.mpe.ui.MPEFontManager;
+import com.raytheon.viz.mpe.ui.MPEFontFactory;
 import com.raytheon.viz.mpe.ui.actions.DrawDQCStations;
 import com.raytheon.viz.ui.cmenu.AbstractRightClickAction;
 import com.raytheon.viz.ui.cmenu.IContextMenuContributor;
@@ -145,6 +145,8 @@ public class MPELegendResource extends
 
     private boolean displayInfo = false;
 
+    private MPEFontFactory fontFactory;
+
     private IFont font;
 
     public MPELegendResource(GenericResourceData rscData,
@@ -159,11 +161,11 @@ public class MPELegendResource extends
      */
     @Override
     protected void disposeInternal() {
-        // DO NOT DISPOSE OF FONT AS IT IS SHARED IN ALL OF MPE
         IDisplayPaneContainer container = getResourceContainer();
         if (container != null) {
             container.unregisterMouseHandler(inspectHandler);
         }
+        fontFactory.dispose();
     }
 
     /*
@@ -177,6 +179,7 @@ public class MPELegendResource extends
     protected void initInternal(IGraphicsTarget target) throws VizException {
         displayMgr = MPEDisplayManager.getInstance(descriptor
                 .getRenderableDisplay());
+        fontFactory = new MPEFontFactory(target, this);
         IDisplayPaneContainer container = getResourceContainer();
         if (container != null) {
             container.registerMouseHandler(inspectHandler);
@@ -194,7 +197,7 @@ public class MPELegendResource extends
     protected void paintInternal(IGraphicsTarget target,
             PaintProperties paintProps) throws VizException {
         // Fonts are shared and cached, no need to init or dispose
-        font = MPEFontManager.getFont(this, displayMgr.getFontState(), target);
+        font = fontFactory.getMPEFont(displayMgr.getFontState());
         IExtent screenExtent = paintProps.getView().getExtent();
 
         scale = (screenExtent.getHeight() / paintProps.getCanvasBounds().height);
diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/PointFreezePlotResource.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/PointFreezePlotResource.java
index 605b7b755e..3824c13e78 100644
--- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/PointFreezePlotResource.java
+++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/PointFreezePlotResource.java
@@ -41,9 +41,9 @@ import org.eclipse.ui.PlatformUI;
 import org.opengis.referencing.FactoryException;
 import org.opengis.referencing.operation.TransformException;
 
-import com.raytheon.uf.common.dataplugin.shef.tables.Colorvalue;
 import com.raytheon.uf.common.colormap.Color;
 import com.raytheon.uf.common.colormap.ColorMap;
+import com.raytheon.uf.common.dataplugin.shef.tables.Colorvalue;
 import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
 import com.raytheon.uf.viz.core.DrawableString;
 import com.raytheon.uf.viz.core.IExtent;
@@ -66,7 +66,7 @@ import com.raytheon.uf.viz.core.style.DataMappingPreferences.DataMappingEntry;
 import com.raytheon.viz.hydrocommon.HydroConstants;
 import com.raytheon.viz.hydrocommon.resource.HydroPointResource;
 import com.raytheon.viz.mpe.ui.MPEDisplayManager;
-import com.raytheon.viz.mpe.ui.MPEFontManager;
+import com.raytheon.viz.mpe.ui.MPEFontFactory;
 import com.raytheon.viz.mpe.ui.actions.DrawDQCStations;
 import com.raytheon.viz.mpe.ui.dialogs.EditFreezeStationsDialog;
 import com.raytheon.viz.mpe.ui.dialogs.QcFreezeOptionsDialog;
@@ -106,6 +106,8 @@ public class PointFreezePlotResource extends
 
     private static Coordinate selectedCoordinate;
 
+    private MPEFontFactory fontFactory;
+
     private IFont font = null;
 
     private final DecimalFormat df = new DecimalFormat();
@@ -478,8 +480,8 @@ public class PointFreezePlotResource extends
         PointFreezePlotResource.target = target;
         this.paintProps = paintProps;
         MPEDisplayManager displayMgr = getResourceData().getMPEDisplayManager();
-        // Fonts are shared and cached, no need to init or dispose
-        font = MPEFontManager.getFont(this, displayMgr.getFontState(), target);
+        // Fonts are shared and cached, get from factory
+        font = fontFactory.getMPEFont(displayMgr.getFontState());
 
         if (DailyQcUtils.points_flag == 1 && displayMgr.isZflag() == true) {
             Iterator iter = dataMap.keySet().iterator();
@@ -684,6 +686,7 @@ public class PointFreezePlotResource extends
      */
     @Override
     protected void initInternal(IGraphicsTarget target) throws VizException {
+        fontFactory = new MPEFontFactory(target, this);
         /* Retrieve the freezing colormap. */
         List colorSet = getResourceData().getColorSet();
         ColorMap colorMap = new ColorMap(colorSet.size());
@@ -810,6 +813,6 @@ public class PointFreezePlotResource extends
      */
     @Override
     protected void disposeInternal() {
-        // DO NOT DISPOSE OF FONT AS IT IS SHARED IN ALL OF MPE
+        fontFactory.dispose();
     }
 }
diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/PointPrecipPlotResource.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/PointPrecipPlotResource.java
index d2b04249e3..0534e59c71 100644
--- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/PointPrecipPlotResource.java
+++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/PointPrecipPlotResource.java
@@ -41,9 +41,9 @@ import org.eclipse.ui.PlatformUI;
 import org.opengis.referencing.FactoryException;
 import org.opengis.referencing.operation.TransformException;
 
-import com.raytheon.uf.common.dataplugin.shef.tables.Colorvalue;
 import com.raytheon.uf.common.colormap.Color;
 import com.raytheon.uf.common.colormap.ColorMap;
+import com.raytheon.uf.common.dataplugin.shef.tables.Colorvalue;
 import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
 import com.raytheon.uf.viz.core.DrawableString;
 import com.raytheon.uf.viz.core.IExtent;
@@ -66,7 +66,7 @@ import com.raytheon.uf.viz.core.style.DataMappingPreferences.DataMappingEntry;
 import com.raytheon.viz.hydrocommon.HydroConstants;
 import com.raytheon.viz.hydrocommon.resource.HydroPointResource;
 import com.raytheon.viz.mpe.ui.MPEDisplayManager;
-import com.raytheon.viz.mpe.ui.MPEFontManager;
+import com.raytheon.viz.mpe.ui.MPEFontFactory;
 import com.raytheon.viz.mpe.ui.actions.DrawDQCStations;
 import com.raytheon.viz.mpe.ui.actions.OtherPrecipOptions;
 import com.raytheon.viz.mpe.ui.dialogs.EditPrecipStationsDialog;
@@ -108,6 +108,8 @@ public class PointPrecipPlotResource extends
 
     private static Coordinate selectedCoordinate;
 
+    private MPEFontFactory fontFactory;
+
     private IFont font = null;
 
     private final DecimalFormat df = new DecimalFormat();
@@ -712,7 +714,7 @@ public class PointPrecipPlotResource extends
         this.paintProps = paintProps;
         MPEDisplayManager displayMgr = getResourceData().getMPEDisplayManager();
         // Fonts are shared and cached, no need to init or dispose
-        font = MPEFontManager.getFont(this, displayMgr.getFontState(), target);
+        font = fontFactory.getMPEFont(displayMgr.getFontState());
 
         if (DailyQcUtils.points_flag == 1 && displayMgr.isQpf() == true) {
             Iterator iter = dataMap.keySet().iterator();
@@ -912,6 +914,7 @@ public class PointPrecipPlotResource extends
      */
     @Override
     protected void initInternal(IGraphicsTarget target) throws VizException {
+        fontFactory = new MPEFontFactory(target, this);
         /* Retrieve the precip colormap. */
         List colorSet = getResourceData().getColorSet();
         ColorMap colorMap = new ColorMap(colorSet.size());
@@ -1038,6 +1041,6 @@ public class PointPrecipPlotResource extends
      */
     @Override
     protected void disposeInternal() {
-        // DO NOT DISPOSE OF FONT AS IT IS SHARED IN ALL OF MPE
+        fontFactory.dispose();
     }
 }
diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/PointTempPlotResource.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/PointTempPlotResource.java
index bd3012de9f..ccd58c613b 100644
--- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/PointTempPlotResource.java
+++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/PointTempPlotResource.java
@@ -66,7 +66,7 @@ import com.raytheon.uf.viz.core.style.DataMappingPreferences.DataMappingEntry;
 import com.raytheon.viz.hydrocommon.HydroConstants;
 import com.raytheon.viz.hydrocommon.resource.HydroPointResource;
 import com.raytheon.viz.mpe.ui.MPEDisplayManager;
-import com.raytheon.viz.mpe.ui.MPEFontManager;
+import com.raytheon.viz.mpe.ui.MPEFontFactory;
 import com.raytheon.viz.mpe.ui.actions.DrawDQCStations;
 import com.raytheon.viz.mpe.ui.dialogs.EditTempStationsDialog;
 import com.raytheon.viz.mpe.ui.dialogs.QcTempOptionsDialog;
@@ -107,6 +107,8 @@ public class PointTempPlotResource extends
 
     private static Coordinate selectedCoordinate;
 
+    private MPEFontFactory fontFactory;
+
     private IFont font = null;
 
     private final DecimalFormat df = new DecimalFormat();
@@ -553,7 +555,7 @@ public class PointTempPlotResource extends
         this.paintProps = paintProps;
         MPEDisplayManager displayMgr = getResourceData().getMPEDisplayManager();
         // Fonts are shared and cached, no need to init or dispose
-        font = MPEFontManager.getFont(this, displayMgr.getFontState(), target);
+        font = fontFactory.getMPEFont(displayMgr.getFontState());
 
         if (DailyQcUtils.points_flag == 1 && displayMgr.isMaxmin() == true) {
             Iterator iter = dataMap.keySet().iterator();
@@ -783,6 +785,7 @@ public class PointTempPlotResource extends
      */
     @Override
     protected void initInternal(IGraphicsTarget target) throws VizException {
+        fontFactory = new MPEFontFactory(target, this);
         List colorSet = getResourceData().getColorSet();
         /* Retrieve the temp colormap. */
         ColorMap colorMap = new ColorMap(colorSet.size());
@@ -909,6 +912,6 @@ public class PointTempPlotResource extends
      */
     @Override
     protected void disposeInternal() {
-        // DO NOT DISPOSE OF FONT AS IT IS SHARED IN ALL OF MPE
+        fontFactory.dispose();
     }
 }