001package armyc2.c5isr.renderer;
002
003import java.util.ArrayList;
004import java.util.List;
005import java.util.Locale;
006import java.util.Map;
007
008import android.graphics.Bitmap;
009import android.graphics.Canvas;
010import android.graphics.DashPathEffect;
011import android.graphics.Paint;
012import android.graphics.Path;
013import android.graphics.Point;
014import android.graphics.PointF;
015import android.graphics.Rect;
016import android.graphics.RectF;
017import android.graphics.Bitmap.Config;
018import android.graphics.Paint.Cap;
019import android.graphics.Paint.Join;
020import android.graphics.Paint.Style;
021import android.graphics.Path.Direction;
022import android.graphics.Typeface;
023
024import armyc2.c5isr.renderer.utilities.Color;
025import armyc2.c5isr.renderer.utilities.ErrorLogger;
026import armyc2.c5isr.renderer.utilities.GENCLookup;
027import armyc2.c5isr.renderer.utilities.ImageInfo;
028import armyc2.c5isr.renderer.utilities.MSInfo;
029import armyc2.c5isr.renderer.utilities.MSLookup;
030import armyc2.c5isr.renderer.utilities.MilStdAttributes;
031import armyc2.c5isr.renderer.utilities.Modifier;
032import armyc2.c5isr.renderer.utilities.Modifiers;
033import armyc2.c5isr.renderer.utilities.PathUtilities;
034import armyc2.c5isr.renderer.utilities.RectUtilities;
035import armyc2.c5isr.renderer.utilities.RendererSettings;
036import armyc2.c5isr.renderer.utilities.RendererUtilities;
037import armyc2.c5isr.renderer.utilities.SVGInfo;
038import armyc2.c5isr.renderer.utilities.SVGLookup;
039import armyc2.c5isr.renderer.utilities.SVGPath;
040import armyc2.c5isr.renderer.utilities.SVGSymbolInfo;
041import armyc2.c5isr.renderer.utilities.Shape2SVG;
042import armyc2.c5isr.renderer.utilities.SymbolDimensionInfo;
043import armyc2.c5isr.renderer.utilities.SymbolID;
044import armyc2.c5isr.renderer.utilities.SymbolUtilities;
045import armyc2.c5isr.renderer.utilities.TextInfo;
046
047/**
048 * This class is used for rendering the labels/amplifiers/modifiers around the single point symbol.
049 */
050public class ModifierRenderer
051{
052
053    private static Paint _modifierFont = null;
054    private static float _modifierFontHeight = 10f;
055    private static float _modifierFontDescent = 2f;
056    private static RendererSettings RS = RendererSettings.getInstance();
057
058    private static final Object modifierFontMutex = new Object();
059    public static void setModifierFont(Paint font, float height, float descent)
060    {
061        synchronized (modifierFontMutex) {
062            _modifierFont = font;
063            _modifierFontHeight = height;
064            _modifierFontDescent = descent;
065        }
066    }
067
068    public static SymbolDimensionInfo processUnitDisplayModifiers(SymbolDimensionInfo sdi, String symbolID, Map<String,String> modifiers, Boolean hasTextModifiers, Map<String,String> attributes)
069    {
070
071        ImageInfo ii = null;
072        ImageInfo newii = null;
073        SVGSymbolInfo ssi = null;
074        SymbolDimensionInfo newsdi = null;
075        Rect symbolBounds = new Rect(sdi.getSymbolBounds());
076        Rect imageBounds = new Rect(sdi.getImageBounds());
077        Point centerPoint = new Point(sdi.getCenterPoint());
078        Point symbolCenter = new Point(symbolBounds.centerX(), symbolBounds.centerY());
079        TextInfo tiEchelon = null;
080        TextInfo tiAM = null;
081        Rect echelonBounds = null;
082        Rect amBounds = null;
083        Color textColor = Color.BLACK;
084        Color textBackgroundColor = null;
085        float strokeWidth = 3.0f;
086        float strokeWidthNL = 3.0f;
087        Color lineColor = SymbolUtilities.getLineColorOfAffiliation(symbolID);
088        Color fillColor = SymbolUtilities.getFillColorOfAffiliation(symbolID);
089        int buffer = 0;
090        int alpha = 255;
091        //ctx = null;
092        int offsetX = 0;
093        int offsetY = 0;
094        int pixelSize = RendererSettings.getInstance().getDefaultPixelSize();
095        SVGPath svgMobilityPath = null;
096        String svgMobilityGroup = null;
097
098        Paint modifierFont = getFont(attributes);
099        float[] hd = getFontHeightandDescent(modifierFont);
100        float modifierFontHeight = hd[0];
101        float modifierFontDescent = hd[1];
102
103        String modifierFontName = RendererSettings.getInstance().getModiferFontProps()[0];
104        if(attributes != null && attributes.containsKey(MilStdAttributes.FontFamily))
105        {
106            String temp = attributes.get(MilStdAttributes.FontFamily);
107            if(temp != null && !temp.isEmpty())
108                modifierFontName = temp;
109        }
110
111        int ss = SymbolID.getSymbolSet(symbolID);
112
113        if (attributes.containsKey(MilStdAttributes.Alpha))
114        {
115            alpha = Integer.parseInt(attributes.get(MilStdAttributes.Alpha));
116            textColor.setAlpha(alpha);
117        }
118        if (attributes.containsKey(MilStdAttributes.TextColor))
119        {
120            textColor = RendererUtilities.getColorFromHexString(attributes.get(MilStdAttributes.TextColor));
121            if(alpha > -1)
122                textColor.setAlpha(alpha);
123        }
124        if (attributes.containsKey(MilStdAttributes.TextBackgroundColor))
125        {
126            textBackgroundColor = RendererUtilities.getColorFromHexString(attributes.get(MilStdAttributes.TextBackgroundColor));
127            if(alpha > -1)
128                textBackgroundColor.setAlpha(alpha);
129        }
130        if (attributes.containsKey(MilStdAttributes.LineColor))
131        {
132            lineColor = RendererUtilities.getColorFromHexString(attributes.get(MilStdAttributes.LineColor));
133        }
134        if (attributes.containsKey(MilStdAttributes.FillColor))
135        {
136            fillColor = RendererUtilities.getColorFromHexString(attributes.get(MilStdAttributes.FillColor));
137        }
138        if(attributes.containsKey(MilStdAttributes.PixelSize))
139        {
140            pixelSize = Integer.parseInt(attributes.get(MilStdAttributes.PixelSize));
141        }
142
143        //float fontsize = RendererSettings.getInstance().getModiferFont().getTextSize();
144
145        // <editor-fold defaultstate="collapsed" desc="Build Mobility Modifiers">
146        float strokeWidthBasedOnDPI = 1;//min//Math.max(RendererSettings.getInstance().getDeviceDPI()/210,1);//min DPI
147        strokeWidthBasedOnDPI = Math.max(pixelSize / 25f,strokeWidthBasedOnDPI);//dpi base on symbol size
148        strokeWidthBasedOnDPI = Math.min(strokeWidthBasedOnDPI,RendererSettings.getInstance().getDeviceDPI()/32f);//max dpi
149
150        RectF mobilityBounds = null;
151        int ad = SymbolID.getAmplifierDescriptor(symbolID);//echelon/mobility
152        List<Path> shapes = new ArrayList<Path>();
153        Path mobilityPath = null;
154        Path mobilityPathFill = null;
155        if (ad >= SymbolID.Mobility_WheeledLimitedCrossCountry &&
156                (SymbolUtilities.canSymbolHaveModifier(symbolID, Modifiers.R_MOBILITY_INDICATOR) ||
157                 SymbolUtilities.canSymbolHaveModifier(symbolID, Modifiers.AG_AUX_EQUIP_INDICATOR)))
158        {
159
160            //Draw Mobility
161            int fifth = (int) ((symbolBounds.width() * 0.2) + 0.5f);
162            mobilityPath = new Path();
163            svgMobilityPath = null;
164            svgMobilityGroup = null;
165
166            int x = 0;
167            int y = 0;
168            int centerX = 0;
169            int bottomY = 0;
170            int height = 0;
171            int width = 0;
172            int middleY = 0;
173            int wheelOffset = 2;
174            int wheelSize = fifth;//10;
175            int rrHeight = fifth;//10;
176            int rrArcWidth = (int) ((fifth * 1.5) + 0.5f);//16;
177            float rad = wheelSize/2;
178
179
180            x = (int) symbolBounds.left + 1;
181            y = (int) symbolBounds.top;
182            height = Math.round(symbolBounds.height());
183            width = Math.round(symbolBounds.width()) - 3;
184            bottomY = y + height + 2;
185
186
187
188            if (ad >= SymbolID.Mobility_WheeledLimitedCrossCountry && //31, mobility starts above 30
189                    SymbolUtilities.canSymbolHaveModifier(symbolID, Modifiers.R_MOBILITY_INDICATOR))
190            {
191                bottomY = y + height + 2;
192
193                //wheelSize = width / 7;
194                //rrHeight = width / 7;
195                //rrArcWidth = width / 7;
196                if (ad == SymbolID.Mobility_WheeledLimitedCrossCountry)
197                {
198                    //line
199                    PathUtilities.addLine(mobilityPath, x, bottomY, x + width, bottomY);
200
201                    //left circle
202                    PathUtilities.addEllipse(mobilityPath, x, bottomY + wheelOffset, wheelSize, wheelSize);
203
204                    //right circle
205                    PathUtilities.addEllipse(mobilityPath, x + width - wheelSize, bottomY + wheelOffset, wheelSize, wheelSize);
206
207                    //SVG
208                    svgMobilityGroup = "<line x1=\"" + x + "\" y1=\"" + bottomY + "\" x2=\"" + (x + width) + "\" y2=\"" + bottomY + "\" />\n";
209                    svgMobilityGroup += "<circle cx=\"" + (x + (wheelSize/2)) + "\" cy=\"" + (bottomY + wheelOffset + (wheelSize/2)) + "\" r=\"" + (wheelSize/2) + "\"  ></circle>\n";
210                    svgMobilityGroup += "<circle cx=\"" + (x + width - (wheelSize/2)) + "\" cy=\"" + (bottomY + wheelOffset + (wheelSize/2)) + "\" r=\"" + (wheelSize/2) + "\"  ></circle>\n";
211                }
212                else if (ad == SymbolID.Mobility_WheeledCrossCountry)
213                {
214                    //line
215                    PathUtilities.addLine(mobilityPath, x, bottomY, x + width, bottomY);
216
217                    //left circle
218                    PathUtilities.addEllipse(mobilityPath, x, bottomY + wheelOffset, wheelSize, wheelSize);
219
220                    //right circle
221                    PathUtilities.addEllipse(mobilityPath, x + width - wheelSize, bottomY + wheelOffset, wheelSize, wheelSize);
222
223                    //center wheel
224                    PathUtilities.addEllipse(mobilityPath, x + (width / 2) - (wheelSize / 2), bottomY + wheelOffset, wheelSize, wheelSize);
225
226                    //SVG
227                    svgMobilityGroup = "<line x1=\"" + x + "\" y1=\"" + bottomY + "\" x2=\"" + (x + width) + "\" y2=\"" + bottomY + "\" />\n";
228                    svgMobilityGroup += "<circle cx=\"" + (x + (wheelSize/2)) + "\" cy=\"" + (bottomY + wheelOffset + (wheelSize/2)) + "\" r=\"" + (wheelSize/2) + "\" stroke=\"black\" ></circle>\n";
229                    svgMobilityGroup += "<circle cx=\"" + (x + width - (wheelSize/2)) + "\" cy=\"" + (bottomY + wheelOffset + (wheelSize/2)) + "\" r=\"" + (wheelSize/2) + "\" stroke=\"black\" ></circle>\n";
230                    svgMobilityGroup += "<circle cx=\"" + (x + (width/2)) + "\" cy=\"" + (bottomY + wheelOffset + (wheelSize/2)) + "\" r=\"" + (wheelSize/2) + "\" stroke=\"black\" ></circle>\n";
231                }
232                else if (ad == SymbolID.Mobility_Tracked)
233                {
234                    //round rectangle
235                    PathUtilities.addRoundedRect(mobilityPath, x, bottomY, width, rrHeight, rrHeight/2, rrHeight);
236                    svgMobilityGroup = "<rect width=\"" + width + "\" height=\"" + rrHeight + "\" x=\"" + x + "\" y=\"" + bottomY + "\" rx=\"" + rrHeight/2 + "\" ry=\"" + rrHeight + "\" />\n";
237
238                }
239                else if (ad == SymbolID.Mobility_Wheeled_Tracked)
240                {
241                    //round rectangle
242                    PathUtilities.addRoundedRect(mobilityPath, x, bottomY, width, rrHeight, wheelSize/2, rrHeight);
243                    svgMobilityGroup = "<rect width=\"" + width + "\" height=\"" + rrHeight + "\" x=\"" + x + "\" y=\"" + bottomY + "\" rx=\"" + rrHeight/2 + "\" ry=\"" + rrHeight + "\" />\n";
244
245                    //left circle
246                    PathUtilities.addEllipse(mobilityPath, x - wheelSize - wheelSize, bottomY, wheelSize, wheelSize);
247                    svgMobilityGroup += "<circle cx=\"" + (x - wheelSize - wheelSize/2) + "\" cy=\"" + (bottomY + (wheelSize/2)) + "\" r=\"" + (wheelSize/2) + "\"  stroke=\"black\" ></circle>\n";
248                }
249                else if (ad == SymbolID.Mobility_Towed)
250                {
251                    //line
252                    PathUtilities.addLine(mobilityPath, x + wheelSize, bottomY + (wheelSize / 2),
253                            x + width - wheelSize, bottomY + (wheelSize / 2));
254
255                    //left circle
256                    PathUtilities.addEllipse(mobilityPath, x, bottomY, wheelSize, wheelSize);
257
258                    //right circle
259                    PathUtilities.addEllipse(mobilityPath, x + width - wheelSize, bottomY, wheelSize, wheelSize);
260
261                    //SVG
262                    svgMobilityGroup = "<line x1=\"" + (x + wheelSize) + "\" y1=\"" + (bottomY + (wheelSize/2) + "\" x2=\"" + (x + width - wheelSize) + "\" y2=\"" + (bottomY + (wheelSize/2))) + "\" />\n";
263                    svgMobilityGroup += "<circle cx=\"" + (x + (wheelSize/2)) + "\" cy=\"" + (bottomY + (wheelSize/2)) + "\" r=\"" + (wheelSize/2) + "\" fill=\"none\" stroke=\"black\" ></circle>\n";
264                    svgMobilityGroup += "<circle cx=\"" + (x + width - (wheelSize/2)) + "\" cy=\"" + (bottomY + (wheelSize/2)) + "\" r=\"" + (wheelSize/2) + "\" fill=\"none\" stroke=\"black\" ></circle>\n";
265                }
266                else if (ad == SymbolID.Mobility_Rail)
267                {
268                    //line
269                    PathUtilities.addLine(mobilityPath, x, bottomY, x + width, bottomY);
270
271                    //left circle
272                    PathUtilities.addEllipse(mobilityPath, x + wheelSize, bottomY + wheelOffset, wheelSize, wheelSize);
273
274                    //left circle2
275                    PathUtilities.addEllipse(mobilityPath, x, bottomY + wheelOffset, wheelSize, wheelSize);
276
277                    //right circle
278                    PathUtilities.addEllipse(mobilityPath, x + width - wheelSize, bottomY + wheelOffset, wheelSize, wheelSize);
279
280                    //right circle2
281                    PathUtilities.addEllipse(mobilityPath, x + width - wheelSize - wheelSize, bottomY + wheelOffset, wheelSize, wheelSize);
282
283                    //SVG
284                    svgMobilityGroup = "<line x1=\"" + x + "\" y1=\"" + bottomY + "\" x2=\"" + (x + width) + "\" y2=\"" + bottomY + "\" />\n";
285
286                    svgMobilityGroup += "<circle cx=\"" + (x + rad) + "\" cy=\"" + (bottomY + wheelOffset + rad) + "\" r=\"" + rad + "\" ></circle>\n";
287                    svgMobilityGroup += "<circle cx=\"" + (x + rad + wheelSize) + "\" cy=\"" + (bottomY + wheelOffset + rad) + "\" r=\"" + rad + "\" ></circle>\n";
288
289                    svgMobilityGroup += "<circle cx=\"" + (x + width - rad) + "\" cy=\"" + (bottomY + wheelOffset + rad) + "\" r=\"" + rad + "\" ></circle>\n";
290                    svgMobilityGroup += "<circle cx=\"" + (x + width - rad - wheelSize) + "\" cy=\"" + (bottomY + wheelOffset + rad) + "\" r=\"" + rad + "\" ></circle>\n";
291
292                }
293                else if (ad == SymbolID.Mobility_OverSnow)
294                {
295                        float halfWidth = (rrArcWidth * 0.5f);
296                    mobilityPath.moveTo(x, bottomY);
297                    mobilityPath.lineTo(x + halfWidth, bottomY + halfWidth);
298                    mobilityPath.lineTo(x + width, bottomY + halfWidth);
299
300                    //SVG
301                    svgMobilityPath = new SVGPath();
302                    svgMobilityPath.moveTo(x,bottomY);
303                    svgMobilityPath.lineTo(x + halfWidth, bottomY + halfWidth);
304                    svgMobilityPath.lineTo(x + width, bottomY + halfWidth);
305
306                }
307                else if (ad == SymbolID.Mobility_Sled)
308                {
309                    mobilityPath.moveTo(x, bottomY);
310
311                    mobilityPath.cubicTo(x, bottomY, x - rrHeight, bottomY + rrHeight/2, x, bottomY + rrHeight);
312                    //mobilityPath.bezierCurveTo(x, bottomY, x-rrArcWidth, bottomY+3, x, bottomY+rrHeight);
313
314                    mobilityPath.lineTo(x + width, bottomY + rrHeight);
315
316                    mobilityPath.cubicTo(x + width, bottomY + rrHeight, x + width + rrHeight, bottomY + rrHeight/2, x + width, bottomY);
317                    //shapeMobility.curveTo(x + width, bottomY + rrHeight, x+ width + rrArcWidth, bottomY+3, x + width, bottomY);
318
319                    //SVG
320                    svgMobilityPath = new SVGPath();
321                    svgMobilityPath.moveTo(x, bottomY);
322                    svgMobilityPath.bezierCurveTo(x, bottomY, x - rrHeight, bottomY + rrHeight/2, x, bottomY + rrHeight);
323                    svgMobilityPath.lineTo(x + width, bottomY + rrHeight);
324                    svgMobilityPath.bezierCurveTo(x + width, bottomY + rrHeight, x + width + rrHeight, bottomY + rrHeight/2, x + width, bottomY);
325
326                }
327                else if (ad == SymbolID.Mobility_PackAnimals)
328                {
329                    centerX = Math.round(RectUtilities.getCenterX(symbolBounds));
330                    int angleWidth = rrHeight / 2;
331                    mobilityPath.moveTo(centerX, bottomY + rrHeight + 2);
332                    mobilityPath.lineTo(centerX - angleWidth, bottomY);
333                    mobilityPath.lineTo(centerX - angleWidth*2, bottomY + rrHeight + 2);
334
335                    mobilityPath.moveTo(centerX, bottomY + rrHeight + 2);
336                    mobilityPath.lineTo(centerX + angleWidth, bottomY);
337                    mobilityPath.lineTo(centerX + angleWidth*2, bottomY + rrHeight + 2);
338
339                    //SVG
340                    svgMobilityPath = new SVGPath();
341                    svgMobilityPath.moveTo(centerX, bottomY + rrHeight + 2);
342                    svgMobilityPath.lineTo(centerX - angleWidth, bottomY);
343                    svgMobilityPath.lineTo(centerX - angleWidth*2, bottomY + rrHeight + 2);
344
345                    svgMobilityPath.moveTo(centerX, bottomY + rrHeight + 2);
346                    svgMobilityPath.lineTo(centerX + angleWidth, bottomY);
347                    svgMobilityPath.lineTo(centerX + angleWidth*2, bottomY + rrHeight + 2);
348                }
349                else if (ad == SymbolID.Mobility_Barge)
350                {
351                    centerX = Math.round(RectUtilities.getCenterX(symbolBounds));
352                    PathUtilities.addLine(mobilityPath, x + width, bottomY, x, bottomY);
353                    //var line = new SO.Line(x + width, bottomY,x, bottomY);
354
355                    float quarterX = (centerX - x) / 2;
356                    //var quarterY = (((bottomY + rrHeight) - bottomY)/2);
357
358                    mobilityPath.moveTo(x, bottomY);
359                    mobilityPath.cubicTo(x + quarterX, bottomY + rrHeight, centerX + quarterX, bottomY + rrHeight, x + width, bottomY);
360                    //shapes.push(new SO.BCurve(x, bottomY,x+quarterX, bottomY+rrHeight, centerX + quarterX, bottomY + rrHeight, x + width, bottomY));
361
362                    //SVG
363                    svgMobilityPath = new SVGPath();
364                    svgMobilityPath.moveTo(x + width, bottomY);
365                    svgMobilityPath.lineTo(x, bottomY);
366                    svgMobilityPath.moveTo(x, bottomY);
367                    svgMobilityPath.bezierCurveTo(x + quarterX, bottomY + rrHeight, centerX + quarterX, bottomY + rrHeight, x + width, bottomY);
368                }
369
370                else if (ad == SymbolID.Mobility_Amphibious)
371                {
372                    float incrementX = width / 7;
373                    middleY = (bottomY + (rrHeight / 2));
374
375                    x = Math.round(x + (incrementX / 2));
376                    float r = Math.round(incrementX / 2);
377
378                    //mobilityPath.arcTo(oval, sAngle, sAngle, moveTo);
379                    PathUtilities.arc(mobilityPath, x, middleY, r, 180, 180);
380                    PathUtilities.arc(mobilityPath, x + incrementX, middleY, r, 180, -180, false);
381                    PathUtilities.arc(mobilityPath, x + incrementX * 2, middleY, r, 180, 180, false);
382                    PathUtilities.arc(mobilityPath, x + incrementX * 3, middleY, r, 180, -180, false);
383                    PathUtilities.arc(mobilityPath, x + incrementX * 4, middleY, r, 180, 180, false);
384                    PathUtilities.arc(mobilityPath, x + incrementX * 5, middleY, r, 180, -180, false);
385                    PathUtilities.arc(mobilityPath, x + incrementX * 6, middleY, r, 180, 180, false);
386
387                    //SVG
388                    x = symbolBounds.left + 1;
389                    svgMobilityGroup = "<path d=\"M" + x + " " + middleY + " ";
390                    svgMobilityGroup += "C " + x + " " + bottomY + " " + (x + incrementX) + " " + bottomY + " " + (x + incrementX) + " " + middleY + " ";
391                    svgMobilityGroup += "C " + (x + incrementX) + " " + (bottomY + rrHeight) + " " + (x + (incrementX * 2)) + " " + (bottomY + rrHeight) + " " + (x + (incrementX*2)) + " " + middleY + " ";
392                    svgMobilityGroup += "C " + (x + (incrementX*2))  + " " + bottomY + " " + (x + (incrementX*3)) + " " + bottomY + " " + (x + incrementX*3) + " " + middleY + " ";
393                    svgMobilityGroup += "C " + (x + (incrementX*3)) + " " + (bottomY + rrHeight) + " " + (x + (incrementX * 4)) + " " + (bottomY + rrHeight) + " " + (x + (incrementX*4)) + " " + middleY + " ";
394                    svgMobilityGroup += "C " + (x + (incrementX*4))  + " " + bottomY + " " + (x + (incrementX*5)) + " " + bottomY + " " + (x + incrementX*5) + " " + middleY + " ";
395                    svgMobilityGroup += "C " + (x + (incrementX*5)) + " " + (bottomY + rrHeight) + " " + (x + (incrementX * 6)) + " " + (bottomY + rrHeight) + " " + (x + (incrementX*6)) + " " + middleY + " ";
396                    svgMobilityGroup += "C " + (x + (incrementX*6))  + " " + bottomY + " " + (x + (incrementX*7)) + " " + bottomY + " " + (x + incrementX*7) + " " + middleY + " ";
397                    svgMobilityGroup += "\"/>";
398
399
400                }
401
402                if(svgMobilityGroup != null)
403                    svgMobilityGroup = "<g stroke-width=\"" + strokeWidthBasedOnDPI + "\" fill=\"none\"" + " stroke=\"" + RendererUtilities.colorToHexString(lineColor,false) + "\"" + ">\n" + svgMobilityGroup + "</g>\n";
404
405            }
406            //Draw Towed Array Sonar
407            if ((ad == SymbolID.Mobility_ShortTowedArray || ad == SymbolID.Mobility_LongTowedArray) &&
408                    SymbolUtilities.canSymbolHaveModifier(symbolID, Modifiers.AG_AUX_EQUIP_INDICATOR)) {
409                int boxHeight = (int) ((rrHeight * 0.8f) + 0.5f);
410                bottomY = y + height + (boxHeight / 7);
411                mobilityPathFill = new Path();
412                offsetY = boxHeight / 7;//1;
413                centerX = Math.round(symbolBounds.left + (symbolBounds.right - symbolBounds.left) / 2);
414                int squareOffset = Math.round(boxHeight * 0.5f);
415                middleY = ((boxHeight / 2) + bottomY) + offsetY;//+1 for offset from symbol
416                if (ad == SymbolID.Mobility_ShortTowedArray) {
417                    //subtract 0.5 because lines 1 pixel thick get aliased into
418                    //a line two pixels wide.
419                    //line
420                    PathUtilities.addLine(mobilityPath, centerX - 1, bottomY - 1, centerX - 1, bottomY + offsetY + boxHeight + offsetY);
421                    //shapes.push(new SO.Line(centerX-1,bottomY-1,centerX-1, bottomY + rrHeight + 3));
422                    //shapeLines.append(new Line2D.Double(centerX,bottomY - 2,centerX, bottomY + rrHeight + 1), false);
423                    //line
424                    PathUtilities.addLine(mobilityPath, x, middleY, x + width, middleY);
425                    //shapes.push(new SO.Line(x,middleY,x + width, middleY));
426                    //shapeLines.append(new Line2D.Double(x,middleY,x + width, middleY), false);
427                    //square
428                    mobilityPathFill.addRect(PathUtilities.makeRectF(x - squareOffset, bottomY + offsetY, boxHeight, boxHeight), Direction.CW);
429                    //shapes.push(new SO.Rectangle(x-squareOffset, bottomY+offsetY, 5, 5));
430                    //shapeSquares.append(new Rectangle2D.Double(x-squareOffset, bottomY, 5, 5), false);
431                    //square
432                    mobilityPathFill.addRect(PathUtilities.makeRectF(Math.round(centerX - squareOffset), bottomY + offsetY, boxHeight, boxHeight), Direction.CW);
433                    //shapes.push(new SO.Rectangle(Math.round(centerX-squareOffset), bottomY+offsetY, 5, 5));
434                    //shapeSquares.append(new Rectangle2D.Double(centerX-squareOffset, bottomY, 5, 5), false);
435                    //square
436                    mobilityPathFill.addRect(PathUtilities.makeRectF(x + width - squareOffset, bottomY + offsetY, boxHeight, boxHeight), Direction.CW);
437                    //shapes.push(new SO.Rectangle(x + width - squareOffset, bottomY+offsetY, 5, 5));
438                    //shapeSquares.append(new Rectangle2D.Double(x + width - squareOffset, bottomY, 5, 5), false);
439
440                    //SVG
441                    String svgColor = RendererUtilities.colorToHexString(lineColor,false);
442                    svgMobilityGroup = "<line x1=\"" + (centerX - 1) + "\" y1=\"" + (bottomY - 1) + "\" x2=\"" + (centerX - 1) + "\" y2=\"" + (bottomY + offsetY + boxHeight + offsetY) + "\" stroke=\"" + svgColor + "\" stroke-width=\"" + strokeWidthBasedOnDPI + "\" />\n";
443                    svgMobilityGroup += "<line x1=\"" + (x) + "\" y1=\"" + (middleY) + "\" x2=\"" + (x + width) + "\" y2=\"" + (middleY) + "\" stroke=\"" + svgColor + "\" stroke-width=\"" + strokeWidthBasedOnDPI + "\" />\n";
444                    svgMobilityGroup += "<rect width=\"" + (boxHeight) + "\" height=\"" + (boxHeight) + "\" x=\"" + (x - squareOffset) + "\" y=\"" + (bottomY + offsetY) + "\" fill=\"" + svgColor + "\" stroke-width=\"0\"/>\n";
445                    svgMobilityGroup += "<rect width=\"" + (boxHeight) + "\" height=\"" + (boxHeight) + "\" x=\"" + (centerX - squareOffset) + "\" y=\"" + (bottomY + offsetY) + "\" fill=\"" + svgColor + "\" stroke-width=\"0\"/>\n";
446                    svgMobilityGroup += "<rect width=\"" + (boxHeight) + "\" height=\"" + (boxHeight) + "\" x=\"" + (x + width - squareOffset) + "\" y=\"" + (bottomY + offsetY) + "\" fill=\"" + svgColor + "\" stroke-width=\"0\"/>\n";
447
448
449                } else if (ad == SymbolID.Mobility_LongTowedArray) {
450                    int leftX = x + (centerX - x) / 2,
451                            rightX = centerX + (x + width - centerX) / 2;
452
453                    //line vertical left
454                    PathUtilities.addLine(mobilityPath, leftX, bottomY - 1, leftX, bottomY + offsetY + boxHeight + offsetY);
455                    //shapes.push(new SO.Line(leftX,bottomY - 1,leftX, bottomY + rrHeight + 3));
456                    //shapeLines.append(new Line2D.Double(leftX,bottomY - 2,leftX, bottomY + rrHeight + 1), false);
457                    //line vertical right
458                    PathUtilities.addLine(mobilityPath, rightX, bottomY - 1, rightX, bottomY + offsetY + boxHeight + offsetY);
459                    //shapes.push(new SO.Line(rightX,bottomY - 1,rightX, bottomY + rrHeight + 3));
460                    //shapeLines.append(new Line2D.Double(rightX,bottomY - 2,rightX, bottomY + rrHeight + 1), false);
461                    //line horizontal
462                    PathUtilities.addLine(mobilityPath, x, middleY, x + width, middleY);
463                    //shapes.push(new SO.Line(x,middleY,x + width, middleY));
464                    //shapeLines.append(new Line2D.Double(x,middleY,x + width, middleY), false);
465                    //square left
466                    mobilityPathFill.addRect(PathUtilities.makeRectF(x - squareOffset, bottomY + offsetY, boxHeight, boxHeight), Direction.CW);
467                    //shapes.push(new SO.Rectangle(x-squareOffset, bottomY+offsetY, 5, 5));
468                    //shapeSquares.append(new Rectangle2D.Double(x-squareOffset, bottomY, 5, 5), false);
469                    //square middle
470                    mobilityPathFill.addRect(PathUtilities.makeRectF(centerX - squareOffset, bottomY + offsetY, boxHeight, boxHeight), Direction.CW);
471                    //shapes.push(new SO.Rectangle(centerX-squareOffset, bottomY+offsetY, 5, 5));
472                    //shapeSquares.append(new Rectangle2D.Double(centerX-squareOffset, bottomY, 5, 5), false);
473                    //square right
474                    mobilityPathFill.addRect(PathUtilities.makeRectF(x + width - squareOffset, bottomY + offsetY, boxHeight, boxHeight), Direction.CW);
475                    //shapes.push(new SO.Rectangle(x + width - squareOffset, bottomY+offsetY, 5, 5));
476                    //shapeSquares.append(new Rectangle2D.Double(x + width - squareOffset, bottomY, 5, 5), false);
477                    //square middle left
478                    mobilityPathFill.addRect(PathUtilities.makeRectF(leftX - squareOffset, bottomY + offsetY, boxHeight, boxHeight), Direction.CW);
479                    //shapes.push(new SO.Rectangle(leftX - squareOffset, bottomY+offsetY, 5, 5));
480                    //shapeSquares.append(new Rectangle2D.Double(leftX - squareOffset, bottomY, 5, 5), false);
481                    //square middle right
482                    mobilityPathFill.addRect(PathUtilities.makeRectF(rightX - squareOffset, bottomY + offsetY, boxHeight, boxHeight), Direction.CW);
483                    //shapes.push(new SO.Rectangle(rightX - squareOffset, bottomY+offsetY, 5, 5));
484                    //shapeSquares.append(new Rectangle2D.Double(rightX - squareOffset, bottomY, 5, 5), false);
485
486                    //SVG
487                    String svgColor = RendererUtilities.colorToHexString(lineColor,false);
488                    svgMobilityGroup = "<line x1=\"" + (leftX) + "\" y1=\"" + (bottomY - 1) + "\" x2=\"" + (leftX) + "\" y2=\"" + (bottomY + offsetY + boxHeight + offsetY) + "\" stroke=\"" + svgColor + "\" stroke-width=\"" + strokeWidthBasedOnDPI + "\" />\n";
489                    svgMobilityGroup += "<line x1=\"" + (rightX) + "\" y1=\"" + (bottomY - 1) + "\" x2=\"" + (rightX) + "\" y2=\"" + (bottomY + offsetY + boxHeight + offsetY) + "\" stroke=\"" + svgColor + "\" stroke-width=\"" + strokeWidthBasedOnDPI + "\" />\n";
490                    svgMobilityGroup += "<line x1=\"" + (x) + "\" y1=\"" + (middleY) + "\" x2=\"" + (x + width) + "\" y2=\"" + (middleY) + "\" stroke=\"" + svgColor + "\" stroke-width=\"" + strokeWidthBasedOnDPI + "\" />\n";
491                    svgMobilityGroup += "<rect width=\"" + (boxHeight) + "\" height=\"" + (boxHeight) + "\" x=\"" + (x - squareOffset) + "\" y=\"" + (bottomY + offsetY) + "\" fill=\"" + svgColor + "\" stroke-width=\"0\"/>\n";
492                    svgMobilityGroup += "<rect width=\"" + (boxHeight) + "\" height=\"" + (boxHeight) + "\" x=\"" + (centerX - squareOffset) + "\" y=\"" + (bottomY + offsetY) + "\" fill=\"" + svgColor + "\" stroke-width=\"0\"/>\n";
493                    svgMobilityGroup += "<rect width=\"" + (boxHeight) + "\" height=\"" + (boxHeight) + "\" x=\"" + (x + width - squareOffset) + "\" y=\"" + (bottomY + offsetY) + "\" fill=\"" + svgColor + "\" stroke-width=\"0\"/>\n";
494                    svgMobilityGroup += "<rect width=\"" + (boxHeight) + "\" height=\"" + (boxHeight) + "\" x=\"" + (leftX - squareOffset) + "\" y=\"" + (bottomY + offsetY) + "\" fill=\"" + svgColor + "\" stroke-width=\"0\"/>\n";
495                    svgMobilityGroup += "<rect width=\"" + (boxHeight) + "\" height=\"" + (boxHeight) + "\" x=\"" + (rightX - squareOffset) + "\" y=\"" + (bottomY + offsetY) + "\" fill=\"" + svgColor + "\" stroke-width=\"0\"/>\n";
496
497                }
498                if(svgMobilityGroup != null)
499                    svgMobilityGroup = "<g stroke-width=\"" + strokeWidthBasedOnDPI + "\" fill=\"" + RendererUtilities.colorToHexString(lineColor,false) + "\"" + " stroke=\"" + RendererUtilities.colorToHexString(lineColor,false) + "\"" +  ">\n" + svgMobilityGroup + "\n</g>";
500            }
501
502            //get mobility bounds
503            if (mobilityPath != null)
504            {
505
506                //build mobility bounds
507                mobilityBounds = new RectF();
508                mobilityPath.computeBounds(mobilityBounds, true);
509
510                RectF mobilityFillBounds = new RectF();
511                if (mobilityPathFill != null)
512                {
513                    mobilityPathFill.computeBounds(mobilityFillBounds, true);
514                    mobilityBounds.union(mobilityFillBounds);
515                }
516
517                //grow by one because we use a line thickness of 2.
518                RectUtilities.grow(mobilityBounds,Math.round(strokeWidthBasedOnDPI/2));
519                //mobilityBounds.set(mobilityBounds.left - 1, mobilityBounds.top - 1, mobilityBounds.right + 1, mobilityBounds.bottom + 1);
520                imageBounds.union(RectUtilities.makeRectFromRectF(mobilityBounds));
521            }
522        }
523        // </editor-fold>
524
525        // <editor-fold defaultstate="collapsed" desc="Leadership Indicator Modifier">
526        RectF liBounds = null;
527        Path liPath = null;
528        PointF liTop = null;
529        PointF liLeft = null;
530        PointF liRight = null;
531        if(ad == SymbolID.Leadership_Individual && ss == SymbolID.SymbolSet_DismountedIndividuals &&
532                (SymbolID.getFrameShape(symbolID)==SymbolID.FrameShape_DismountedIndividuals ||
533                        SymbolID.getFrameShape(symbolID)==SymbolID.FrameShape_Unknown))
534        {
535            liPath = new Path();
536
537            int si = SymbolID.getStandardIdentity(symbolID);
538            int af = SymbolID.getAffiliation(symbolID);
539            int c = SymbolID.getContext(symbolID);
540            //int fs = SymbolID.getFrameShape(symbolID);
541            double centerOffset = 0;
542            double sideOffset = 0;
543            double left = symbolBounds.left;
544            double right = symbolBounds.left + symbolBounds.width();
545
546            if(af == SymbolID.StandardIdentity_Affiliation_Unknown || af == SymbolID.StandardIdentity_Affiliation_Pending)
547            {
548                centerOffset = (symbolBounds.height()*0.1012528735632184);
549                sideOffset = (right - left)*0.3583513488109785;
550                //left = symbolBounds.getCenterX() - ((symbolBounds.getWidth() / 2) * 0.66420458);
551                //right = symbolBounds.getCenterX() + ((symbolBounds.getWidth() / 2) * 0.66420458);
552            }
553            if(af == SymbolID.StandardIdentity_Affiliation_Neutral)
554            {
555                centerOffset = (symbolBounds.height()*0.25378787878787878);
556                sideOffset = (right - left)*0.2051402812352822;
557            }
558            if(SymbolUtilities.isReality(symbolID) || SymbolUtilities.isSimulation(symbolID))
559            {
560                if(af==SymbolID.StandardIdentity_Affiliation_Friend || af==SymbolID.StandardIdentity_Affiliation_AssumedFriend)
561                {//hexagon friend/assumed friend
562                    centerOffset = (symbolBounds.height()*0.08);
563                    sideOffset = (right - left)*0.282714524168219;//(symbolBounds.getHeight()*0.29);
564                }
565                else if(af==SymbolID.StandardIdentity_Affiliation_Hostile_Faker || af==SymbolID.StandardIdentity_Affiliation_Suspect_Joker)
566                {//diamond hostile/suspect
567
568                    left = symbolBounds.centerX() - ((symbolBounds.width() / 2) * 1.0653694149);//1.07);//1.0653694149);
569                    right = symbolBounds.centerX() + ((symbolBounds.width() / 2) * 1.0653694149);//1.07);//1.0653694149);
570
571                    centerOffset = (symbolBounds.height()*0.08);//0.0751139601139601
572                    sideOffset = (right - left)*0.4923255424955992;
573                }
574            }
575            else//Exercise
576            {
577                //hexagon
578                if(af!=SymbolID.StandardIdentity_Affiliation_Unknown ||
579                        af==SymbolID.StandardIdentity_Affiliation_Neutral)
580                {
581                    centerOffset = (symbolBounds.height()*0.08);
582                    sideOffset = (right - left)*0.282714524168219;
583                }
584            }
585
586            //create leadership indicator /\
587            liTop = new PointF(symbolBounds.centerX(), (float)(symbolBounds.top - centerOffset));
588            liLeft = new PointF((float)left, (float)(liTop.y + sideOffset));
589            liRight = new PointF((float)right, (float)(liTop.y + sideOffset));
590
591
592            liPath.moveTo(liTop.x, liTop.y);
593            liPath.lineTo(liLeft.x, liLeft.y);
594            liPath.moveTo(liTop.x, liTop.y);
595            liPath.lineTo(liRight.x, liRight.y);//*/
596
597
598            liBounds = new RectF(liLeft.x, liTop.y, liRight.x - liLeft.x, liLeft.y - liTop.y);
599
600            RectUtilities.grow(liBounds,2);
601
602            imageBounds.union(RectUtilities.makeRectFromRectF(liBounds));
603        }
604
605        // </editor-fold>
606
607        // <editor-fold defaultstate="collapsed" desc="Build Echelon">
608        //Draw Echelon
609        int intEchelon = SymbolID.getAmplifierDescriptor(symbolID);
610        String strEchelon = SymbolUtilities.getEchelonText(intEchelon);
611
612        if (strEchelon != null
613                && SymbolUtilities.hasModifier(symbolID, Modifiers.B_ECHELON))
614        {
615
616            int echelonOffset = 2,
617                    outlineOffset = RS.getTextOutlineWidth();
618
619            tiEchelon = new TextInfo(strEchelon, 0, 0, modifierFont, modifierFontName);
620            echelonBounds = tiEchelon.getTextBounds();
621
622            int y = Math.round(symbolBounds.left - echelonOffset);
623            int x = Math.round(symbolBounds.left + (symbolBounds.width() / 2)
624                    - (echelonBounds.width() / 2));
625            tiEchelon.setLocation(x, y);
626
627            //There will never be lowercase characters in an echelon so trim that fat.
628            //Remove the descent from the bounding box.
629            tiEchelon.getTextOutlineBounds();//.shiftBR(0,Math.round(-(echelonBounds.height()*0.3)));
630
631            //make echelon bounds a little more spacious for things like nearby labels and Task Force.
632            RectUtilities.grow(echelonBounds, outlineOffset);
633            //tiEchelon.getTextOutlineBounds();
634//                RectUtilities.shift(echelonBounds, x, -outlineOffset);
635            //echelonBounds.shift(0,-outlineOffset);// - Math.round(echelonOffset/2));
636            tiEchelon.setLocation(x, y - outlineOffset);
637
638            imageBounds.union(echelonBounds);
639
640        }
641        // </editor-fold>
642
643        // <editor-fold defaultstate="collapsed" desc="Build Task Force">
644        Rect tfBounds = null;
645        Rect tfRectangle = null;
646        if (SymbolUtilities.isTaskForce(symbolID) && SymbolUtilities.hasModifier(symbolID, Modifiers.D_TASK_FORCE_INDICATOR))
647        {
648
649            int height = Math.round(symbolBounds.height() / 4.0f);
650            int width = Math.round(symbolBounds.width() / 3.0f);
651
652            if(!SymbolUtilities.hasRectangleFrame(symbolID))
653            {
654                height = (int)Math.round(symbolBounds.height() / 6.0f);
655            }
656
657            tfRectangle = RectUtilities.makeRect((int) symbolBounds.left + width,
658                    (int) symbolBounds.top - height,
659                    width,
660                    height);
661
662            tfBounds = RectUtilities.makeRect(tfRectangle.left + -1,
663                    tfRectangle.top - 1,
664                    tfRectangle.width() + 2,
665                    tfRectangle.height() + 2);
666
667            if (echelonBounds != null)
668            {
669                /*tfRectangle = new Rect(echelonBounds.left,
670                        echelonBounds.top,// + outlineOffset,
671                        echelonBounds.right,
672                        symbolBounds.top-1);
673                tfBounds = new Rect(tfRectangle);*/
674
675                int tfx = tfRectangle.left;
676                int tfw = tfRectangle.width();
677                int tfy = tfRectangle.top;
678                int tfh = tfRectangle.height();
679
680                if(echelonBounds.width() > tfRectangle.width())
681                {
682                    tfx = symbolBounds.left + symbolBounds.width()/2 - (echelonBounds.width()/2) - 1;
683                    tfw = echelonBounds.width()+2;
684                }
685                if(echelonBounds.height() > tfRectangle.height())
686                {
687                    tfy = echelonBounds.top-1;
688                    tfh = echelonBounds.height()+2;
689
690                }
691                tfRectangle = RectUtilities.makeRect((int)tfx,
692                        tfy,// + outlineOffset,
693                        tfw,
694                        tfh);
695
696
697                tfBounds = RectUtilities.makeRect((tfRectangle.left - 1),
698                        (tfRectangle.top - 1),
699                        (tfRectangle.width() + 2),
700                        (tfRectangle.height() + 2));
701            }
702
703            imageBounds.union(tfBounds);
704        }
705        // </editor-fold>
706
707        // <editor-fold defaultstate="collapsed" desc="Build Feint Dummy Indicator">
708        Rect fdiBounds = null;
709        Point fdiTop = null;
710        Point fdiLeft = null;
711        Point fdiRight = null;
712
713
714        if (SymbolUtilities.hasFDI(symbolID)
715                && SymbolUtilities.canSymbolHaveModifier(symbolID, Modifiers.AB_FEINT_DUMMY_INDICATOR))
716        {
717            //create feint indicator /\
718            fdiLeft = new Point((int) symbolBounds.left, (int) symbolBounds.top);
719            fdiRight = new Point((int) (symbolBounds.left + symbolBounds.width()), (int) symbolBounds.top);
720            fdiTop = new Point(Math.round(RectUtilities.getCenterX(symbolBounds)), Math.round(symbolBounds.top - (symbolBounds.width() * .5f)));
721
722
723            fdiBounds = RectUtilities.makeRect(fdiLeft.x, fdiLeft.y, 1, 1);
724            fdiBounds.union(fdiTop.x, fdiTop.y);
725            fdiBounds.union(fdiRight.x, fdiRight.y);
726
727            float fdiStrokeWidth = Math.round(RendererSettings.getInstance().getDeviceDPI() / 96f);
728            RectUtilities.grow(fdiBounds,Math.round(fdiStrokeWidth/2));
729
730            if (echelonBounds != null)
731            {
732                int shiftY = Math.round(symbolBounds.top - echelonBounds.height() - 2);
733                fdiLeft.offset(0, shiftY);
734                fdiTop.offset(0, shiftY);
735                fdiRight.offset(0, shiftY);
736                fdiBounds.offset(0, shiftY);
737            }
738
739            imageBounds.union(fdiBounds);
740
741        }
742        // </editor-fold>
743
744        //Using SVG files for installation indicator now
745        // <editor-fold defaultstate="collapsed" desc="Build Installation">
746        /*//Using SVG files for the installation indicator
747        Rect instRectangle = null;
748        Rect instBounds = null;
749        if (SymbolUtilities.hasInstallationModifier(symbolID)
750                && SymbolUtilitiesD.canSymbolHaveModifier(symbolID, Modifiers.AC_INSTALLATION))
751        {//the actual installation symbols have the modifier
752            //built in.  everything else, we have to draw it.
753            //
754            ////get indicator dimensions////////////////////////////////
755            int width;
756            int height;
757            char affiliation = SymbolUtilities.getAffiliation(symbolID);
758
759            if (affiliation == 'F'
760                    || affiliation == 'A'
761                    || affiliation == 'D'
762                    || affiliation == 'M'
763                    || affiliation == 'J'
764                    || affiliation == 'K')
765            {
766                //4th height, 3rd width
767                height = Math.round(symbolBounds.height() / 4);
768                width = Math.round(symbolBounds.width() / 3);
769            }
770            else if (affiliation == 'H' || affiliation == 'S')//hostile,suspect
771            {
772                //6th height, 3rd width
773                height = Math.round(symbolBounds.height() / 6);
774                width = Math.round(symbolBounds.width() / 3);
775            }
776            else if (affiliation == 'N' || affiliation == 'L')//neutral,exercise neutral
777            {
778                //6th height, 3rd width
779                height = Math.round(symbolBounds.height() / 6);
780                width = Math.round(symbolBounds.width() / 3);
781            }
782            else if (affiliation == 'P'
783                    || affiliation == 'U'
784                    || affiliation == 'G'
785                    || affiliation == 'W')
786            {
787                //6th height, 3rd width
788                height = Math.round(symbolBounds.height() / 6);
789                width = Math.round(symbolBounds.width() / 3);
790            }
791            else
792            {
793                //6th height, 3rd width
794                height = Math.round(symbolBounds.height() / 6);
795                width = Math.round(symbolBounds.width() / 3);
796            }
797
798//                    if(width * 3 < symbolBounds.width())
799//                        width++;
800            //set installation position/////////////////////////////////
801            //set position of indicator
802            if (affiliation == 'F'
803                    || affiliation == 'A'
804                    || affiliation == 'D'
805                    || affiliation == 'M'
806                    || affiliation == 'J'
807                    || affiliation == 'K'
808                    || affiliation == 'N'
809                    || affiliation == 'L')
810            {
811                instRectangle = RectUtilities.makeRect((int) (symbolBounds.left + width),
812                        (int) (symbolBounds.top - height),
813                        width,
814                        height);
815            }
816            else if (affiliation == 'H' || affiliation == 'S')//hostile,suspect
817            {
818                instRectangle = RectUtilities.makeRect((int) symbolBounds.left + width,
819                        Math.round((int) symbolBounds.top - (height * 0.15f)),
820                        width,
821                        height);
822            }
823            else if (affiliation == 'P'
824                    || affiliation == 'U'
825                    || affiliation == 'G'
826                    || affiliation == 'W')
827            {
828                instRectangle = RectUtilities.makeRect((int) symbolBounds.left + width,
829                        Math.round(symbolBounds.top - (height * 0.3f)),
830                        width,
831                        height);
832            }
833            else
834            {
835                instRectangle = RectUtilities.makeRect((int) symbolBounds.left + width,
836                        Math.round(symbolBounds.top - (height * 0.3f)),
837                        width,
838                        height);
839            }
840
841            //generate installation bounds//////////////////////////////
842            instBounds = new Rect(instRectangle.left + -1,
843                    instRectangle.top - 1,
844                    instRectangle.width() + 2,
845                    instRectangle.height() + 2);
846
847            imageBounds.union(instBounds);
848
849        }//*/
850        // </editor-fold>
851
852        // <editor-fold defaultstate="collapsed" desc="Build Engagement Bar (AO)">
853        //A:BBB-CC
854        String strAO = null;
855        Rect ebRectangle = null;
856        Rect ebBounds = null;
857        Rect ebTextBounds = null;
858        TextInfo ebText = null;
859
860        int ebTop = 0;
861        int ebLeft = 0;
862        int ebWidth = 0;
863        int ebHeight = 0;
864        Color ebColor = null;//SymbolUtilities.getFillColorOfAffiliation(symbolID);
865
866        if(attributes.containsKey(MilStdAttributes.EngagementBarColor))
867            ebColor = RendererUtilities.getColorFromHexString(attributes.get(MilStdAttributes.EngagementBarColor));
868        else
869            ebColor = fillColor;
870
871        if(SymbolUtilities.hasModifier(symbolID, Modifiers.AO_ENGAGEMENT_BAR) &&
872                modifiers.containsKey(Modifiers.AO_ENGAGEMENT_BAR))
873            strAO = modifiers.get(Modifiers.AO_ENGAGEMENT_BAR);
874        if(strAO != null)
875        {
876            ebText = new TextInfo(strAO, 0, 0, modifierFont, modifierFontName);
877            ebTextBounds = ebText.getTextBounds();
878            ebHeight = ebTextBounds.height() + 4;
879
880            int barOffset = Math.max(RendererSettings.getInstance().getDeviceDPI()/32, 4);
881
882            if(fdiBounds != null)//set bar above FDI if present
883            {
884                ebTop = fdiBounds.top - ebHeight - barOffset;
885            }
886            else if(tfBounds != null)//set bar above TF if present
887            {
888                ebTop = tfBounds.top - ebHeight - barOffset;
889            }
890            else if(echelonBounds != null)//set bar above echelon if present
891            {
892                ebTop = echelonBounds.top - ebHeight - barOffset;
893            }
894            else if((isCOnTop(symbolID) && modifiers.containsKey(Modifiers.C_QUANTITY)) ||
895                        SymbolID.getContext(symbolID) == SymbolID.StandardIdentity_Context_Exercise ||
896                        SymbolID.getContext(symbolID) == SymbolID.StandardIdentity_Context_Simulation)
897            {
898                ebTop = symbolBounds.top - (int)(ebHeight*2.5f);
899            }
900            else if(ss == SymbolID.SymbolSet_LandInstallation)
901            {
902                ebTop = symbolBounds.top - ebHeight - (barOffset * 2);
903            }
904            else//position above symbol
905            {
906                ebTop = symbolBounds.top - ebHeight - barOffset;
907            }
908
909            //if text wider than symbol, extend the bar.
910            if(ebTextBounds.width() > symbolBounds.width())
911            {
912                ebWidth = ebTextBounds.width() + 4;
913                ebLeft = symbolCenter.x - (ebWidth/2);
914            }
915            else
916            {
917                ebLeft = symbolBounds.left + (int)Math.ceil(strokeWidthBasedOnDPI/2f);//1;//leave room for outline
918                ebWidth = symbolBounds.width() - (int)Math.ceil(strokeWidthBasedOnDPI);//2;//leave room for outline
919            }
920
921            //set text location within the bar
922            ebText.setLocation(symbolCenter.x - (ebTextBounds.width()/2), ebTop + ebHeight - ((ebHeight - ebTextBounds.height()) / 2));
923
924            ebRectangle = RectUtilities.makeRect(ebLeft,ebTop,ebWidth,ebHeight);
925            ebBounds = new Rect(ebRectangle);
926            RectUtilities.grow(ebBounds,(int)Math.ceil(strokeWidthBasedOnDPI/2f));
927
928            imageBounds.union(ebBounds);
929        }
930
931
932        // </editor-fold>
933
934        // <editor-fold defaultstate="collapsed" desc="Build Affiliation Modifier">
935        String affiliationModifier = null;
936        if (RS.getDrawAffiliationModifierAsLabel() == false)
937        {
938            affiliationModifier = SymbolUtilities.getStandardIdentityModifier(symbolID);
939        }
940        if (affiliationModifier != null)
941        {
942
943            int amOffset = 2;
944            int outlineOffset = RS.getTextOutlineWidth();
945
946            tiAM = new TextInfo(affiliationModifier, 0, 0, modifierFont, modifierFontName);
947            amBounds = tiAM.getTextBounds();
948
949            int x, y;
950
951            if (echelonBounds != null
952                    && ((echelonBounds.left + echelonBounds.width() > symbolBounds.left + symbolBounds.width())))
953            {
954                y = Math.round(symbolBounds.top - amOffset);
955                x = echelonBounds.left + echelonBounds.width();
956            }
957            else
958            {
959                y = Math.round(symbolBounds.top - amOffset);
960                x = Math.round(symbolBounds.left + symbolBounds.width());
961            }
962            tiAM.setLocation(x, y);
963
964            //adjust for outline.
965            RectUtilities.grow(amBounds, outlineOffset);
966            RectUtilities.shift(amBounds, 0, -outlineOffset);
967            tiAM.setLocation(x, y - outlineOffset);
968
969            imageBounds.union(amBounds);
970        }
971        // </editor-fold>
972
973        // <editor-fold defaultstate="collapsed" desc="Build HQ Staff">
974        Point pt1HQ = null;
975        Point pt2HQ = null;
976        Rect hqBounds = null;
977        //Draw HQ Staff
978        if (SymbolUtilities.isHQ(symbolID))
979        {
980            int affiliation = SymbolID.getAffiliation(symbolID);
981            int context = SymbolID.getContext(symbolID);
982            //get points for the HQ staff
983            if (SymbolUtilities.hasRectangleFrame(symbolID))
984            {
985                pt1HQ = new Point((int) symbolBounds.left + 1,
986                        (int) (symbolBounds.top + symbolBounds.height() - 1));
987            }
988            else
989            {
990                pt1HQ = new Point((int) symbolBounds.left + 1,
991                        (int) (symbolBounds.top + (symbolBounds.height() / 2)));
992            }
993            pt2HQ = new Point((int) pt1HQ.x, (int) (pt1HQ.y + symbolBounds.height()));
994
995            //create bounding rectangle for HQ staff.
996            hqBounds = new Rect(pt1HQ.x, pt1HQ.y, pt1HQ.x + 2, pt2HQ.y);
997            //adjust the image bounds accordingly.
998            imageBounds.union(hqBounds);
999            //imageBounds.shiftBR(0,pt2HQ.y-imageBounds.bottom);
1000            //adjust symbol center
1001            centerPoint.set(pt2HQ.x, pt2HQ.y);
1002        }
1003
1004        // </editor-fold>
1005
1006        // <editor-fold defaultstate="collapsed" desc="Build DOM Arrow">
1007        Point[] domPoints = null;
1008        Rect domBounds = null;
1009        if (modifiers.containsKey(Modifiers.Q_DIRECTION_OF_MOVEMENT)
1010                && SymbolUtilities.hasModifier(symbolID, Modifiers.Q_DIRECTION_OF_MOVEMENT))
1011        {
1012                String strQ = modifiers.get(Modifiers.Q_DIRECTION_OF_MOVEMENT);
1013                
1014                if(strQ != null && SymbolUtilities.isNumber(strQ))
1015                {
1016                    float q = Float.valueOf(strQ);
1017        
1018                    boolean isY = (modifiers.containsKey(Modifiers.Y_LOCATION));
1019        
1020                    domPoints = createDOMArrowPoints(symbolID, symbolBounds, symbolCenter, q, isY, modifierFontHeight);
1021        
1022                    domBounds = new Rect(domPoints[0].x, domPoints[0].y, 1, 1);
1023        
1024                    Point temp = null;
1025                    for (int i = 1; i < 6; i++)
1026                    {
1027                        temp = domPoints[i];
1028                        if (temp != null)
1029                        {
1030                            domBounds.union(temp.x, temp.y);
1031                        }
1032                    }
1033                    imageBounds.union(domBounds);
1034                }
1035        }
1036
1037        // </editor-fold>
1038
1039        // <editor-fold defaultstate="collapsed" desc="Build Operational Condition Indicator">
1040        Rect ociBounds = null;
1041        RectF ociBoundsF = null;
1042        Rect ociShape = null;
1043        Path ociSlashShape = null;
1044        int ociOffset = Math.max(RendererSettings.getInstance().getDeviceDPI()/32, 4);
1045        if (SymbolUtilities.canSymbolHaveModifier(symbolID, Modifiers.AL_OPERATIONAL_CONDITION)) {
1046            if (mobilityBounds != null)
1047            {
1048                ociOffset = Math.round(mobilityBounds.bottom - symbolBounds.bottom) + 4;
1049            }
1050            if(RendererSettings.getInstance().getOperationalConditionModifierType() == RendererSettings.OperationalConditionModifierType_BAR)
1051            {
1052                ociShape = processOperationalConditionIndicator(symbolID, symbolBounds, ociOffset);
1053                if (ociShape != null)
1054                {
1055                    Rect temp = new Rect(ociShape);
1056                    RectUtilities.grow(temp, 2);
1057                    ociBounds = temp;
1058                    imageBounds.union(ociBounds);
1059                }
1060            }
1061            else//slash
1062            {
1063                ociSlashShape = processOperationalConditionIndicatorSlash(symbolID, symbolBounds);
1064                if (ociSlashShape != null)
1065                {
1066                    //build mobility bounds
1067                    ociBoundsF = new RectF();
1068                    ociBounds = new Rect();
1069                    ociSlashShape.computeBounds(ociBoundsF, true);
1070                    ociBoundsF.roundOut(ociBounds);
1071                    imageBounds.union(ociBounds);
1072                    ociBounds = null;
1073                }
1074            }
1075        }
1076
1077        // </editor-fold>
1078
1079        // <editor-fold defaultstate="collapsed" desc="Build Restricted Indicator">
1080        RectF rBounds = null;
1081        Path rPath = null;
1082        Path rPath2 = null;
1083        SVGPath rsvgPath = null;
1084        SVGPath rsvgPath2 = null;
1085        PointF rcirclePt = null;
1086        PointF rdotPt = null;
1087        float rdotRadius = 0;
1088        float rStrokeWidth = 3;
1089        if(SymbolID.getContext(symbolID) == SymbolID.StandardIdentity_Context_Restricted_Target_Reality)
1090        {
1091            // <path id="primary" d="M380,320l38,-67l40,67h-78m38,-11v-1m0,-10l0,-20" fill="yellow" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="7" />
1092            float nsTx = 0;
1093            float nsTy = 0;
1094            float ratio = 1;
1095            SVGInfo si = SVGLookup.getInstance().getSVGLInfo(SVGLookup.getFrameID(symbolID),SymbolID.getVersion(symbolID));
1096            if(symbolBounds.height() > symbolBounds.width())
1097            {
1098                double sHeight = si.getBbox().height();
1099                ratio = (float)(symbolBounds.height() / sHeight);
1100            }
1101            else
1102            {
1103                double sWidth = si.getBbox().width();
1104                ratio = (float)(symbolBounds.width() / sWidth);
1105            }
1106
1107            nsTx = (float)(si.getBbox().left * ratio) * -1;
1108            nsTy = (float)(si.getBbox().top * ratio) * -1;
1109
1110            //<path d="m373,313l53,-97l57,97l-110,0" fill="yellow" id="triangle" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="6"/>
1111            //<path d="m373,313L426,216L483,313L373,313" fill="yellow" id="triangle" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="6"/>
1112            rPath = new Path();//triangle
1113            rPath.moveTo(373f * ratio, 313f * ratio);
1114            rPath.lineTo(426f * ratio, 216f * ratio);
1115            rPath.lineTo(483f * ratio, 313f * ratio);
1116            rPath.lineTo(373f * ratio, 313f * ratio);
1117            rsvgPath = new SVGPath();//triangle
1118            rsvgPath.moveTo(373f * ratio, 313f * ratio);
1119            rsvgPath.lineTo(426f * ratio, 216f * ratio);
1120            rsvgPath.lineTo(483f * ratio, 313f * ratio);
1121            rsvgPath.lineTo(373f * ratio, 313f * ratio);
1122
1123            //<path d="M426.5,276L426.5,244" fill="none" id="line" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="10"/>
1124            rPath2 = new Path();//line
1125            rPath2.moveTo(426.5f * ratio, 276f * ratio);
1126            rPath2.lineTo(426.5f * ratio, 248f * ratio);
1127            rsvgPath2 = new SVGPath();//line
1128            rsvgPath2.moveTo(426.5f * ratio, 276f * ratio);
1129            rsvgPath2.lineTo(426.5f * ratio, 248f * ratio);
1130
1131            //<circle cx="426.5" cy="293" r="6" id="dot"/>//DOT
1132            rdotPt = new PointF(426.5f * ratio, 293 * ratio);
1133            rdotRadius = 5f * ratio;
1134
1135            //need to shift like we do the frame and main icons since it's based in that space
1136            rPath.offset(nsTx, nsTy);
1137            rPath2.offset(nsTx, nsTy);
1138            rsvgPath.shift(nsTx,nsTy);
1139            rsvgPath2.shift(nsTx,nsTy);
1140            rdotPt.offset(nsTx,nsTy);
1141            //rCircle = (Ellipse2D) txfm.createTransformedShape(rCircle);
1142
1143
1144            //RectF bounds = new RectF();
1145            //bounds = rPath.computeBounds(bounds);  //getBounds();//triangle bounds
1146            Rect bounds = rsvgPath.getBounds();
1147            rBounds = RectUtilities.makeRectF(bounds.left,bounds.top,bounds.width(), bounds.height());
1148            rStrokeWidth = (2/66.666667f) * ((float)symbolBounds.height() / SymbolUtilities.getUnitRatioHeight(symbolID));
1149            RectUtilities.grow(rBounds,(int)Math.ceil(rStrokeWidth/2));
1150            RectUtilities.grow(bounds,(int)Math.ceil(rStrokeWidth/2));
1151            imageBounds.union(bounds);
1152        }
1153        // </editor-fold>
1154
1155        // <editor-fold defaultstate="collapsed" desc="Build No Strike Indicator">
1156        RectF nsBounds = null;
1157        PointF nsCirclePt = null;
1158        float nsRadius = 0;
1159        Path nsLine = null;
1160        SVGPath nssvgLine = null;
1161        double nsStrokeWidth = 3;
1162        if(SymbolID.getContext(symbolID) == SymbolID.StandardIdentity_Context_No_Strike_Entity_Reality)
1163        {
1164            //octagon~182.08058166503906~272.0794677734375~245.8407440185547~244.85235595703125
1165            //restricted~375.44801678047673~248.63298320770264~85.1039714496415~79.36734275822477
1166            //no-strike~378.0~248.0~80.0~80.0
1167            //<circle cx="418" cy="288" fill="yellow" r="36" stroke="black" stroke-width="8"/>
1168            //<line fill="none" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="8" x1="390" x2="446" y1="265" y2="310"/>
1169            //nsCircle = new Ellipse(x,y,radius * 2, radius * 2);
1170            //nsLine = new Line(390 * ratio, 265 * ratio, 446 * ratio, 310 * ratio);
1171            float nsTx = 0;
1172            float nsTy = 0;
1173            float ratio = 1;
1174            SVGInfo si = SVGLookup.getInstance().getSVGLInfo(SVGLookup.getFrameID(symbolID),SymbolID.getVersion(symbolID));
1175            if(symbolBounds.height() > symbolBounds.width())
1176            {
1177                float sHeight = si.getBbox().height();
1178                ratio = symbolBounds.height() / sHeight;
1179            }
1180            else
1181            {
1182                float sWidth = si.getBbox().width();
1183                ratio = symbolBounds.width() / sWidth;
1184            }
1185
1186            nsTx = (si.getBbox().left * ratio) * -1;
1187            nsTy = (si.getBbox().top * ratio) * -1;
1188
1189            float radius = 50f * ratio;
1190            float x = 426f * ratio;
1191            float y = 267f * ratio;
1192            nsCirclePt = new PointF(x,y);
1193            nsRadius = radius;
1194            nsLine = new Path();
1195            nsLine.moveTo(390 * ratio, 235 * ratio);
1196            nsLine.lineTo(463 * ratio, 298 * ratio);
1197            nssvgLine = new SVGPath();
1198            nssvgLine.moveTo(390 * ratio, 235 * ratio);
1199            nssvgLine.lineTo(463 * ratio, 298 * ratio);
1200
1201            //need to shift like we do the frame and main icons since it's based in that space
1202            nsCirclePt.offset(nsTx,nsTy);
1203            nsLine.offset(nsTx,nsTy);
1204            nssvgLine.shift(nsTx,nsTy);
1205
1206            nsBounds = RectUtilities.makeRectF(nsCirclePt.x - radius, nsCirclePt.y - radius, radius * 2, radius * 2);
1207
1208            nsStrokeWidth = (2/66.666667) * (symbolBounds.height() / SymbolUtilities.getUnitRatioHeight(symbolID));
1209            RectUtilities.grow(nsBounds,(int)Math.ceil(nsStrokeWidth/2));
1210            imageBounds.union(RectUtilities.makeRectFromRectF(nsBounds));
1211        }
1212        // </editor-fold>
1213
1214        // <editor-fold defaultstate="collapsed" desc="Shift Modifiers">
1215        //adjust points if necessary
1216        if (sdi instanceof ImageInfo && (imageBounds.left < 0 || imageBounds.top < 0))
1217        {
1218            int shiftX = Math.abs(imageBounds.left);
1219            int shiftY = Math.abs(imageBounds.top);
1220
1221            if (hqBounds != null)
1222            {
1223                pt1HQ.offset(shiftX, shiftY);
1224                pt2HQ.offset(shiftX, shiftY);
1225            }
1226            if (echelonBounds != null)
1227            {
1228                tiEchelon.setLocation(tiEchelon.getLocation().x + shiftX, tiEchelon.getLocation().y + shiftY);
1229            }
1230            if (amBounds != null)
1231            {
1232                tiAM.setLocation(tiAM.getLocation().x + shiftX, tiAM.getLocation().y + shiftY);
1233            }
1234            if (tfBounds != null)
1235            {
1236                tfRectangle.offset(shiftX, shiftY);
1237                tfBounds.offset(shiftX, shiftY);
1238            }
1239            if(ebBounds != null)
1240            {
1241                ebRectangle.offset(shiftX, shiftY);
1242                ebBounds.offset(shiftX, shiftY);
1243                ebText.shift(shiftX, shiftY);
1244                ebTextBounds.offset(shiftX, shiftY);
1245            }
1246            /*if (instBounds != null)//part of symbol bounds now
1247            {
1248                instRectangle.offset(shiftX, shiftY);
1249                instBounds.offset(shiftX, shiftY);
1250            }//*/
1251            if (fdiBounds != null)
1252            {
1253                fdiBounds.offset(shiftX, shiftY);
1254                fdiLeft.offset(shiftX, shiftY);
1255                fdiTop.offset(shiftX, shiftY);
1256                fdiRight.offset(shiftX, shiftY);
1257            }
1258            if (liBounds != null)
1259            {
1260                liBounds.offset(shiftX, shiftY);
1261                liLeft.offset(shiftX, shiftY);
1262                liTop.offset(shiftX, shiftY);
1263                liRight.offset(shiftX, shiftY);
1264                if(liPath != null)
1265                {
1266                    liPath.offset(shiftX,shiftY);
1267                }
1268            }
1269            if (ociBounds != null)
1270            {
1271                ociBounds.offset(shiftX, shiftY);
1272                ociShape.offset(shiftX, shiftY);
1273            }
1274            if(ociBoundsF != null)
1275            {
1276                ociBoundsF.offset(shiftX, shiftY);
1277                ociSlashShape.offset(shiftX, shiftY);
1278            }
1279            if(rBounds != null)
1280            {
1281                rBounds.offset(shiftX, shiftY);//bounds
1282                rPath.offset(shiftX, shiftY);//triangle
1283                rPath2.offset(shiftX, shiftY);//exclamation
1284                rdotPt.offset(shiftX, shiftY);//dot
1285            }
1286            if(nsBounds != null)
1287            {
1288                nsBounds.offset(shiftX, shiftY);//bounds
1289                nsCirclePt.offset(shiftX, shiftY);//circle
1290                nsLine.offset(shiftX, shiftY);//line
1291            }
1292            if (domBounds != null)
1293            {
1294                for (int i = 0; i < 6; i++)
1295                {
1296                    Point temp = domPoints[i];
1297                    if (temp != null)
1298                    {
1299                        temp.offset(shiftX, shiftY);
1300                    }
1301                }
1302                domBounds.offset(shiftX, shiftY);
1303            }
1304            if (mobilityBounds != null)
1305            {
1306                //shift mobility points
1307                mobilityPath.offset(shiftX, shiftY);
1308                if (mobilityPathFill != null)
1309                {
1310                    mobilityPathFill.offset(shiftX, shiftY);
1311                }
1312
1313                mobilityBounds.offset(shiftX, shiftY);
1314            }
1315
1316            centerPoint.offset(shiftX, shiftY);
1317            symbolBounds.offset(shiftX, shiftY);
1318            imageBounds.offset(shiftX, shiftY);
1319        }
1320        // </editor-fold>
1321
1322        // <editor-fold defaultstate="collapsed" desc="Convert to SVG (SVGSymbolInfo)">
1323        if(sdi instanceof SVGSymbolInfo)
1324        {
1325            StringBuilder sbSVG = new StringBuilder();
1326            Path temp = null;
1327            SVGPath svgtemp = null;
1328            String svgStroke = RendererUtilities.colorToHexString(lineColor,false);
1329            String svgFill = RendererUtilities.colorToHexString(fillColor,false);
1330            String svgTextColor = RendererUtilities.colorToHexString(textColor,false);
1331            String svgTextBGColor = RendererUtilities.colorToHexString(textBackgroundColor,false);
1332            String svgStrokeWidth = String.valueOf(strokeWidthBasedOnDPI);
1333            String svgTextOutlineWidth = String.valueOf(RendererSettings.getInstance().getTextOutlineWidth());
1334            String svgAlpha = "1";
1335            if(alpha >= 0 && alpha <= 1)
1336                svgAlpha = String.valueOf(alpha);
1337            String svgDashArray = null;
1338
1339            if(hqBounds != null)
1340            {
1341                /*Line2D hqStaff = new Line2D.Double(pt1HQ,pt2HQ);
1342                temp = new Path2D.Double();
1343                temp.append(hqStaff,false);
1344                sbSVG.append(Shape2SVG.Convert(temp, svgStroke, null, svgStrokeWidth, svgAlpha, svgAlpha, null));//*/
1345
1346                svgtemp = new SVGPath();
1347                svgtemp.moveTo(pt1HQ.x, pt1HQ.y);
1348                svgtemp.lineTo(pt2HQ.x, pt2HQ.y);
1349                svgtemp.toSVGElement(svgStroke,Float.parseFloat(svgStrokeWidth),null,Float.parseFloat(svgAlpha),Float.parseFloat(svgAlpha),null);
1350            }
1351            if (echelonBounds != null)
1352            {
1353                sbSVG.append(Shape2SVG.Convert(tiEchelon, svgTextBGColor, svgTextColor, svgTextOutlineWidth, svgAlpha, svgAlpha, null));
1354            }
1355            if (amBounds != null)
1356            {
1357                sbSVG.append(Shape2SVG.Convert(tiAM, svgTextBGColor, svgTextColor, svgTextOutlineWidth, svgAlpha, svgAlpha, null));
1358            }
1359            if (tfBounds != null)
1360            {
1361                sbSVG.append(Shape2SVG.Convert(tfRectangle, svgStroke, null, svgStrokeWidth, svgAlpha, svgAlpha, null,null));
1362            }
1363            if(ebBounds != null)
1364            {
1365                String svgEBFill = RendererUtilities.colorToHexString(ebColor,false);
1366                //create fill and outline
1367                sbSVG.append(Shape2SVG.Convert(ebRectangle, svgStroke, svgEBFill, svgStrokeWidth, svgAlpha, svgAlpha, null,null));
1368                //create internal text
1369                sbSVG.append(Shape2SVG.Convert(ebText, null, "#000000", null, svgAlpha, svgAlpha, null));
1370            }
1371            if (fdiBounds != null)
1372            {
1373                /*int dpi = RendererSettings.getInstance().getDeviceDPI();
1374                int lineLength = dpi / 96 * 6;
1375                int lineGap = dpi / 96 * 4;
1376                String svgFDIDashArray = "" + lineLength + " " + lineGap;//*/
1377
1378                /// ///////////////////////////////////
1379                //Divide line in 14 parts. line is 3 parts to 2 parts gap
1380                float distance = RendererUtilities.getDistanceBetweenPoints(fdiTop,fdiLeft);
1381                //distance = distance / 14f;
1382                int lineGap = (int)((distance / 14f) * 2);
1383                int lineLength = (int)((distance / 14f) * 3);
1384                String svgFDIDashArray = "" + lineLength + " " + lineGap;
1385                /// //////////////////////////////////
1386
1387                SVGPath fdiPath = new SVGPath();
1388
1389                fdiPath.moveTo(fdiTop.x, fdiTop.y);
1390                fdiPath.lineTo(fdiLeft.x, fdiLeft.y);
1391                fdiPath.moveTo(fdiTop.x, fdiTop.y);
1392                fdiPath.lineTo(fdiRight.x, fdiRight.y);//*/
1393
1394                sbSVG.append(Shape2SVG.Convert(fdiPath, svgStroke, null, svgStrokeWidth, svgAlpha, svgAlpha, svgFDIDashArray,"round"));
1395
1396            }
1397            if (liBounds != null)
1398            {
1399                SVGPath svgliPath = new SVGPath();
1400                svgliPath.moveTo(liTop.x, liTop.y);
1401                svgliPath.lineTo(liLeft.x, liLeft.y);
1402                svgliPath.moveTo(liTop.x, liTop.y);
1403                svgliPath.lineTo(liRight.x, liRight.y);
1404
1405                sbSVG.append(svgliPath.toSVGElement(svgStroke,strokeWidthBasedOnDPI,null,Float.parseFloat(svgAlpha),Float.parseFloat(svgAlpha),"round"));
1406                //sbSVG.append(Shape2SVG.Convert(liPath, svgStroke, null, String.valueOf(liStrokeWidth), svgAlpha, svgAlpha, null));
1407            }
1408            if (ociBounds != null && ociShape != null)
1409            {
1410
1411                int status = SymbolID.getStatus(symbolID);
1412                Color statusColor = null;
1413
1414                switch (status) {
1415                    //Fully Capable
1416                    case SymbolID.Status_Present_FullyCapable:
1417                        statusColor = Color.green;
1418                        break;
1419                    //Damaged
1420                    case SymbolID.Status_Present_Damaged:
1421                        statusColor = Color.yellow;
1422                        break;
1423                    //Destroyed
1424                    case SymbolID.Status_Present_Destroyed:
1425                        statusColor = Color.red;
1426                        break;
1427                    //full to capacity(hospital)
1428                    case SymbolID.Status_Present_FullToCapacity:
1429                        statusColor = Color.blue;
1430                        break;
1431                    default:
1432                        break;
1433                }
1434
1435                String svgOCIStatusColor = RendererUtilities.colorToHexString(statusColor,false);
1436                sbSVG.append(Shape2SVG.Convert(ociBounds, null, svgStroke, svgStrokeWidth, svgAlpha, svgAlpha, null,null));
1437                sbSVG.append(Shape2SVG.Convert(ociShape, null, svgOCIStatusColor, svgStrokeWidth, svgAlpha, svgAlpha, null,null));
1438
1439                ociBounds = null;
1440                ociShape = null;
1441
1442            }
1443
1444            if (mobilityBounds != null)
1445            {
1446                if(svgMobilityGroup != null)
1447                    sbSVG.append(svgMobilityGroup);
1448                else if (svgMobilityPath != null)
1449                    sbSVG.append(svgMobilityPath.toSVGElement(svgStroke,strokeWidthBasedOnDPI,null,Float.parseFloat(svgAlpha),Float.parseFloat(svgAlpha),null));
1450
1451                mobilityBounds = null;
1452            }
1453
1454            //add symbol
1455            ssi = (SVGSymbolInfo)sdi;
1456            sbSVG.append(ssi.getSVG());
1457
1458            if (ociBounds != null && ociSlashShape != null)
1459            {
1460                SVGPath svgociSlash = processOperationalConditionIndicatorSlashSVG(symbolID,symbolBounds);
1461
1462                double size = symbolBounds.width();
1463                float ociStrokeWidth = 3f;
1464
1465                ociStrokeWidth = (float) size / 20f;
1466                if (ociStrokeWidth < 1f)
1467                    ociStrokeWidth = 1f;
1468
1469                sbSVG.append(svgociSlash.toSVGElement(svgStroke,ociStrokeWidth,null,Float.parseFloat(svgAlpha),Float.parseFloat(svgAlpha),null));
1470                //sbSVG.append(Shape2SVG.Convert(ociSlashShape, svgStroke, null, String.valueOf(ociStrokeWidth), svgAlpha, svgAlpha, null));
1471                ociBounds = null;
1472                ociSlashShape = null;
1473            }
1474
1475            if(rBounds != null)
1476            {
1477                String restrictedGroup = "<g id=\"restricted\" stroke-linecap=\"round\" stroke-linejoin=\"round\">";
1478                //triangle
1479                restrictedGroup += Shape2SVG.Convert(rsvgPath, "#000000", "#FFFF00", String.valueOf(rStrokeWidth),svgAlpha,svgAlpha,null,null);
1480                //exclamation
1481                restrictedGroup += Shape2SVG.Convert(rsvgPath2, "#000000", null, String.valueOf(rStrokeWidth * 1.66667),svgAlpha,svgAlpha,null,null);
1482                //dot
1483                restrictedGroup += Shape2SVG.ConvertCircle(rdotPt, rdotRadius, "#000000", "#000000", String.valueOf(rStrokeWidth),svgAlpha,svgAlpha,null);
1484                restrictedGroup += "</g>";
1485
1486                sbSVG.append(restrictedGroup);
1487            }
1488
1489            if(nsBounds != null)
1490            {
1491                String noStrikeGroup = "<g id=\"nostrike\">";
1492                noStrikeGroup += Shape2SVG.ConvertCircle(nsCirclePt, nsRadius,"#000000", "#FFFF00", String.valueOf(nsStrokeWidth),svgAlpha,svgAlpha,null);
1493                noStrikeGroup += Shape2SVG.Convert(nssvgLine, "#000000", null, String.valueOf(nsStrokeWidth),svgAlpha,svgAlpha,null,null);
1494                noStrikeGroup += "</g>";
1495                sbSVG.append(noStrikeGroup);
1496            }
1497
1498            if (domBounds != null)
1499            {
1500                //Path2D domPath = new Path2D.Double();
1501                SVGPath domPath = new SVGPath();
1502
1503                domPath.moveTo(domPoints[0].x, domPoints[0].y);
1504                if (domPoints[1] != null)
1505                {
1506                    domPath.lineTo(domPoints[1].x, domPoints[1].y);
1507                }
1508                if (domPoints[2] != null)
1509                {
1510                    domPath.lineTo(domPoints[2].x, domPoints[2].y);
1511                }
1512                //sbSVG.append(Shape2SVG.Convert(domPath, svgStroke, null, svgStrokeWidth, svgAlpha, svgAlpha, null));
1513                sbSVG.append(domPath.toSVGElement(svgStroke, Float.parseFloat(svgStrokeWidth), null,Float.parseFloat(svgAlpha), Float.parseFloat(svgAlpha),null));
1514
1515
1516                //domPath.reset();
1517                domPath = new SVGPath();
1518
1519                domPath.moveTo(domPoints[3].x, domPoints[3].y);
1520                domPath.lineTo(domPoints[4].x, domPoints[4].y);
1521                domPath.lineTo(domPoints[5].x, domPoints[5].y);
1522                sbSVG.append(Shape2SVG.Convert(domPath, "none", svgStroke, "0", svgAlpha, svgAlpha, null,null));
1523                sbSVG.append(domPath.toSVGElement("none", 0f, svgStroke,Float.parseFloat(svgAlpha), Float.parseFloat(svgAlpha),null));
1524
1525                domBounds = null;
1526                domPoints = null;
1527            }
1528
1529            newsdi = new SVGSymbolInfo(sbSVG.toString(),centerPoint,symbolBounds,imageBounds);
1530        }
1531
1532        // </editor-fold>
1533
1534        // <editor-fold defaultstate="collapsed" desc="Draw Modifiers (ImageInfo)">
1535        if(sdi instanceof ImageInfo)
1536        {
1537            ii = (ImageInfo) sdi;
1538
1539            Bitmap bmp = Bitmap.createBitmap(imageBounds.width(), imageBounds.height(), Config.ARGB_8888);
1540            Canvas ctx = new Canvas(bmp);
1541
1542            if (echelonBounds != null || amBounds != null) {
1543                //   ctx.font = RendererSettings.getModifierFont();
1544            }
1545
1546            //render////////////////////////////////////////////////////////
1547            Paint paint = new Paint();
1548            paint.setStyle(Style.STROKE);
1549            //paint.setColor(Color.black.toInt());
1550            paint.setColor(lineColor.toInt());
1551            if (alpha > -1)
1552                paint.setAlpha(alpha);
1553            paint.setStrokeWidth(2.0f);
1554
1555            paint.setStrokeWidth(strokeWidthBasedOnDPI);
1556
1557            if (hqBounds != null) {
1558                ctx.drawLine(pt1HQ.x, pt1HQ.y, pt2HQ.x, pt2HQ.y, paint);
1559            }
1560
1561            if (tfBounds != null) {
1562                ctx.drawRect(tfRectangle, paint);
1563            }
1564
1565        /*if (instBounds != null) Part of frame SVG now
1566        {
1567            paint.setStyle(Style.FILL);
1568            ctx.drawRect(instRectangle, paint);
1569        }//*/
1570
1571            if (ebBounds != null) {
1572                //draw bar fill
1573                paint.setStyle(Style.FILL);
1574                paint.setColor(ebColor.toInt());
1575                ctx.drawRect(ebRectangle, paint);
1576
1577                //draw bar outline
1578                paint.setStyle(Style.STROKE);
1579                paint.setStrokeWidth(4.0f);
1580                paint.setColor(lineColor.toInt());
1581                ctx.drawRect(ebRectangle, paint);
1582
1583                //draw bar text
1584                modifierFont.setColor(Color.BLACK.toInt());
1585                modifierFont.setStyle(Style.FILL);
1586                ctx.drawText(ebText.getText(), ebText.getLocation().x, ebText.getLocation().y, modifierFont);
1587
1588                ebBounds = null;
1589                ebText = null;
1590                ebRectangle = null;
1591                paint.setStrokeWidth(strokeWidthBasedOnDPI);//2.0f
1592            }
1593
1594            if (echelonBounds != null) {
1595                TextInfo[] aTiEchelon =
1596                        {
1597                                tiEchelon
1598                        };
1599                renderText(ctx, aTiEchelon, textColor, textBackgroundColor, modifierFont);
1600
1601                echelonBounds = null;
1602                tiEchelon = null;
1603            }
1604
1605            if (amBounds != null) {
1606                TextInfo[] aTiAM =
1607                        {
1608                                tiAM
1609                        };
1610                renderText(ctx, aTiAM, textColor, textBackgroundColor, modifierFont);
1611                amBounds = null;
1612                tiAM = null;
1613            }
1614
1615            if (fdiBounds != null) {
1616
1617                Paint fdiPaint = new Paint();
1618                fdiPaint.setAntiAlias(true);
1619                fdiPaint.setColor(lineColor.toInt());/// setARGB(255, 0, 0, 0);
1620                if (alpha > -1)
1621                    fdiPaint.setAlpha(alpha);
1622                fdiPaint.setStyle(Style.STROKE);
1623
1624                /*int dpi = RendererSettings.getInstance().getDeviceDPI();
1625
1626                int lineLength = dpi / 96 * 6;
1627                int lineGap = dpi / 96 * 4;//*/
1628
1629                /// ///////////////////////////////////
1630                //Divide line in 14 parts. line is 3 parts to 2 parts gap
1631                float distance = RendererUtilities.getDistanceBetweenPoints(fdiTop,fdiLeft);
1632                //distance = distance / 14f;
1633                int lineGap = (int)((distance / 14f) * 2);
1634                int lineLength = (int)((distance / 14f) * 3);
1635                /// //////////////////////////////////
1636
1637                fdiPaint.setPathEffect(new DashPathEffect(new float[]
1638                        {
1639                                lineLength, lineGap
1640                        }, 0));
1641
1642
1643                fdiPaint.setStrokeCap(Cap.ROUND);
1644                fdiPaint.setStrokeJoin(Join.MITER);
1645                fdiPaint.setStrokeWidth(strokeWidthBasedOnDPI);
1646
1647                Path fdiPath = new Path();
1648
1649                fdiPath.moveTo(fdiTop.x, fdiTop.y);
1650                fdiPath.lineTo(fdiLeft.x, fdiLeft.y);
1651                fdiPath.moveTo(fdiTop.x, fdiTop.y);
1652                fdiPath.lineTo(fdiRight.x, fdiRight.y);
1653                ctx.drawPath(fdiPath, fdiPaint);
1654
1655                fdiBounds = null;
1656
1657            }
1658
1659            if (liBounds != null) {
1660
1661                Paint liPaint = new Paint();
1662                liPaint.setAntiAlias(true);
1663                liPaint.setColor(lineColor.toInt());/// setARGB(255, 0, 0, 0);
1664                if (alpha > -1)
1665                    liPaint.setAlpha(alpha);
1666                liPaint.setStyle(Style.STROKE);
1667
1668                int dpi = RendererSettings.getInstance().getDeviceDPI();
1669
1670                liPaint.setStrokeCap(Cap.BUTT);
1671                liPaint.setStrokeJoin(Join.MITER);
1672                liPaint.setStrokeWidth(strokeWidthBasedOnDPI);
1673
1674                ctx.drawPath(liPath, liPaint);
1675
1676                liBounds = null;
1677
1678            }
1679
1680            if (mobilityBounds != null) {
1681                Paint mobilityPaint = new Paint();
1682                mobilityPaint.setStyle(Style.STROKE);
1683                //mobilityPaint.setColor(Color.black.toInt());
1684                mobilityPaint.setColor(lineColor.toInt());
1685                if (alpha > -1)
1686                    mobilityPaint.setAlpha(alpha);
1687
1688                //ctx.lineCap = "butt";
1689                //ctx.lineJoin = "miter";
1690                if (ad >= SymbolID.Mobility_WheeledLimitedCrossCountry && ad < SymbolID.Mobility_ShortTowedArray)//mobility
1691                {
1692                    //mobilityPaint.setStrokeWidth(3f);
1693                    mobilityPaint.setStrokeWidth(strokeWidthBasedOnDPI);
1694                    mobilityPaint.setAntiAlias(true);
1695                } else //towed-array
1696                {
1697                    //mobilityPaint.setStrokeWidth(3f);
1698                    mobilityPaint.setStrokeWidth(strokeWidthBasedOnDPI);
1699                    //mobilityPaint.setAntiAlias(true);
1700                }
1701
1702                ctx.drawPath(mobilityPath, mobilityPaint);
1703
1704                if (mobilityPathFill != null) {
1705                    mobilityPaint.setStyle(Style.FILL);
1706                    ctx.drawPath(mobilityPathFill, mobilityPaint);
1707                }
1708
1709                mobilityBounds = null;
1710
1711            }
1712
1713            if (ociBounds != null) {
1714                Paint ociPaint = new Paint();
1715
1716                int statusColor = 0;
1717                int status = SymbolID.getStatus(symbolID);
1718                if (status == (SymbolID.Status_Present_FullyCapable))//Fully Capable
1719                {
1720                    statusColor = Color.green.toInt();
1721                } else if (status == (SymbolID.Status_Present_Damaged))//Damage
1722                {
1723                    statusColor = Color.yellow.toInt();
1724                } else if (status == (SymbolID.Status_Present_Destroyed)) {
1725                    statusColor = Color.red.toInt();
1726                } else if (status == (SymbolID.Status_Present_FullToCapacity))//full to capacity(hospital)
1727                {
1728                    statusColor = Color.blue.toInt();
1729                }
1730
1731                ociPaint.setColor(lineColor.toInt());
1732                ociPaint.setStyle(Style.FILL);
1733
1734                if (alpha > -1)
1735                    ociPaint.setAlpha(alpha);
1736                ctx.drawRect(ociBounds, ociPaint);
1737                ociPaint.setColor(statusColor);
1738                if (alpha > -1)
1739                    ociPaint.setAlpha(alpha);
1740                ctx.drawRect(ociShape, ociPaint);
1741
1742                ociBounds = null;
1743                ociShape = null;
1744            }
1745
1746            //draw original icon.
1747            //ctx.drawImage(ii.getImage(),symbolBounds.left, symbolBounds.top);
1748            ctx.drawBitmap(ii.getImage(), null, symbolBounds, null);
1749
1750            if(rBounds != null)
1751            {
1752                Paint rPaint = new Paint();
1753                rPaint.setColor(Color.YELLOW.toInt());
1754                rPaint.setAlpha(alpha);
1755                rPaint.setStrokeCap(Cap.ROUND);
1756                rPaint.setStrokeJoin(Join.ROUND);
1757                rPaint.setStyle(Style.FILL);
1758                //triangle fill
1759                ctx.drawPath(rPath, rPaint);
1760
1761                //triangle outline
1762                rPaint.setStrokeWidth(rStrokeWidth);
1763                rPaint.setStyle(Style.STROKE);
1764                rPaint.setColor(Color.BLACK.toInt());
1765                ctx.drawPath(rPath, rPaint);
1766
1767                //exclamation line
1768                rPaint.setStrokeWidth(rStrokeWidth * 1.66667f);
1769                ctx.drawPath(rPath2, rPaint);
1770
1771                //exclamation dot
1772                rPaint.setStrokeWidth(rStrokeWidth);
1773                rPaint.setStyle(Style.FILL_AND_STROKE);
1774                ctx.drawCircle(rdotPt.x,rdotPt.y,rdotRadius,rPaint);
1775
1776            }
1777            if(nsBounds != null)
1778            {
1779                Paint nsPaint = new Paint();
1780                nsPaint.setColor(Color.YELLOW.toInt());
1781                nsPaint.setAlpha(alpha);
1782                nsPaint.setStrokeCap(Cap.ROUND);
1783                nsPaint.setStrokeJoin(Join.ROUND);
1784                nsPaint.setStyle(Style.FILL);
1785
1786                //circle fill
1787                ctx.drawCircle(nsCirclePt.x, nsCirclePt.y,nsRadius,nsPaint);
1788
1789                //circle outline
1790                nsPaint.setStyle(Style.STROKE);
1791                nsPaint.setColor(Color.BLACK.toInt());
1792                nsPaint.setStrokeWidth((float)nsStrokeWidth);
1793                ctx.drawCircle(nsCirclePt.x,nsCirclePt.y,nsRadius,nsPaint);
1794
1795                //draw slash
1796                ctx.drawPath(nsLine,nsPaint);
1797
1798            }
1799
1800            if (domBounds != null) {
1801                drawDOMArrow(ctx, domPoints, alpha, lineColor);
1802
1803                domBounds = null;
1804                domPoints = null;
1805            }
1806
1807            if (ociBoundsF != null) {
1808                Paint ociPaint = new Paint();
1809                int size = symbolBounds.width();
1810                float ociStrokeWidth = 3f;
1811
1812                ociStrokeWidth = size / 20f;
1813                if (ociStrokeWidth < 1f)
1814                    ociStrokeWidth = 1f;
1815            /*if(size > 50 && size < 100)
1816                ociStrokeWidth = 5f;
1817            else if(size >= 100 && size < 200)
1818                ociStrokeWidth = 7f;
1819            else if(size >= 200)
1820                ociStrokeWidth = 10f;*/
1821                //ociPaint.setColor(Color.black.toInt());
1822                ociPaint.setColor(lineColor.toInt());
1823                if (alpha > -1)
1824                    ociPaint.setAlpha(alpha);
1825                ociPaint.setStrokeWidth(ociStrokeWidth);
1826                ociPaint.setStrokeCap(Cap.BUTT);
1827                ociPaint.setStyle(Style.STROKE);
1828                ociPaint.setAntiAlias(true);
1829                ctx.drawPath(ociSlashShape, ociPaint);
1830
1831                ociBoundsF = null;
1832                ociSlashShape = null;
1833            }
1834
1835
1836            if (bmp != null)
1837                newsdi = new ImageInfo(bmp, centerPoint, symbolBounds);
1838        }
1839        // </editor-fold>
1840
1841        // <editor-fold defaultstate="collapsed" desc="Cleanup">
1842        // </editor-fold>
1843        if (newsdi != null)
1844        {
1845            return newsdi;
1846        }
1847        else
1848        {
1849            return null;
1850        }
1851
1852    }
1853
1854    /**
1855     *
1856     * @param symbolID
1857     * @return
1858     * @deprecated no longer a thing in 2525D
1859     * TODO: remove
1860     */
1861    private static double getYPositionForSCC(String symbolID)
1862    {
1863        double yPosition = 0.32;
1864        /*int aff = SymbolID.getAffiliation(symbolID);
1865        int context = SymbolID.getContext(symbolID);
1866        char affiliation = symbolID.charAt(1);
1867
1868        if(temp.equals("WMGC--"))//GROUND (BOTTOM) MILCO
1869        {
1870            if(affiliation == 'H' || 
1871                    affiliation == 'S')//suspect
1872                yPosition = 0.29;
1873            else if(affiliation == 'N' ||
1874                    affiliation == 'L')//exercise neutral
1875                yPosition = 0.32;
1876            else if(affiliation == 'F' ||
1877                    affiliation == 'A' ||//assumed friend
1878                    affiliation == 'D' ||//exercise friend
1879                    affiliation == 'M' ||//exercise assumed friend
1880                    affiliation == 'K' ||//faker
1881                    affiliation == 'J')//joker
1882                yPosition = 0.32;
1883            else
1884                yPosition = 0.34;
1885        }
1886        else if(temp.equals("WMMC--"))//MOORED MILCO
1887        {
1888            if(affiliation == 'H' || 
1889                    affiliation == 'S')//suspect
1890                yPosition = 0.25;
1891            else if(affiliation == 'N' ||
1892                    affiliation == 'L')//exercise neutral
1893                yPosition = 0.25;
1894            else if(affiliation == 'F' ||
1895                    affiliation == 'A' ||//assumed friend
1896                    affiliation == 'D' ||//exercise friend
1897                    affiliation == 'M' ||//exercise assumed friend
1898                    affiliation == 'K' ||//faker
1899                    affiliation == 'J')//joker
1900                yPosition = 0.25;
1901            else
1902                yPosition = 0.28;
1903        }
1904        else if(temp.equals("WMFC--"))//FLOATING MILCO
1905        {
1906            if(affiliation == 'H' || 
1907                    affiliation == 'S')//suspect
1908                yPosition = 0.29;
1909            else if(affiliation == 'N' ||
1910                    affiliation == 'L')//exercise neutral
1911                yPosition = 0.32;
1912            else if(affiliation == 'F' ||
1913                    affiliation == 'A' ||//assumed friend
1914                    affiliation == 'D' ||//exercise friend
1915                    affiliation == 'M' ||//exercise assumed friend
1916                    affiliation == 'K' ||//faker
1917                    affiliation == 'J')//joker
1918                yPosition = 0.32;
1919            else
1920                yPosition= 0.34;
1921        }
1922        else if(temp.equals("WMC---"))//GENERAL MILCO
1923        {
1924            if(affiliation == 'H' || 
1925                    affiliation == 'S')//suspect
1926                yPosition = 0.33;
1927            else if(affiliation == 'N' ||
1928                    affiliation == 'L')//exercise neutral
1929                yPosition = 0.36;
1930            else if(affiliation == 'F' ||
1931                    affiliation == 'A' ||//assumed friend
1932                    affiliation == 'D' ||//exercise friend
1933                    affiliation == 'M' ||//exercise assumed friend
1934                    affiliation == 'K' ||//faker
1935                    affiliation == 'J')//joker
1936                yPosition = 0.36;
1937            else
1938                yPosition = 0.36;
1939        }*/
1940        
1941        return yPosition;
1942    }
1943
1944    /**
1945     *
1946     * @param {type} symbolID
1947     * @param {type} bounds symbolBounds SO.Rectangle
1948     * @param {type} center SO.Point Location where symbol is centered.
1949     * @param {type} angle in degrees
1950     * @param {Boolean} isY Boolean.
1951     * @returns {Array} of SO.Point. First 3 items are the line. Last three are
1952     * the arrowhead.
1953     */
1954    private static Point[] createDOMArrowPoints(String symbolID, Rect bounds, Point center, float angle, boolean isY, float modifierFontHeight)
1955    {
1956        Point[] arrowPoints = new Point[6];
1957        Point pt1 = null;
1958        Point pt2 = null;
1959        Point pt3 = null;
1960
1961        int affiliation = SymbolID.getAffiliation(symbolID);
1962        int context = SymbolID.getContext(symbolID);
1963        int length = 40;
1964        if (SymbolUtilities.isCBRNEvent(symbolID))
1965        {
1966            length = Math.round(bounds.height() / 2);
1967        }
1968        else if((SymbolUtilities.isHQ(symbolID)))
1969        {
1970            if(SymbolUtilities.hasRectangleFrame(symbolID))
1971                length = bounds.height();
1972            else
1973                length = (int)Math.round(bounds.height() * 0.7);
1974        }
1975        else// if(bounds.height() >= 100)
1976        {
1977            length = (int)Math.round(bounds.height() * 0.7);
1978        }
1979
1980        //get endpoint
1981        int dx2, dy2,
1982                x1, y1,
1983                x2, y2;
1984
1985        x1 = Math.round(center.x);
1986        y1 = Math.round(center.y);
1987
1988        pt1 = new Point(x1, y1);
1989
1990        if (SymbolUtilities.hasModifier(symbolID, Modifiers.Q_DIRECTION_OF_MOVEMENT ) &&
1991            SymbolUtilities.isCBRNEvent(symbolID) ||
1992                SymbolUtilities.isLand(symbolID) ||
1993                SymbolID.getSymbolSet(symbolID)==SymbolID.SymbolSet_DismountedIndividuals)
1994        {
1995            //drawStaff = true;
1996            if(SymbolUtilities.isHQ(symbolID)==false)//has HQ staff to start from
1997            {
1998                y1 = bounds.top + bounds.height();
1999                pt1 = new Point(x1, y1);
2000
2001                if (isY == true && SymbolUtilities.isCBRNEvent(symbolID))//make room for y modifier
2002                {
2003                    int yModifierOffset = (int) modifierFontHeight;
2004
2005                    yModifierOffset += RS.getTextOutlineWidth();
2006
2007                    pt1.offset(0, yModifierOffset);
2008                }
2009
2010                y1 = y1 + length;
2011                pt2 = new Point(x1, y1);
2012            }
2013            else
2014            {
2015                x1 = bounds.left+1;
2016                pt2 = new Point(x1, y1);
2017                if(SymbolUtilities.hasRectangleFrame(symbolID))
2018                {
2019                    /*y1 = bounds.top + bounds.height();
2020                    pt1 = new Point(x1, y1);
2021                    y1 = y1 + length;
2022                    pt2 = new Point(x1, y1);//*/
2023
2024                    pt1.x = x1;
2025                    y1 = bounds.top + (bounds.height());
2026                    pt1.y = y1;
2027                    x2 = x1;
2028                    pt2.x = x2;
2029                    y1 = pt1.y + bounds.height();
2030                    pt2.y = y1;//*/
2031
2032                }
2033                else
2034                {
2035                    pt1.x = x1;
2036                    y1 = bounds.top + (bounds.height() / 2);
2037                    pt1.y = y1;
2038                    x2 = x1;
2039                    pt2.x = x2;
2040                    y1 = pt1.y + bounds.height();
2041                    pt2.y = y1;
2042                }
2043            }
2044        }
2045
2046            //get endpoint given start point and an angle
2047        //x2 = x1 + (length * Math.cos(radians)));
2048        //y2 = y1 + (length * Math.sin(radians)));
2049        angle = angle - 90;//in java, east is zero, we want north to be zero
2050        double radians = 0;
2051        radians = (angle * (Math.PI / 180));//convert degrees to radians
2052
2053        dx2 = x1 + (int) (length * Math.cos(radians));
2054        dy2 = y1 + (int) (length * Math.sin(radians));
2055        x2 = Math.round(dx2);
2056        y2 = Math.round(dy2);
2057
2058
2059        //UPDATED ARROWHEAD CODE
2060        Point[] head = null;
2061        Point endPoint = new Point((int) x2, (int) y2);
2062        if(pt2 != null)
2063            head = createDOMArrowHead(pt2, endPoint);//pt3);
2064        else
2065            head = createDOMArrowHead(pt1, endPoint);//pt3);
2066
2067        if(head != null)
2068        {
2069            arrowPoints[0] = pt1;
2070            arrowPoints[1] = pt2;
2071            arrowPoints[2] = pt3;
2072            arrowPoints[3] = head[0];
2073            arrowPoints[4] = head[1];
2074            arrowPoints[5] = head[2];
2075
2076            //adjusted endpoint
2077            if(head.length >= 4 && head[3] != null)
2078            {
2079                arrowPoints[2] = head[3];
2080            }
2081        }
2082
2083        return arrowPoints;
2084
2085    }
2086
2087    private static Point[] createDOMArrowHead(Point lpt1, Point lpt2)
2088    {
2089        Point[] arrowPoints = new Point[6];
2090        Point pt1 = null;
2091        Point pt2 = null;
2092        Point pt3 = null;
2093
2094        int x1 = lpt1.x;
2095        int y1 = lpt1.y;
2096        int x2 = lpt2.x;
2097        int y2 = lpt2.y;
2098
2099        // Compute direction vector
2100        double dx = x2 - x1;
2101        double dy = y2 - y1;
2102        double length = Math.sqrt(dx * dx + dy * dy);
2103
2104        // Scale triangle size
2105        double scale = length * 0.1;  // Scaling factor for size
2106        double offset = scale * 1.5;  // Move triangle further down the line
2107
2108        // Normalize direction vector
2109        double unitX = dx / length;
2110        double unitY = dy / length;
2111
2112        // Compute perpendicular vector for triangle base
2113        double nx = -unitY;
2114        double ny = unitX;
2115
2116        // Compute adjusted triangle vertices
2117        int tipX = x2;
2118        int tipY = y2;
2119        int baseX1 = (int) (x2 - offset * unitX + scale * nx);
2120        int baseY1 = (int) (y2 - offset * unitY + scale * ny);
2121        int baseX2 = (int) (x2 - offset * unitX - scale * nx);
2122        int baseY2 = (int) (y2 - offset * unitY - scale * ny);
2123
2124
2125        //arrowHead = new Polygon(xPoints, yPoints, 3);
2126        arrowPoints[0] = new Point(tipX,tipY);
2127        arrowPoints[1] = new Point(baseX1,baseY1);
2128        arrowPoints[2] = new Point(baseX2,baseY2);
2129        // Adjust line endpoint to be the middle of the base line of the arrowhead
2130        int adjustedX2 = (baseX1 + baseX2) / 2;
2131        int adjustedY2 = (baseY1 + baseY2) / 2;
2132        arrowPoints[3] = new Point(adjustedX2,adjustedY2);
2133
2134        return arrowPoints;
2135
2136    }
2137
2138    private static void drawDOMArrow(Canvas ctx, Point[] domPoints, int alpha, Color lineColor)
2139    {
2140        float domStrokeWidth = Math.round(RendererSettings.getInstance().getDeviceDPI() / 96f);
2141        if(domStrokeWidth < 1)
2142            domStrokeWidth=1;
2143
2144
2145        Paint domPaint = new Paint();
2146        domPaint.setAntiAlias(true);
2147        domPaint.setStrokeCap(Cap.BUTT);
2148        domPaint.setStrokeJoin(Join.MITER);
2149        domPaint.setStrokeWidth(domStrokeWidth);//3
2150        domPaint.setColor(lineColor.toInt());
2151        domPaint.setStyle(Style.STROKE);
2152        if(alpha > -1)
2153            domPaint.setAlpha(alpha);
2154
2155        Path domPath = new Path();
2156        domPath.moveTo(domPoints[0].x, domPoints[0].y);
2157        if (domPoints[1] != null)
2158        {
2159            domPath.lineTo(domPoints[1].x, domPoints[1].y);
2160        }
2161        if (domPoints[2] != null)
2162        {
2163            domPath.lineTo(domPoints[2].x, domPoints[2].y);
2164        }
2165        ctx.drawPath(domPath, domPaint);
2166
2167        domPath.reset();
2168        domPaint.setStyle(Style.FILL);
2169        domPath.moveTo(domPoints[3].x, domPoints[3].y);
2170        domPath.lineTo(domPoints[4].x, domPoints[4].y);
2171        domPath.lineTo(domPoints[5].x, domPoints[5].y);
2172        ctx.drawPath(domPath, domPaint);
2173    }
2174
2175    private static Rect processOperationalConditionIndicator(String symbolID, Rect symbolBounds, int offsetY)
2176    {
2177        //create Operational Condition Indicator
2178        //set color
2179        Rect bar = null;
2180        int status;
2181        Color statusColor;
2182        int barSize = 0;
2183        int pixelSize = symbolBounds.height();
2184
2185        status = SymbolID.getStatus(symbolID);
2186        if (status == SymbolID.Status_Present_FullyCapable ||
2187                status == SymbolID.Status_Present_Damaged ||
2188                status == SymbolID.Status_Present_Destroyed ||
2189                status == SymbolID.Status_Present_FullToCapacity)
2190        {
2191            if (pixelSize > 0)
2192            {
2193                barSize = Math.round(pixelSize / 5);
2194            }
2195
2196            if (barSize < 2)
2197            {
2198                barSize = 2;
2199            }
2200
2201            offsetY += Math.round(symbolBounds.top + symbolBounds.height());
2202
2203            bar = RectUtilities.makeRect(symbolBounds.left + 2, offsetY, Math.round(symbolBounds.width()) - 4, barSize);
2204        }
2205
2206        return bar;
2207    }
2208
2209    private static Path processOperationalConditionIndicatorSlash(String symbolID, Rect symbolBounds)
2210    {
2211        //create Operational Condition Indicator
2212        Path path = null;
2213        int status;
2214        status = SymbolID.getStatus(symbolID);
2215
2216        if (status == SymbolID.Status_Present_Damaged  || status == SymbolID.Status_Present_Destroyed)
2217        {
2218            float widthRatio = SymbolUtilities.getUnitRatioWidth(symbolID);
2219            float heightRatio = SymbolUtilities.getUnitRatioHeight(symbolID);
2220
2221            float slashHeight = (symbolBounds.height() / heightRatio * 1.47f);
2222            float slashWidth = (symbolBounds.width() / widthRatio * 0.85f);
2223            float centerX = symbolBounds.exactCenterX();
2224            float centerY = symbolBounds.exactCenterY();
2225            path = new Path();
2226            if(status == SymbolID.Status_Present_Damaged)//Damaged /
2227            {
2228                path.moveTo(centerX - (slashWidth/2),centerY+(slashHeight/2));
2229                path.lineTo(centerX + (slashWidth/2),centerY-(slashHeight/2));
2230            }
2231            else if(status == SymbolID.Status_Present_Destroyed)//Destroyed X
2232            {
2233                path.moveTo(centerX - (slashWidth/2),centerY+(slashHeight/2));
2234                path.lineTo(centerX + (slashWidth/2),centerY-(slashHeight/2));
2235                path.moveTo(centerX - (slashWidth/2),centerY-(slashHeight/2));
2236                path.lineTo(centerX + (slashWidth/2),centerY+(slashHeight/2));
2237            }
2238            return path;
2239
2240        }
2241
2242        return path;
2243    }
2244
2245    private static SVGPath processOperationalConditionIndicatorSlashSVG(String symbolID, Rect symbolBounds)
2246    {
2247        //create Operational Condition Indicator
2248        SVGPath path = null;
2249        int status;
2250        status = SymbolID.getStatus(symbolID);
2251
2252        if (status == SymbolID.Status_Present_Damaged  || status == SymbolID.Status_Present_Destroyed)
2253        {
2254            float widthRatio = SymbolUtilities.getUnitRatioWidth(symbolID);
2255            float heightRatio = SymbolUtilities.getUnitRatioHeight(symbolID);
2256
2257            float slashHeight = (symbolBounds.height() / heightRatio * 1.47f);
2258            float slashWidth = (symbolBounds.width() / widthRatio * 0.85f);
2259            float centerX = symbolBounds.exactCenterX();
2260            float centerY = symbolBounds.exactCenterY();
2261            path = new SVGPath();
2262            if(status == SymbolID.Status_Present_Damaged)//Damaged /
2263            {
2264                path.moveTo(centerX - (slashWidth/2),centerY+(slashHeight/2));
2265                path.lineTo(centerX + (slashWidth/2),centerY-(slashHeight/2));
2266            }
2267            else if(status == SymbolID.Status_Present_Destroyed)//Destroyed X
2268            {
2269                path.moveTo(centerX - (slashWidth/2),centerY+(slashHeight/2));
2270                path.lineTo(centerX + (slashWidth/2),centerY-(slashHeight/2));
2271                path.moveTo(centerX - (slashWidth/2),centerY-(slashHeight/2));
2272                path.lineTo(centerX + (slashWidth/2),centerY+(slashHeight/2));
2273            }
2274            return path;
2275
2276        }
2277
2278        return path;
2279    }
2280
2281
2282    public static SymbolDimensionInfo processSpeedLeader(SymbolDimensionInfo sdi, String symbolID, Map<String,String> modifiers, Map<String,String> attributes)
2283    {
2284        SymbolDimensionInfo rsdi = sdi;
2285
2286        Rect imageBounds = sdi.getImageBounds();
2287        Rect symbolBounds = sdi.getSymbolBounds();
2288        Point symbolCenter = sdi.getCenterPoint();
2289        int ss = SymbolID.getSymbolSet(symbolID);
2290        int pixelSize = RendererSettings.getInstance().getDefaultPixelSize();
2291        int dpi = RendererSettings.getInstance().getDeviceDPI();
2292        if(attributes != null && attributes.containsKey(MilStdAttributes.PixelSize))
2293            pixelSize = Integer.parseInt(attributes.get(MilStdAttributes.PixelSize));
2294        float strokeWidth = 3f;
2295        strokeWidth = (float) dpi / 48f;
2296        if (strokeWidth < 1f)
2297            strokeWidth = 1f;
2298
2299        Path slPath = null;
2300        SVGPath slsvgPath = null;
2301        Rect slBounds = null;
2302        try {
2303            if (SymbolUtilities.hasModifier(symbolID, Modifiers.AJ_SPEED_LEADER) &&
2304                    (modifiers != null && modifiers.containsKey(Modifiers.AJ_SPEED_LEADER)))
2305            {
2306                String aj = modifiers.get(Modifiers.AJ_SPEED_LEADER);
2307                String[] values = aj.split(" ");
2308                if (values.length >= 3) {
2309                    int speed = Integer.parseInt(values[0]);
2310                    String speedUnit = values[1];
2311                    int angle = 0;
2312                    if (values[2].length() == 3)
2313                        angle = Integer.parseInt(values[2]) - 90;
2314                    else
2315                        angle = (int) (Integer.parseInt(values[2]) * 0.05625) - 90;
2316
2317                    slPath = new Path();
2318                    slPath.moveTo(symbolCenter.x, symbolCenter.y);
2319                    slsvgPath = new SVGPath();
2320                    slsvgPath.moveTo(symbolCenter.x, symbolCenter.y);
2321
2322                    //convert to Knots
2323                    switch (speedUnit)//KPH, KPS, MPH, NMH, KTS//https://www.aviationhunt.com/speed-converter/
2324                    {
2325                        case "KPH":
2326                            speed = (int) (speed * 0.539957);
2327                            break;
2328                        case "KPS"://https://www.metric-conversions.org/speed/kilometers-per-second-to-knots.htm
2329                            speed = (int) (speed * 1943.84);
2330                            break;
2331                        case "MPH":
2332                            speed = (int) (speed * 0.86897);
2333                            break;
2334                    }
2335
2336                    int distance = 0;
2337                    char frame = SymbolID.getFrameShape(symbolID);
2338                    boolean fast = false;
2339                    if (frame == '0' && ss == SymbolID.SymbolSet_Air ||
2340                            ss == SymbolID.SymbolSet_AirMissile ||
2341                            ss == SymbolID.SymbolSet_SignalsIntelligence_Air ||
2342                            ss == SymbolID.SymbolSet_SpaceMissile ||
2343                            ss == SymbolID.SymbolSet_Space ||
2344                            (SymbolID.getVersion(symbolID) <= SymbolID.Version_2525Dch1 && ss == SymbolID.SymbolSet_SignalsIntelligence_Space))
2345                    {
2346                        fast = true;
2347                    }
2348                    else if(frame == SymbolID.FrameShape_Air || frame == SymbolID.FrameShape_Space)
2349                    {
2350                        fast = true;
2351                    }
2352
2353                    float distanceScaler = dpi;//spec does scale by inch, but if the symbol is too big, scale by pixel size
2354                    if(dpi < pixelSize)
2355                        distanceScaler = pixelSize;
2356
2357                    if(fast)
2358                    {//aircraft might be 1/4 inch if its speed is less than 300 knots, 1/2 inch if its speed is between 300 and 600 knots and 3/4 inch if its speed is more than 600 knots.
2359                        if (speed < 300)
2360                            distance = (int) (distanceScaler * 0.25)/300 * speed;
2361                        else if (speed < 600)
2362                            distance = (int) (distanceScaler * 0.5)/600 * speed;
2363                        else
2364                            distance = (int) (distanceScaler * 0.75);
2365                    }
2366                    else//submarine might be 1/4 inch if its speed is less than 15 knots, 1/2 inch if its speed is between 15 and 30 knots and 3/4 inch if its speed is more than 30 knots
2367                    {
2368                        if (speed < 15)
2369                            distance = (int) (distanceScaler * 0.25)/15 * speed;
2370                        else if (speed < 30)
2371                            distance = (int) (distanceScaler * 0.5)/30 * speed;
2372                        else
2373                            distance = (int) (distanceScaler * 0.75);
2374                    }
2375                    double radians = (angle * (Math.PI / 180));//convert degrees to radians
2376                    int x2 = (int) (symbolCenter.x + distance * Math.cos(radians));
2377                    int y2 = (int) (symbolCenter.y + distance * Math.sin(radians));
2378
2379                    slPath.lineTo(x2, y2);
2380                    slsvgPath.lineTo(x2, y2);
2381                    slBounds = slsvgPath.getBounds();
2382                    imageBounds.union(slBounds);
2383                }
2384
2385                if (sdi instanceof ImageInfo) {
2386                    Bitmap bmp = Bitmap.createBitmap((int) Math.ceil(imageBounds.width()), (int) Math.ceil(imageBounds.height()), Config.ARGB_8888);
2387                    Canvas ctx = new Canvas(bmp);
2388
2389                    int alpha = 1;
2390                    if (attributes.containsKey(MilStdAttributes.Alpha))
2391                        alpha = Integer.parseInt(attributes.get(MilStdAttributes.Alpha));
2392
2393
2394                    Paint slPaint = new Paint();
2395                    slPaint.setColor(Color.BLACK.toInt());
2396                    slPaint.setAlpha(alpha * 255);
2397                    slPaint.setStyle(Style.STROKE);
2398                    slPaint.setStrokeWidth(strokeWidth);
2399
2400
2401                    float offsetX = 0;
2402                    float offsetY = 0;
2403                    if (imageBounds.left < 0)
2404                        offsetX = imageBounds.left * -1;
2405                    if (imageBounds.top < 0)
2406                        offsetY = imageBounds.top * -1;
2407
2408                    slPath.offset(offsetX,offsetY);
2409
2410                    ctx.drawBitmap(((ImageInfo) sdi).getImage(), offsetX, offsetY, null);
2411                    ctx.drawPath(slPath,slPaint);
2412
2413                    imageBounds.offset((int)offsetX,(int)offsetY);
2414                    symbolBounds.offset((int)offsetX,(int)offsetY);
2415                    symbolCenter.offset((int)offsetX,(int)offsetY);
2416
2417                    rsdi = new ImageInfo(bmp, symbolCenter, symbolBounds);
2418                }
2419                else if (sdi instanceof SVGSymbolInfo)
2420                {//public static String Convert(Shape shape,String stroke, String fill, String strokeWidth, String strokeOpacity, String fillOpacity, String dashArray, String lineCap)
2421                    String svg = ((SVGSymbolInfo) sdi).getSVG();
2422                    svg += slsvgPath.toSVGElement("#000000",strokeWidth,"none",1,1,null);
2423                    //svg += (Shape2SVG.Convert(slPath, "#000000", "none", String.valueOf(strokeWidth),null,null,null, null));
2424                    rsdi = new SVGSymbolInfo(svg,symbolCenter,symbolBounds,imageBounds);
2425                }
2426            }
2427        }
2428        catch(Exception exc)
2429        {
2430            ErrorLogger.LogException("ModifierRenderer","processSpeedLineIndicator",exc);
2431        }
2432
2433        return rsdi;
2434    }
2435
2436    /**
2437     * uses 2525C layout which shows most modifiers
2438     * @param sdi
2439     * @param symbolID
2440     * @param modifiers
2441     * @param attributes
2442     * @return
2443     */
2444    public static SymbolDimensionInfo processUnknownTextModifiers(SymbolDimensionInfo sdi, String symbolID, Map<String,String> modifiers, Map<String,String> attributes)
2445    {
2446        Paint modifierFont = getFont(attributes);
2447        float[] hd = getFontHeightandDescent(modifierFont);
2448        float modifierFontHeight = hd[0];
2449        float modifierFontDescent = hd[1];
2450
2451        String modifierFontName = RendererSettings.getInstance().getModiferFontProps()[0];
2452        if(attributes != null && attributes.containsKey(MilStdAttributes.FontFamily))
2453        {
2454            String temp = attributes.get(MilStdAttributes.FontFamily);
2455            if(temp != null && !temp.isEmpty())
2456                modifierFontName = temp;
2457        }
2458
2459        int bufferHorizontal = (int)modifierFontHeight/2;
2460        int bufferXL = bufferHorizontal;
2461        int bufferXR = bufferHorizontal;
2462        int bufferY = 2;
2463        int bufferText = 2;
2464        int x = 0;
2465        int y = 0;//best y
2466
2467        SymbolDimensionInfo  newsdi = null;
2468
2469        ArrayList<TextInfo> tiArray = new ArrayList<TextInfo>(modifiers.size());
2470
2471        int descent = (int) (modifierFontDescent + 0.5);
2472
2473        Rect labelBounds = null;
2474        int labelWidth, labelHeight;
2475
2476        Rect bounds = new Rect(sdi.getSymbolBounds());
2477        Rect symbolBounds = new Rect(sdi.getSymbolBounds());
2478        Point centerPoint = new Point(sdi.getCenterPoint());
2479        Rect imageBounds = new Rect(sdi.getImageBounds());
2480
2481        int echelon = SymbolID.getAmplifierDescriptor(symbolID);
2482        String echelonText = SymbolUtilities.getEchelonText(echelon);
2483        String amText = SymbolUtilities.getStandardIdentityModifier(symbolID);
2484        int mobility = SymbolID.getAmplifierDescriptor(symbolID);
2485
2486        //adjust width of bounds for mobility/echelon/engagement bar which could be wider than the symbol
2487        bounds = RectUtilities.makeRect(imageBounds.left, bounds.top, imageBounds.width(), bounds.height());
2488
2489
2490        //check if text is too tall:
2491        boolean byLabelHeight = false;
2492        labelHeight = (int) (modifierFontHeight + 0.5);/* RendererUtilities.measureTextHeight(RendererSettings.getModifierFontName(),
2493         RendererSettings.getModifierFontSize(),
2494         RendererSettings.getModifierFontStyle()).fullHeight;*/
2495
2496        int maxHeight = (bounds.height());
2497        if ((labelHeight * 3) > maxHeight)
2498        {
2499            byLabelHeight = true;
2500        }
2501
2502        //Affiliation Modifier being drawn as a display modifier
2503        String affiliationModifier = null;
2504        if (RS.getDrawAffiliationModifierAsLabel() == true)
2505        {
2506            affiliationModifier = SymbolUtilities.getStandardIdentityModifier(symbolID);
2507        }
2508        if (affiliationModifier != null)
2509        {   //Set affiliation modifier
2510            modifiers.put(Modifiers.E_FRAME_SHAPE_MODIFIER, affiliationModifier);
2511            //modifiers[Modifiers.E_FRAME_SHAPE_MODIFIER] = affiliationModifier;
2512        }//*/
2513
2514
2515        //            int y0 = 0;//W            E/F
2516        //            int y1 = 0;//X/Y          G
2517        //            int y2 = 0;//V/AD/AE      H/AF
2518        //            int y3 = 0;//T            M CC
2519        //            int y4 = 0;//Z            J/K/L/N/P
2520        //
2521
2522        // <editor-fold defaultstate="collapsed" desc="Build Modifiers">
2523        String modifierValue = null;
2524        TextInfo tiTemp = null;
2525        //if(Modifiers.C_QUANTITY in modifiers
2526        if (modifiers.containsKey(Modifiers.C_QUANTITY)
2527                && SymbolUtilities.canSymbolHaveModifier(symbolID, Modifiers.C_QUANTITY))
2528        {
2529            String text = modifiers.get(Modifiers.C_QUANTITY);
2530            if(text != null)
2531            {
2532                    //bounds = armyc2.c5isr.renderer.utilities.RendererUtilities.getTextOutlineBounds(modifierFont, text, new SO.Point(0,0));
2533                    tiTemp = new TextInfo(text, 0, 0, modifierFont, modifierFontName);
2534                    labelBounds = tiTemp.getTextBounds();
2535                    labelWidth = labelBounds.width();
2536                    x = Math.round((symbolBounds.left + (symbolBounds.width() * 0.5f)) - (labelWidth * 0.5f));
2537                    y = Math.round(symbolBounds.top - bufferY - descent);
2538                    tiTemp.setLocation(x, y);
2539                    tiArray.add(tiTemp);
2540            }
2541        }
2542
2543        //if(Modifiers.X_ALTITUDE_DEPTH in modifiers || Modifiers.Y_LOCATION in modifiers)
2544        if (modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH) || modifiers.containsKey(Modifiers.Y_LOCATION))
2545        {
2546            modifierValue = null;
2547
2548            String xm = null,
2549                    ym = null;
2550
2551            if (modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH) && SymbolUtilities.canSymbolHaveModifier(symbolID, Modifiers.X_ALTITUDE_DEPTH))
2552            {
2553                xm = modifiers.get(Modifiers.X_ALTITUDE_DEPTH);// xm = modifiers.X;
2554            }
2555            if (modifiers.containsKey(Modifiers.Y_LOCATION))
2556            {
2557                ym = modifiers.get(Modifiers.Y_LOCATION);// ym = modifiers.Y;
2558            }
2559            if (xm == null && ym != null)
2560            {
2561                modifierValue = ym;
2562            }
2563            else if (xm != null && ym == null)
2564            {
2565                modifierValue = xm;
2566            }
2567            else if (xm != null && ym != null)
2568            {
2569                modifierValue = xm + "  " + ym;
2570            }
2571
2572            if(modifierValue != null)
2573            {
2574                    tiTemp = new TextInfo(modifierValue, 0, 0, modifierFont, modifierFontName);
2575                    labelBounds = tiTemp.getTextBounds();
2576                    labelWidth = labelBounds.width();
2577        
2578                    if (!byLabelHeight)
2579                    {
2580                        x = bounds.left - labelBounds.width() - bufferXL;
2581                        y = bounds.top + labelHeight - descent;
2582                    }
2583                    else
2584                    {
2585                        x = bounds.left - labelBounds.width() - bufferXL;
2586        
2587                        y = (bounds.height());
2588                        y = (int) ((y * 0.5) + (labelHeight * 0.5));
2589        
2590                        y = y - ((labelHeight + bufferText));
2591                        y = bounds.top + y;
2592                    }
2593        
2594                    tiTemp.setLocation(x, y);
2595                    tiArray.add(tiTemp);
2596            }
2597        }
2598
2599        if (modifiers.containsKey(Modifiers.G_STAFF_COMMENTS) )
2600        {
2601            modifierValue = modifiers.get(Modifiers.G_STAFF_COMMENTS);
2602
2603            if(modifierValue != null)
2604            {
2605                    tiTemp = new TextInfo(modifierValue, 0, 0, modifierFont, modifierFontName);
2606                    labelBounds = tiTemp.getTextBounds();
2607                    labelWidth = labelBounds.width();
2608        
2609                    x = bounds.left + bounds.width() + bufferXR;
2610                    if (!byLabelHeight)
2611                    {
2612                        y = bounds.top + labelHeight - descent;
2613                    }
2614                    else
2615                    {
2616                        y = (bounds.height());
2617                        y = (int) ((y * 0.5) + (labelHeight * 0.5));
2618        
2619                        y = y - ((labelHeight + bufferText));
2620                        y = bounds.top + y;
2621                    }
2622        
2623                    tiTemp.setLocation(x, y);
2624                    tiArray.add(tiTemp);
2625
2626            }
2627        }
2628
2629        if ((modifiers.containsKey(Modifiers.V_EQUIP_TYPE)) ||
2630                (modifiers.containsKey(Modifiers.AD_PLATFORM_TYPE)) ||
2631                (modifiers.containsKey(Modifiers.AE_EQUIPMENT_TEARDOWN_TIME)))
2632        {
2633            String vm = null,
2634                    adm = null,
2635                    aem = null;
2636
2637            if (modifiers.containsKey(Modifiers.V_EQUIP_TYPE) && SymbolUtilities.canSymbolHaveModifier(symbolID, Modifiers.V_EQUIP_TYPE))
2638            {
2639                vm = modifiers.get(Modifiers.V_EQUIP_TYPE);
2640            }
2641            if (modifiers.containsKey(Modifiers.AD_PLATFORM_TYPE) && SymbolUtilities.canSymbolHaveModifier(symbolID, Modifiers.AD_PLATFORM_TYPE))
2642            {
2643                adm = modifiers.get(Modifiers.AD_PLATFORM_TYPE);
2644            }
2645            if (modifiers.containsKey(Modifiers.AE_EQUIPMENT_TEARDOWN_TIME) && SymbolUtilities.canSymbolHaveModifier(symbolID, Modifiers.AE_EQUIPMENT_TEARDOWN_TIME))
2646            {
2647                aem = modifiers.get(Modifiers.AE_EQUIPMENT_TEARDOWN_TIME);
2648            }
2649
2650            modifierValue = "";
2651            if(vm != null && vm.equals("") == false)
2652                modifierValue = vm;
2653            if(adm != null && adm.equals("") == false)
2654                modifierValue += " " + adm;
2655            if(aem != null && aem.equals("") == false)
2656                modifierValue += " " + aem;
2657
2658            if(modifierValue != null)
2659                modifierValue = modifierValue.trim();
2660            if(modifierValue != null && modifierValue.equals("") == false)
2661            {
2662                    tiTemp = new TextInfo(modifierValue, 0, 0, modifierFont, modifierFontName);
2663                    labelBounds = tiTemp.getTextBounds();
2664                    labelWidth = labelBounds.width();
2665        
2666                    x = bounds.left - labelBounds.width() - bufferXL;
2667        
2668                    y = (bounds.height());
2669                    y = (int) ((y * 0.5f) + ((labelHeight - descent) * 0.5f));
2670                    y = bounds.top + y;
2671        
2672                    tiTemp.setLocation(x, y);
2673                    tiArray.add(tiTemp);
2674            }
2675        }
2676
2677        if (modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1) || modifiers.containsKey(Modifiers.AF_COMMON_IDENTIFIER))
2678        {
2679            modifierValue = "";
2680            String hm = "",
2681                    afm = "";
2682
2683            hm = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
2684            if (modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
2685            {
2686                hm = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
2687            }
2688            if (modifiers.containsKey(Modifiers.AF_COMMON_IDENTIFIER) && SymbolUtilities.canSymbolHaveModifier(symbolID, Modifiers.AF_COMMON_IDENTIFIER))
2689            {
2690                afm = modifiers.get(Modifiers.AF_COMMON_IDENTIFIER);
2691            }
2692
2693            modifierValue = hm + " " + afm;
2694            modifierValue = modifierValue.trim();
2695
2696            if(modifierValue != null && modifierValue.equals("") == false)
2697            {
2698                    tiTemp = new TextInfo(modifierValue, 0, 0, modifierFont, modifierFontName);
2699                    labelBounds = tiTemp.getTextBounds();
2700                    labelWidth = labelBounds.width();
2701        
2702                    x = bounds.left + bounds.width() + bufferXR;
2703        
2704                    y = (bounds.height());
2705                    y = (int) ((y * 0.5) + ((labelHeight - descent) * 0.5));
2706                    y = bounds.top + y;
2707        
2708                    tiTemp.setLocation(x, y);
2709                    tiArray.add(tiTemp);
2710
2711            }
2712        }
2713
2714        if (modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
2715        {
2716            modifierValue = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
2717
2718            if(modifierValue != null)
2719            {
2720                    tiTemp = new TextInfo(modifierValue, 0, 0, modifierFont, modifierFontName);
2721                    labelBounds = tiTemp.getTextBounds();
2722                    labelWidth = labelBounds.width();
2723        
2724                    if (!byLabelHeight)
2725                    {
2726                        x = bounds.left - labelWidth - bufferXL;
2727                        y = bounds.top + bounds.height();
2728                    }
2729                    else
2730                    {
2731                        x = bounds.left - labelWidth - bufferXL;
2732        
2733                        y = (bounds.height());
2734                        y = (int) ((y * 0.5) + (labelHeight * 0.5));
2735        
2736                        y = y + ((labelHeight + bufferText) - descent);
2737                        y = bounds.top + y;
2738                    }
2739        
2740                    tiTemp.setLocation(x, y);
2741                    tiArray.add(tiTemp);
2742            }
2743        }
2744
2745        if (modifiers.containsKey(Modifiers.M_HIGHER_FORMATION) || modifiers.containsKey(Modifiers.AS_COUNTRY))
2746        {
2747            modifierValue = "";
2748
2749            if (modifiers.containsKey(Modifiers.M_HIGHER_FORMATION) && SymbolUtilities.canSymbolHaveModifier(symbolID, Modifiers.M_HIGHER_FORMATION))
2750            {
2751                modifierValue += modifiers.get(Modifiers.M_HIGHER_FORMATION);
2752            }
2753            if (modifiers.containsKey(Modifiers.AS_COUNTRY))
2754            {
2755                if (modifierValue.length() > 0)
2756                {
2757                    modifierValue += " ";
2758                }
2759                modifierValue += modifiers.get(Modifiers.AS_COUNTRY);
2760            }
2761
2762            if(modifierValue.equals("")==false)
2763            {
2764                tiTemp = new TextInfo(modifierValue, 0, 0, modifierFont, modifierFontName);
2765                labelBounds = tiTemp.getTextBounds();
2766                labelWidth = labelBounds.width();
2767
2768                x = bounds.left + bounds.width() + bufferXR;
2769                if (!byLabelHeight)
2770                {
2771                    y = bounds.top + bounds.height();
2772                }
2773                else
2774                {
2775                    y = (bounds.height());
2776                    y = (int) ((y * 0.5) + (labelHeight * 0.5));
2777
2778                    y = y + ((labelHeight + bufferText - descent));
2779                    y = bounds.top + y;
2780                }
2781
2782                tiTemp.setLocation(x, y);
2783                tiArray.add(tiTemp);
2784
2785            }
2786        }
2787
2788        if (modifiers.containsKey(Modifiers.Z_SPEED) )
2789        {
2790            modifierValue = modifiers.get(Modifiers.Z_SPEED);
2791
2792            if(modifierValue != null)
2793            {
2794                    tiTemp = new TextInfo(modifierValue, 0, 0, modifierFont, modifierFontName);
2795                    labelBounds = tiTemp.getTextBounds();
2796                    labelWidth = labelBounds.width();
2797        
2798                    x = bounds.left - labelWidth - bufferXL;
2799                    if (!byLabelHeight)
2800                    {
2801                        y = Math.round(bounds.top + bounds.height() + labelHeight + bufferText);
2802                    }
2803                    else
2804                    {
2805                        y = (bounds.height());
2806                        y = (int) ((y * 0.5) + (labelHeight * 0.5));
2807        
2808                        y = y + ((labelHeight + bufferText) * 2) - (descent * 2);
2809                        y = Math.round(bounds.top + y);
2810                    }
2811        
2812                    tiTemp.setLocation(x, y);
2813                    tiArray.add(tiTemp);
2814            }
2815        }
2816
2817        if (modifiers.containsKey(Modifiers.J_EVALUATION_RATING)
2818                || modifiers.containsKey(Modifiers.K_COMBAT_EFFECTIVENESS)//
2819                || modifiers.containsKey(Modifiers.L_SIGNATURE_EQUIP)//
2820                || modifiers.containsKey(Modifiers.N_HOSTILE)//
2821                || modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))//
2822        {
2823            modifierValue = null;
2824
2825            String jm = null,
2826                    km = null,
2827                    lm = null,
2828                    nm = null,
2829                    pm = null;
2830
2831            if (modifiers.containsKey(Modifiers.J_EVALUATION_RATING))
2832            {
2833                jm = modifiers.get(Modifiers.J_EVALUATION_RATING);
2834            }
2835            if (modifiers.containsKey(Modifiers.K_COMBAT_EFFECTIVENESS) && SymbolUtilities.canSymbolHaveModifier(symbolID, Modifiers.K_COMBAT_EFFECTIVENESS))
2836            {
2837                km = modifiers.get(Modifiers.K_COMBAT_EFFECTIVENESS);
2838            }
2839            if (modifiers.containsKey(Modifiers.L_SIGNATURE_EQUIP) && SymbolUtilities.canSymbolHaveModifier(symbolID, Modifiers.L_SIGNATURE_EQUIP))
2840            {
2841                lm = modifiers.get(Modifiers.L_SIGNATURE_EQUIP);
2842            }
2843            if (modifiers.containsKey(Modifiers.N_HOSTILE) && SymbolUtilities.canSymbolHaveModifier(symbolID, Modifiers.N_HOSTILE))
2844            {
2845                nm = modifiers.get(Modifiers.N_HOSTILE);
2846            }
2847            if (modifiers.containsKey(Modifiers.P_IFF_SIF_AIS) && SymbolUtilities.canSymbolHaveModifier(symbolID, Modifiers.P_IFF_SIF_AIS))
2848            {
2849                pm = modifiers.get(Modifiers.P_IFF_SIF_AIS);
2850            }
2851
2852            modifierValue = "";
2853            if (jm != null && jm.equals("") == false)
2854            {
2855                modifierValue = modifierValue + jm;
2856            }
2857            if (km != null && km.equals("") == false)
2858            {
2859                modifierValue = modifierValue + " " + km;
2860            }
2861            if (lm != null && lm.equals("") == false)
2862            {
2863                modifierValue = modifierValue + " " + lm;
2864            }
2865            if (nm != null && nm.equals("") == false)
2866            {
2867                modifierValue = modifierValue + " " + nm;
2868            }
2869            if (pm != null && pm.equals("") == false)
2870            {
2871                modifierValue = modifierValue + " " + pm;
2872            }
2873
2874            if (modifierValue.length() > 2 && modifierValue.charAt(0) == ' ')
2875            {
2876                modifierValue = modifierValue.substring(1);
2877            }
2878
2879            modifierValue = modifierValue.trim();
2880
2881            if(modifierValue.equals("")==false)
2882            {
2883                tiTemp = new TextInfo(modifierValue, 0, 0, modifierFont, modifierFontName);
2884                labelBounds = tiTemp.getTextBounds();
2885                labelWidth = labelBounds.width();
2886
2887                x = bounds.left + bounds.width() + bufferXR;
2888                if (!byLabelHeight)
2889                {
2890                    y = Math.round(bounds.top + bounds.height() + labelHeight + bufferText);
2891                }
2892                else
2893                {
2894                    y = (bounds.height());
2895                    y = (int) ((y * 0.5) + (labelHeight * 0.5));
2896
2897                    y = y + ((labelHeight + bufferText) * 2) - (descent * 2);
2898                    y = Math.round(bounds.top + y);
2899                }
2900
2901                tiTemp.setLocation(x, y);
2902                tiArray.add(tiTemp);
2903
2904            }
2905
2906        }
2907
2908        if (modifiers.containsKey(Modifiers.W_DTG_1))
2909        {
2910            modifierValue = modifiers.get(Modifiers.W_DTG_1);
2911
2912            if(modifierValue != null)
2913            {
2914                    tiTemp = new TextInfo(modifierValue, 0, 0, modifierFont, modifierFontName);
2915                    labelBounds = tiTemp.getTextBounds();
2916                    labelWidth = labelBounds.width();
2917        
2918                    if (!byLabelHeight)
2919                    {
2920                        x = bounds.left - labelWidth - bufferXL;
2921                        y = bounds.top - bufferY - descent;
2922                    }
2923                    else
2924                    {
2925                        x = bounds.left - labelWidth - bufferXL;
2926        
2927                        y = (bounds.height());
2928                        y = (int) ((y * 0.5) + (labelHeight * 0.5));
2929        
2930                        y = y - ((labelHeight + bufferText) * 2);
2931                        y = bounds.top + y;
2932                    }
2933        
2934                    tiTemp.setLocation(x, y);
2935                    tiArray.add(tiTemp);
2936            }
2937        }
2938
2939        if (modifiers.containsKey(Modifiers.F_REINFORCED_REDUCED) || modifiers.containsKey(Modifiers.E_FRAME_SHAPE_MODIFIER))
2940        {
2941            modifierValue = null;
2942            String E = null,
2943                    F = null;
2944
2945            if (modifiers.containsKey(Modifiers.E_FRAME_SHAPE_MODIFIER))
2946            {
2947                E = modifiers.get(Modifiers.E_FRAME_SHAPE_MODIFIER);
2948                modifiers.remove(Modifiers.E_FRAME_SHAPE_MODIFIER);
2949            }
2950            if (modifiers.containsKey(Modifiers.F_REINFORCED_REDUCED) && SymbolUtilities.canSymbolHaveModifier(symbolID, Modifiers.F_REINFORCED_REDUCED))
2951            {
2952                F = modifiers.get(Modifiers.F_REINFORCED_REDUCED);
2953            }
2954
2955            if (E != null && E.equals("") == false)
2956            {
2957                modifierValue = E;
2958            }
2959
2960            if (F != null && F.equals("") == false)
2961            {
2962                if (F.toUpperCase(Locale.US) == ("R"))
2963                {
2964                    F = "(+)";
2965                }
2966                else if (F.toUpperCase(Locale.US) == ("D"))
2967                {
2968                    F = "(-)";
2969                }
2970                else if (F.toUpperCase(Locale.US) == ("RD"))
2971                {
2972                    F = "(" + (char) (177) + ")";
2973                }
2974            }
2975
2976            if (F != null && F.equals("") == false)
2977            {
2978                if (modifierValue != null && modifierValue.equals("") == false)
2979                {
2980                    modifierValue = modifierValue + " " + F;
2981                }
2982                else
2983                {
2984                    modifierValue = F;
2985                }
2986            }
2987
2988            if(modifierValue != null)
2989            {
2990                    tiTemp = new TextInfo(modifierValue, 0, 0, modifierFont, modifierFontName);
2991                    labelBounds = tiTemp.getTextBounds();
2992                    labelWidth = labelBounds.width();
2993        
2994                    if (!byLabelHeight)
2995                    {
2996                        x = bounds.left + bounds.width() + bufferXR;
2997                        y = bounds.top - bufferY - descent;
2998                    }
2999                    else
3000                    {
3001                        x = bounds.left + bounds.width() + bufferXR;
3002        
3003                        y = (bounds.height());
3004                        y = (int) ((y * 0.5) + (labelHeight * 0.5));
3005        
3006                        y = y - ((labelHeight + bufferText) * 2);
3007                        y = bounds.top + y;
3008                    }
3009        
3010                    tiTemp.setLocation(x, y);
3011                    tiArray.add(tiTemp);
3012
3013            }
3014        }
3015
3016        if (modifiers.containsKey(Modifiers.AA_SPECIAL_C2_HQ) && SymbolUtilities.canSymbolHaveModifier(symbolID, Modifiers.AA_SPECIAL_C2_HQ))
3017        {
3018            modifierValue = modifiers.get(Modifiers.AA_SPECIAL_C2_HQ);
3019
3020            if(modifierValue != null)
3021            {
3022                    tiTemp = new TextInfo(modifierValue, 0, 0, modifierFont, modifierFontName);
3023                    labelBounds = tiTemp.getTextBounds();
3024                    labelWidth = labelBounds.width();
3025        
3026                    x = (int) ((symbolBounds.left + (symbolBounds.width() * 0.5f)) - (labelWidth * 0.5f));
3027        
3028                    y = (symbolBounds.height());//checkpoint, get box above the point
3029                    y = (int) ((y * 0.5) + ((labelHeight - descent) * 0.5));
3030                    y = symbolBounds.top + y;
3031        
3032                    tiTemp.setLocation(x, y);
3033                    tiArray.add(tiTemp);
3034            }
3035        }
3036
3037
3038        // </editor-fold>
3039
3040        //Shift Points and Draw
3041        newsdi = shiftUnitPointsAndDraw(tiArray,sdi,attributes, modifierFont);
3042
3043        // <editor-fold defaultstate="collapsed" desc="Cleanup">
3044        tiArray = null;
3045        tiTemp = null;
3046        //tempShape = null;
3047        //ctx = null;
3048        //buffer = null;
3049        // </editor-fold>
3050
3051        return newsdi;
3052    }
3053
3054
3055    public static SymbolDimensionInfo  processSPTextModifiers(SymbolDimensionInfo sdi, String symbolID, Map<String,String> modifiers, Map<String,String> attributes)
3056    {
3057        Paint modifierFont = getFont(attributes);
3058        float[] hd = getFontHeightandDescent(modifierFont);
3059        float modifierFontHeight = hd[0];
3060        float modifierFontDescent = hd[1];
3061
3062        String modifierFontName = RendererSettings.getInstance().getModiferFontProps()[0];
3063        if(attributes != null && attributes.containsKey(MilStdAttributes.FontFamily))
3064        {
3065            String temp = attributes.get(MilStdAttributes.FontFamily);
3066            if(temp != null && !temp.isEmpty())
3067                modifierFontName = temp;
3068        }
3069
3070        int bufferXL = 7;
3071        int bufferXR = 7;
3072        int bufferY = 2;
3073        int bufferText = 2;
3074        int x = 0;
3075        int y = 0;//best y
3076        SymbolDimensionInfo newsdi = null;
3077
3078        ArrayList<TextInfo> tiArray = new ArrayList<TextInfo>(modifiers.size());
3079
3080        int descent = (int) (modifierFontDescent + 0.5);
3081
3082
3083        Rect labelBounds = null;
3084        int labelWidth, labelHeight;
3085
3086        Rect bounds = new Rect(sdi.getSymbolBounds());
3087        Rect symbolBounds = new Rect(sdi.getSymbolBounds());
3088        Rect imageBounds = new Rect(sdi.getImageBounds());
3089
3090        //adjust width of bounds for mobility/echelon/engagement bar which could be wider than the symbol
3091        bounds = RectUtilities.makeRect(imageBounds.left, bounds.top, imageBounds.width(), bounds.height());
3092
3093        labelHeight = (int) (modifierFontHeight + 0.5);
3094
3095        //Affiliation Modifier being drawn as a display modifier
3096        String affiliationModifier = null;
3097        if (RS.getDrawAffiliationModifierAsLabel() == true)
3098        {
3099            affiliationModifier = SymbolUtilities.getStandardIdentityModifier(symbolID);
3100        }
3101        if (affiliationModifier != null)
3102        {   //Set affiliation modifier
3103            modifiers.put(Modifiers.E_FRAME_SHAPE_MODIFIER, affiliationModifier);
3104            //modifiers[Modifiers.E_FRAME_SHAPE_MODIFIER] = affiliationModifier;
3105        }//*/
3106
3107        //Check for Valid Country Code
3108        int cc = SymbolID.getCountryCode(symbolID);
3109        String scc = "";
3110        if(cc > 0)
3111        {
3112            scc = GENCLookup.getInstance().get3CharCode(cc);
3113        }
3114        if(!scc.isEmpty())
3115            modifiers.put(Modifiers.AS_COUNTRY, scc);
3116
3117        // <editor-fold defaultstate="collapsed" desc="Build Modifiers">
3118        String modifierValue = null;
3119        TextInfo tiTemp = null;
3120
3121
3122        List<Modifier> mods = getLabelPositionIndexes(symbolID, modifiers, attributes);
3123
3124        Modifier mod = null;
3125        if(mods != null) {
3126            for (int i = 0; i < mods.size(); i++) {
3127                mod = mods.get(i);
3128
3129                tiTemp = new TextInfo(mod.getText(), 0, 0, modifierFont, modifierFontName);
3130                labelBounds = tiTemp.getTextBounds();
3131                labelWidth = (int) labelBounds.width();
3132
3133                //centered
3134                if(mod.getIndexX()==0)
3135                    x = (int) getLabelXPosition(symbolBounds, labelWidth, mod.getIndexX(), modifierFontHeight);
3136                else//on left
3137                    x = (int) getLabelXPosition(bounds, labelWidth, mod.getIndexX(), modifierFontHeight);
3138                //above center V
3139                y = (int) getLabelYPosition(bounds, labelHeight, descent, bufferText, mod.getCentered(), mod.getIndexY());
3140
3141                tiTemp.setLocation(x, y);
3142                tiArray.add(tiTemp);
3143            }
3144        }
3145
3146
3147        // </editor-fold>
3148
3149        //Shift Points and Draw
3150        newsdi = shiftUnitPointsAndDraw(tiArray,sdi,attributes, modifierFont);
3151
3152        // <editor-fold defaultstate="collapsed" desc="Cleanup">
3153        tiArray = null;
3154        tiTemp = null;
3155        //tempShape = null;
3156        //ctx = null;
3157        //buffer = null;
3158        // </editor-fold>
3159
3160        return newsdi;
3161    }
3162
3163    public static SymbolDimensionInfo ProcessTGSPWithSpecialModifierLayout(SymbolDimensionInfo sdi, String symbolID, Map<String,String> modifiers, Map<String,String> attributes, Color lineColor)
3164    {
3165        Paint modifierFont = getFont(attributes);
3166        float[] hd = getFontHeightandDescent(modifierFont);
3167        float modifierFontHeight = hd[0];
3168        float modifierFontDescent = hd[1];
3169
3170        String modifierFontName = RendererSettings.getInstance().getModiferFontProps()[0];
3171        if(attributes != null && attributes.containsKey(MilStdAttributes.FontFamily))
3172        {
3173            String temp = attributes.get(MilStdAttributes.FontFamily);
3174            if(temp != null && !temp.isEmpty())
3175                modifierFontName = temp;
3176        }
3177
3178        ImageInfo ii = null;
3179        SVGSymbolInfo ssi = null;
3180
3181        int bufferXL = 6;
3182        int bufferXR = 4;
3183        int bufferY = 2;
3184        int bufferText = 2;
3185        int centerOffset = 1; //getCenterX/Y function seems to go over by a pixel
3186        int x = 0;
3187        int y = 0;
3188        int x2 = 0;
3189        int y2 = 0;
3190
3191        int outlineOffset = RS.getTextOutlineWidth();
3192        int labelHeight = 0;
3193        int labelWidth = 0;
3194        int alpha = -1;
3195        SymbolDimensionInfo newsdi = null;
3196        Color textColor = lineColor;
3197        Color textBackgroundColor = null;
3198        int ss = SymbolID.getSymbolSet(symbolID);
3199        int ec = SymbolID.getEntityCode(symbolID);
3200        int e = SymbolID.getEntity(symbolID);
3201        int et = SymbolID.getEntityType(symbolID);
3202        int est = SymbolID.getEntitySubtype(symbolID);
3203
3204        //Feint Dummy Indicator variables
3205        Rect fdiBounds = null;
3206        Point fdiTop = null;
3207        Point fdiLeft = null;
3208        Point fdiRight = null;
3209
3210        ArrayList<TextInfo> arrMods = new ArrayList<TextInfo>();
3211        boolean duplicate = false;
3212
3213        Rect bounds = new Rect(sdi.getSymbolBounds());
3214        Rect symbolBounds = new Rect(sdi.getSymbolBounds());
3215        Point centerPoint = new Point(sdi.getCenterPoint());
3216        Rect imageBounds = new Rect(sdi.getImageBounds());
3217
3218        if (attributes.containsKey(MilStdAttributes.Alpha))
3219        {
3220            alpha = Integer.parseInt(attributes.get(MilStdAttributes.Alpha));
3221            textColor.setAlpha(alpha);
3222        }
3223
3224        centerPoint = new Point(Math.round(sdi.getCenterPoint().x), Math.round(sdi.getCenterPoint().y));
3225
3226        boolean byLabelHeight = false;
3227        labelHeight = (int) (modifierFontHeight + 0.5f);
3228
3229        int maxHeight = (symbolBounds.height());
3230        if ((labelHeight * 3) > maxHeight)
3231        {
3232            byLabelHeight = true;
3233        }
3234
3235        int descent = (int) (modifierFontDescent + 0.5f);
3236        int yForY = -1;
3237
3238        Rect labelBounds1 = null;//text.getPixelBounds(null, 0, 0);
3239        Rect labelBounds2 = null;
3240        String strText = "";
3241        String strText1 = "";
3242        String strText2 = "";
3243        TextInfo text1 = null;
3244        TextInfo text2 = null;
3245
3246
3247        if (outlineOffset > 2)
3248        {
3249            outlineOffset = ((outlineOffset - 1) / 2);
3250        }
3251        else
3252        {
3253            outlineOffset = 0;
3254        }
3255
3256        //Check for Valid Country Code
3257        int cc = SymbolID.getCountryCode(symbolID);
3258        String scc = "";
3259        if(cc > 0)
3260        {
3261            scc = GENCLookup.getInstance().get3CharCode(cc);
3262        }
3263        if(!scc.isEmpty())
3264            modifiers.put(Modifiers.AS_COUNTRY, scc);
3265
3266        // <editor-fold defaultstate="collapsed" desc="Process Special Modifiers">
3267        TextInfo ti = null;
3268        if (SymbolUtilities.isCBRNEvent(symbolID))//chemical
3269        {
3270            if ((labelHeight * 3) > bounds.height())
3271            {
3272                byLabelHeight = true;
3273            }
3274        }
3275
3276        if(ss == SymbolID.SymbolSet_ControlMeasure) {
3277            if (ec == 130500) //contact point
3278            {
3279                if (modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1)) {
3280                    strText = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
3281                    if (strText != null) {
3282                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3283                        labelWidth = Math.round(ti.getTextBounds().width());
3284                        //One modifier symbols and modifier goes in center
3285                        x = bounds.left + (int) (bounds.width() * 0.5f);
3286                        x = x - (int) (labelWidth * 0.5f);
3287                        y = bounds.top + (int) (bounds.height() * 0.4f);
3288                        y = y + (int) (labelHeight * 0.5f);
3289
3290                        ti.setLocation(Math.round(x), Math.round(y));
3291                        arrMods.add(ti);
3292                    }
3293                }
3294                if (modifiers.containsKey(Modifiers.W_DTG_1)) {
3295                    strText = modifiers.get(Modifiers.W_DTG_1);
3296                    if (strText != null) {
3297                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3298                        labelWidth = ti.getTextBounds().width();
3299
3300                        x = (bounds.left - labelWidth - bufferXL);
3301                        y = (bounds.top + labelHeight - descent);
3302
3303                        ti.setLocation(x, y);
3304                        arrMods.add(ti);
3305                    }
3306                }
3307            }
3308            else if (ec == 130700) //decision point
3309            {
3310                if (modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1)) {
3311
3312                    strText = "";
3313                    if (modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
3314                        strText += modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
3315                    if (modifiers.containsKey(Modifiers.AS_COUNTRY))
3316                        strText += " " + modifiers.get(Modifiers.AS_COUNTRY);
3317                    strText = strText.trim();
3318
3319                    if (!strText.isEmpty()) {
3320                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3321                        labelWidth = Math.round(ti.getTextBounds().width());
3322                        //One modifier symbols and modifier goes in center
3323                        x = bounds.left + (int) (bounds.width() * 0.5f);
3324                        x = x - (int) (labelWidth * 0.5f);
3325                        y = bounds.top + (int) (bounds.height() * 0.5f);
3326                        y = y + (int) (labelHeight * 0.5f);
3327
3328                        ti.setLocation(Math.round(x), Math.round(y));
3329                        arrMods.add(ti);
3330                    }
3331                }
3332            }
3333            else if (ec == 212800)//harbor
3334            {
3335                if (modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1)) {
3336                    strText = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
3337                    if (strText != null) {
3338                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3339                        labelWidth = Math.round(ti.getTextBounds().width());
3340                        //One modifier symbols and modifier goes in center
3341                        x = bounds.left + (int) (bounds.width() * 0.5f);
3342                        x = x - (int) (labelWidth * 0.5f);
3343                        y = bounds.top + (int) (bounds.height() * 0.5f);
3344                        y = y + (int) (labelHeight * 0.5f);
3345
3346                        ti.setLocation(Math.round(x), Math.round(y));
3347                        arrMods.add(ti);
3348                    }
3349                }
3350            } else if (ec == 131300)//point of interest
3351            {
3352                if (modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1)) {
3353                    strText = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
3354                    if (strText != null) {
3355                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3356                        labelWidth = Math.round(ti.getTextBounds().width());
3357                        //One modifier symbols, top third & center
3358                        x = bounds.left + (int) (bounds.width() * 0.5f);
3359                        x = x - (int) (labelWidth * 0.5f);
3360                        y = bounds.top + (int) (bounds.height() * 0.25f);
3361                        y = y + (int) (labelHeight * 0.5f);
3362
3363                        ti.setLocation(Math.round(x), Math.round(y));
3364                        arrMods.add(ti);
3365                    }
3366                }
3367            } else if (ec == 131800//waypoint
3368                    || ec == 240900)//fire support station
3369            {
3370                if (modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1)) {
3371                    strText = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
3372                    if (strText != null) {
3373                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3374
3375                        //One modifier symbols and modifier goes right of center
3376                        if (ec == 131800)
3377                            x = bounds.left + (int) (bounds.width() * 0.75f);
3378                        else
3379                            x = bounds.left + (bounds.width());
3380                        y = bounds.top + (int) (bounds.height() * 0.5f);
3381                        y = y + (int) ((labelHeight - descent) * 0.5f);
3382
3383                        ti.setLocation(Math.round(x), Math.round(y));
3384                        arrMods.add(ti);
3385                    }
3386                }
3387            }
3388            else if (ec == 131900)//Airfield (AEGIS Only)
3389            {
3390                if (modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1)) {
3391                    strText = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
3392                    if (strText != null) {
3393                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3394
3395                        //One modifier symbols and modifier goes right of symbol
3396
3397                        x = bounds.left + (bounds.width() + bufferXR);
3398
3399                        y = bounds.top + (int) (bounds.height() * 0.5f);
3400                        y = y + (int) ((labelHeight - descent) * 0.5f);
3401
3402                        ti.setLocation(Math.round(x), Math.round(y));
3403                        arrMods.add(ti);
3404                    }
3405                }
3406            }
3407            else if (ec == 180100 //Air Control point
3408                    || ec == 180200) //Communications Check point
3409            {
3410                if (modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1)) {
3411                    strText = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
3412                    if (strText != null) {
3413                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3414                        labelWidth = ti.getTextBounds().width();
3415                        //One modifier symbols and modifier goes just below of center
3416                        x = bounds.left + (int) (bounds.width() * 0.5);
3417                        x = x - (int) (labelWidth * 0.5);
3418                        y = bounds.top + (int) (bounds.height() * 0.5f);
3419                        y = y + (int) (((bounds.height() * 0.5f) - labelHeight) / 2) + labelHeight - descent;
3420
3421                        ti.setLocation(Math.round(x), Math.round(y));
3422                        arrMods.add(ti);
3423                    }
3424                }
3425            } else if (ec == 160300 || //T (target reference point)
3426                    ec == 132000 || //T (Target Handover)
3427                    ec == 240601 || //ap,ap1,x,h (Point/Single Target)
3428                    ec == 240602) //ap (nuclear target)
3429            { //Targets with special modifier positions
3430                if (modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1)
3431                        && ec == 240601)//H //point single target
3432                {
3433                    strText = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
3434                    if (strText != null) {
3435                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3436
3437                        x = RectUtilities.getCenterX(bounds) + (int) (bounds.width() * 0.15f);
3438                        y = bounds.top + (int) (bounds.height() * 0.75f);
3439                        y = y + (int) (labelHeight * 0.5f);
3440
3441                        ti.setLocation(Math.round(x), Math.round(y));
3442                        arrMods.add(ti);
3443                    }
3444                }
3445                if (modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH)
3446                        && ec == 240601)//X point or single target
3447                {
3448                    strText = modifiers.get(Modifiers.X_ALTITUDE_DEPTH);
3449                    if (strText != null) {
3450                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3451                        labelWidth = Math.round(ti.getTextBounds().width());
3452                        x = RectUtilities.getCenterX(bounds) - (int) (bounds.width() * 0.15f);
3453                        x = x - (labelWidth);
3454                        y = bounds.top + (int) (bounds.height() * 0.75f);
3455                        y = y + (int) (labelHeight * 0.5f);
3456
3457                        ti.setLocation(Math.round(x), Math.round(y));
3458                        arrMods.add(ti);
3459                    }
3460                }
3461                strText = null;
3462                if (modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1) && (ec == 160300 || ec == 132000)) {
3463                    strText = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
3464                    if (strText != null) {
3465                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3466
3467                        x = RectUtilities.getCenterX(bounds) + (int) (bounds.width() * 0.15f);
3468                        y = bounds.top + (int) (bounds.height() * 0.30f);
3469
3470                        ti.setLocation(Math.round(x), Math.round(y));
3471                        arrMods.add(ti);
3472                    }
3473                }
3474                if (ec == 240601 || ec == 240602)
3475                {
3476                    if (modifiers.containsKey(Modifiers.AP_TARGET_NUMBER)) {
3477                        strText = modifiers.get(Modifiers.AP_TARGET_NUMBER);
3478                    }
3479                    if (ec == 240601 && modifiers.containsKey(Modifiers.AP1_TARGET_NUMBER_EXTENSION)) {
3480                        if (strText != null)
3481                            strText = strText + "  " + modifiers.get(Modifiers.AP1_TARGET_NUMBER_EXTENSION);
3482                        else
3483                            strText = modifiers.get(Modifiers.AP1_TARGET_NUMBER_EXTENSION);
3484                    }
3485                    if (strText != null) {
3486                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3487
3488                        x = RectUtilities.getCenterX(bounds) + (int) (bounds.width() * 0.15f);
3489                        y = bounds.top + (int) (bounds.height() * 0.30f);
3490
3491                        ti.setLocation(Math.round(x), Math.round(y));
3492                        arrMods.add(ti);
3493                    }
3494                }
3495            }
3496            else if (ec == 213400 && SymbolID.getVersion(symbolID)==SymbolID.Version_APP6Ech2)  //Navigation Reference Point
3497            {
3498                if (modifiers.containsKey(Modifiers.W_DTG_1))
3499                {
3500                    strText = modifiers.get(Modifiers.W_DTG_1);
3501                    if (strText != null) {
3502                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3503
3504                        x = (int)(bounds.left + (bounds.width() * 0.75f));
3505                        y = (int)(bounds.top + (bounds.height() * 0.75f));
3506                        y = y + labelHeight;
3507
3508                        ti.setLocation(Math.round(x), Math.round(y));
3509                        arrMods.add(ti);
3510                    }
3511                }
3512                if (modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1)) {
3513                    strText = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
3514                    if (strText != null) {
3515                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3516
3517                        x = (int)(bounds.left + (bounds.width() * 0.25f)-ti.getTextBounds().width());
3518                        y = (int)(bounds.top + (bounds.height() * 0.25f));
3519
3520                        ti.setLocation(Math.round(x), Math.round(y));
3521                        arrMods.add(ti);
3522                    }
3523                }
3524            }
3525            else if (ec == 132100)//Key Terrain
3526            {
3527                if (modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1)) {
3528                    strText = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
3529                    if (strText != null) {
3530                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3531
3532                        //One modifier symbols and modifier goes right of symbol
3533
3534                        x = bounds.left + (int)(bounds.width() * 0.5) + bufferXL;
3535
3536                        y = bounds.top + (int) (bounds.height() * 0.5f);
3537                        y = y + (int) ((labelHeight - descent) * 0.5f);
3538
3539                        ti.setLocation(Math.round(x), Math.round(y));
3540                        arrMods.add(ti);
3541                    }
3542                }
3543            }
3544            else if (ec == 132300)  //Vital Ground
3545            {
3546                if (modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1)) {
3547                    strText = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
3548                    if (strText != null) {
3549                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3550
3551                        //One modifier symbols and modifier goes bottom right of symbol
3552                        x = (int)(bounds.left + (bounds.width() * 0.88f));
3553
3554                        y = (int)(bounds.top + (bounds.height() * 0.88f));
3555                        y = y + (labelHeight - descent);
3556
3557                        ti.setLocation(Math.round(x), Math.round(y));
3558                        arrMods.add(ti);
3559                    }
3560                }
3561            }
3562            else if(ec == 182600)//Isolated Personnel Location
3563            {
3564                if (modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1)) {
3565                    strText = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
3566                    if (strText != null) {
3567                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3568                        labelWidth = (int)Math.round(ti.getTextBounds().width());
3569
3570                        x = (int)(bounds.left + (bounds.width() * 0.5));
3571                        x = x - (int) (labelWidth * 0.5);
3572                        y = (int)bounds.top - descent;
3573                        ti.setLocation(Math.round(x), Math.round(y));
3574                        arrMods.add(ti);
3575                    }
3576                }
3577                if (modifiers.containsKey(Modifiers.W_DTG_1)) {
3578                    strText = modifiers.get(Modifiers.W_DTG_1);
3579                    if (strText != null) {
3580                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3581                        labelWidth = (int)Math.round(ti.getTextBounds().width());
3582
3583                        x = (int)bounds.left - labelWidth - bufferXL;
3584                        if (!byLabelHeight) {
3585                            y = (int)bounds.top + labelHeight - descent;
3586                        } else {
3587                            //y = bounds.y + ((bounds.getHeight * 0.5) + (labelHeight * 0.5) - (labelHeight + bufferText));
3588                            y = (int)(bounds.top + ((bounds.height() * 0.5) - ((labelHeight - descent) * 0.5) + (-descent - bufferText)));
3589                        }
3590
3591                        ti.setLocation(Math.round(x), Math.round(y));
3592                        arrMods.add(ti);
3593                    }
3594                }
3595                if (modifiers.containsKey(Modifiers.W1_DTG_2)) {
3596                    strText = modifiers.get(Modifiers.W1_DTG_2);
3597                    if (strText != null) {
3598                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3599                        labelWidth = (int)Math.round(ti.getTextBounds().width());
3600
3601                        x = (int)bounds.left - labelWidth - bufferXL;
3602                        if (!byLabelHeight) {
3603                            y = (int)bounds.top + labelHeight - descent;
3604                        } else {
3605                            //y = bounds.y + ((bounds.getHeight * 0.5) + (labelHeight * 0.5) - (labelHeight + bufferText));
3606                            y = (int)(bounds.top + ((bounds.height() * 0.5) - (((labelHeight * 2) - descent) * 0.5) + (-descent - bufferText)));
3607                        }
3608
3609                        ti.setLocation(Math.round(x), Math.round(y));
3610                        arrMods.add(ti);
3611                    }
3612                }
3613            }
3614            else if (SymbolUtilities.isCBRNEvent(symbolID)) //CBRN
3615            {
3616                if (modifiers.containsKey(Modifiers.N_HOSTILE)) {
3617                    strText = modifiers.get(Modifiers.N_HOSTILE);
3618                    if (strText != null) {
3619                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3620
3621                        x = bounds.left + bounds.width() + bufferXR;
3622
3623                        if (!byLabelHeight) {
3624                            y = bounds.top + bounds.height();
3625                        } else {
3626                            y = bounds.top + (int) ((bounds.height() * 0.5f) + ((labelHeight - descent) * 0.5) + (labelHeight - descent + bufferText));
3627                        }
3628
3629                        ti.setLocation(Math.round(x), Math.round(y));
3630                        arrMods.add(ti);
3631                    }
3632
3633                }
3634                if (modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1)) {
3635                    strText = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
3636                    if (strText != null) {
3637                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3638
3639                        x = bounds.left + bounds.width() + bufferXR;
3640                        if (!byLabelHeight) {
3641                            y = bounds.top + labelHeight - descent;
3642                        } else {
3643                            //y = bounds.y + ((bounds.height * 0.5) + (labelHeight * 0.5) - (labelHeight + bufferText));
3644                            y = bounds.top + (int) ((bounds.height() * 0.5f) - ((labelHeight - descent) * 0.5) + (-descent - bufferText));
3645                        }
3646
3647                        ti.setLocation(Math.round(x), Math.round(y));
3648                        arrMods.add(ti);
3649                    }
3650                }
3651                if (modifiers.containsKey(Modifiers.W_DTG_1)) {
3652                    strText = modifiers.get(Modifiers.W_DTG_1);
3653                    if (strText != null) {
3654                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3655                        labelWidth = Math.round(ti.getTextBounds().width());
3656
3657                        x = bounds.left - labelWidth - bufferXL;
3658                        if (!byLabelHeight) {
3659                            y = bounds.top + labelHeight - descent;
3660                        } else {
3661                            //y = bounds.y + ((bounds.height * 0.5) + (labelHeight * 0.5) - (labelHeight + bufferText));
3662                            y = bounds.top + (int) ((bounds.height() * 0.5) - ((labelHeight - descent) * 0.5) + (-descent - bufferText));
3663                        }
3664
3665                        ti.setLocation(Math.round(x), Math.round(y));
3666                        arrMods.add(ti);
3667                    }
3668                }
3669                if ((ec == 281500 || ec == 281600) && modifiers.containsKey(Modifiers.V_EQUIP_TYPE)) {//nuclear event or nuclear fallout producing event
3670                    strText = modifiers.get(Modifiers.V_EQUIP_TYPE);
3671                    if (strText != null) {
3672                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3673
3674                        //subset of nbc, just nuclear
3675                        labelWidth = Math.round(ti.getTextBounds().width());
3676                        x = bounds.left - labelWidth - bufferXL;
3677                        y = bounds.top + (int) ((bounds.height() * 0.5) + ((labelHeight - descent) * 0.5));//((bounds.height / 2) - (labelHeight/2));
3678
3679                        ti.setLocation(Math.round(x), Math.round(y));
3680                        arrMods.add(ti);
3681                    }
3682                }
3683                if (modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1)) {
3684                    strText = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
3685                    if (strText != null) {
3686                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3687                        labelWidth = Math.round(ti.getTextBounds().width());
3688                        x = bounds.left - labelWidth - bufferXL;
3689                        if (!byLabelHeight) {
3690                            y = bounds.top + bounds.height();
3691                        } else {
3692                            //y = bounds.y + ((bounds.height * 0.5) + ((labelHeight-descent) * 0.5) + (labelHeight + bufferText));
3693                            y = bounds.top + (int) ((bounds.height() * 0.5) + ((labelHeight - descent) * 0.5) + (labelHeight - descent + bufferText));
3694                        }
3695                        ti.setLocation(Math.round(x), Math.round(y));
3696                        arrMods.add(ti);
3697                    }
3698                }
3699                if (modifiers.containsKey(Modifiers.Y_LOCATION)) {
3700                    strText = modifiers.get(Modifiers.Y_LOCATION);
3701                    if (strText != null) {
3702                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3703                        labelWidth = Math.round(ti.getTextBounds().width());
3704                        //just NBC
3705                        //x = bounds.left + (bounds.width() * 0.5);
3706                        //x = x - (labelWidth * 0.5);
3707                        x = bounds.left + (int) (bounds.width() * 0.5f);
3708                        x = x - (int) (labelWidth * 0.5f);
3709
3710                        if (!byLabelHeight) {
3711                            y = bounds.top + bounds.height() + labelHeight - descent + bufferY;
3712                        } else {
3713                            y = bounds.top + (int) ((bounds.height() * 0.5) + ((labelHeight - descent) * 0.5) + ((labelHeight + bufferText) * 2) - descent);
3714
3715                        }
3716                        yForY = y + descent; //so we know where to start the DOM arrow.
3717                        ti.setLocation(Math.round(x), Math.round(y));
3718                        arrMods.add(ti);
3719                    }
3720
3721                }
3722                if (modifiers.containsKey(Modifiers.C_QUANTITY)) {
3723                    strText = modifiers.get(Modifiers.C_QUANTITY);
3724                    if (strText != null) {
3725                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3726                        labelWidth = Math.round(ti.getTextBounds().width());
3727                        //subset of NBC, just nuclear
3728                        x = bounds.left + (int) (bounds.width() * 0.5);
3729                        x = x - (int) (labelWidth * 0.5);
3730                        y = bounds.top - descent;
3731                        ti.setLocation(Math.round(x), Math.round(y));
3732                        arrMods.add(ti);
3733                    }
3734
3735                }
3736            }
3737            else if (ec == 270701)//static depiction
3738            {
3739                if (modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1)) {
3740                    strText = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
3741                    if (strText != null) {
3742                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3743                        labelWidth = Math.round(ti.getTextBounds().width());
3744                        x = bounds.left + (int) (bounds.width() * 0.5);
3745                        x = x - (int) (labelWidth * 0.5);
3746                        y = bounds.top - descent;// + (bounds.height * 0.5);
3747                        //y = y + (labelHeight * 0.5);
3748
3749                        ti.setLocation(Math.round(x), Math.round(y));
3750                        arrMods.add(ti);
3751                    }
3752
3753                }
3754                if (modifiers.containsKey(Modifiers.W_DTG_1)) {
3755                    strText = modifiers.get(Modifiers.W_DTG_1);
3756                    if (strText != null) {
3757                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3758                        labelWidth = Math.round(ti.getTextBounds().width());
3759                        x = bounds.left + (int) (bounds.width() * 0.5);
3760                        x = x - (int) (labelWidth * 0.5);
3761                        y = bounds.top + (bounds.height());
3762                        y = y + (labelHeight);
3763
3764                        ti.setLocation(Math.round(x), Math.round(y));
3765                        arrMods.add(ti);
3766                    }
3767                }
3768                if (modifiers.containsKey(Modifiers.N_HOSTILE)) {
3769                    strText = modifiers.get(Modifiers.N_HOSTILE);
3770                    if (strText != null) {
3771                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3772                        TextInfo ti2 = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3773                        labelWidth = Math.round(ti.getTextBounds().width());
3774                        x = bounds.left + (bounds.width()) + bufferXR;//right
3775                        //x = x + labelWidth;//- (labelBounds.width * 0.75);
3776
3777                        duplicate = true;
3778
3779                        x2 = bounds.left;//left
3780                        x2 = x2 - labelWidth - bufferXL;// - (labelBounds.width * 0.25);
3781
3782                        y = bounds.top + (int) (bounds.height() * 0.5);//center
3783                        y = y + (int) ((labelHeight - descent) * 0.5);
3784
3785                        y2 = y;
3786
3787                        ti.setLocation(Math.round(x), Math.round(y));
3788                        ti2.setLocation(Math.round(x2), Math.round(y2));
3789                        arrMods.add(ti);
3790                        arrMods.add(ti2);
3791                    }
3792                }
3793
3794            }
3795            else if(e == 21 && et == 35)//sonobuoys
3796            {
3797                boolean is2525E = (SymbolID.getVersion(symbolID) >= SymbolID.Version_2525E);
3798                //H sitting on center of circle to the right
3799                //T above H
3800                centerPoint = SymbolUtilities.getCMSymbolAnchorPoint(symbolID,RectUtilities.makeRectFFromRect(bounds));
3801                if (modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1)) {
3802                    strText = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
3803                    if (strText != null) {
3804                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3805                        TextInfo ti2 = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3806                        labelWidth = Math.round(ti.getTextBounds().width());
3807                        x = bounds.left + (bounds.width()) + bufferXR;//right
3808                        y = centerPoint.y;
3809
3810                        if(is2525E) {
3811                            x = x - (int)(bounds.width() * 0.2);
3812                            y = (int) (bounds.top + (bounds.height() / 2));
3813                        }
3814
3815                        ti.setLocation(Math.round(x), Math.round(y));
3816                        arrMods.add(ti);
3817                    }
3818                }
3819                if (est == 0 || est == 1 || est == 4 || est == 7 || est == 8 || est == 15) {
3820                    if (modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1)) {
3821                        strText = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
3822                        if (strText != null) {
3823                            ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3824                            TextInfo ti2 = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3825                            labelWidth = Math.round(ti.getTextBounds().width());
3826                            x = (bounds.left + (bounds.width()) + bufferXR - (int)(bounds.width() * 0.2) );//right
3827                            y = centerPoint.y - labelHeight;
3828
3829                            if(is2525E) {
3830                                y = (bounds.top + (bounds.height() / 2)) - labelHeight;
3831                            }
3832
3833                            ti.setLocation(Math.round(x), Math.round(y));
3834                            arrMods.add(ti);
3835                        }
3836                    }
3837                }
3838            }
3839            else if(ec == 282001 || //tower, low
3840                    ec == 282002)   //tower, high
3841            {
3842                if (modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH)) {
3843                    strText = modifiers.get(Modifiers.X_ALTITUDE_DEPTH);
3844                    if (strText != null) {
3845                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3846                        labelWidth = Math.round(ti.getTextBounds().width());
3847                        x = bounds.left + (int) (bounds.width() * 0.7);
3848                        y = bounds.top + labelHeight;// + (bounds.height * 0.5);
3849                        //y = y + (labelHeight * 0.5);
3850
3851                        ti.setLocation(Math.round(x), Math.round(y));
3852                        arrMods.add(ti);
3853                    }
3854
3855                }
3856            }
3857            else if(ec == 180600)//TACAN
3858            {
3859                if (modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1)) {
3860                    strText = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
3861                    if (strText != null) {
3862                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3863                        labelWidth = Math.round(ti.getTextBounds().width());
3864                        x = bounds.left + bounds.width() + bufferXR;
3865                        y = bounds.top + labelHeight;// + (bounds.height * 0.5);
3866                        //y = y + (labelHeight * 0.5);
3867
3868                        ti.setLocation(Math.round(x), Math.round(y));
3869                        arrMods.add(ti);
3870                    }
3871
3872                }
3873            }
3874            else if(ec == 210300)//Defended Asset
3875            {
3876                if (modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1)) {
3877                    strText = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
3878                    if (strText != null) {
3879                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3880                        labelWidth = Math.round(ti.getTextBounds().width());
3881                        x = bounds.left - labelWidth - bufferXL;
3882                        y = bounds.top + labelHeight;// + (bounds.height * 0.5);
3883                        //y = y + (labelHeight * 0.5);
3884
3885                        ti.setLocation(Math.round(x), Math.round(y));
3886                        arrMods.add(ti);
3887                    }
3888
3889                }
3890            }
3891            else if(ec == 210600)//Air Detonation
3892            {
3893                if (modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH)) {
3894                    strText = modifiers.get(Modifiers.X_ALTITUDE_DEPTH);
3895                    if (strText != null) {
3896                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3897                        labelWidth = Math.round(ti.getTextBounds().width());
3898                        x = bounds.left + (bounds.width() + bufferXR);
3899                        y = bounds.top + labelHeight;// + (bounds.height * 0.5);
3900                        //y = y + (labelHeight * 0.5);
3901
3902                        ti.setLocation(Math.round(x), Math.round(y));
3903                        arrMods.add(ti);
3904                    }
3905
3906                }
3907            }
3908            else if(ec == 210800)//Impact Point
3909            {
3910                if (modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1)) {
3911                    strText = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
3912                    if (strText != null) {
3913                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3914                        labelWidth = Math.round(ti.getTextBounds().width());
3915                        x = bounds.left + (int) (bounds.width() * 0.65f);
3916//                  x = x - (labelBounds.width * 0.5);
3917                        y = bounds.top + (int) (bounds.height() * 0.25f);
3918                        y = y + (int) (labelHeight * 0.5f);
3919                        //y = y + (labelHeight * 0.5);
3920
3921                        ti.setLocation(Math.round(x), Math.round(y));
3922                        arrMods.add(ti);
3923                    }
3924
3925                }
3926            }
3927            else if(ec == 211000)//Launched Torpedo
3928            {
3929                if (modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1)) {
3930                    strText = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
3931                    if (strText != null) {
3932                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3933                        labelWidth = Math.round(ti.getTextBounds().width());
3934                        x = (int)(bounds.left + (bounds.width() * 0.5) - (labelWidth/2));
3935                        y = bounds.top - bufferY;
3936
3937                        ti.setLocation(Math.round(x), Math.round(y));
3938                        arrMods.add(ti);
3939                    }
3940
3941                }
3942            }
3943            else if(ec == 214900 || ec == 215600)//General Sea SubSurface Station & General Sea Surface Station
3944            {
3945                if (modifiers.containsKey(Modifiers.W_DTG_1)) {
3946                    strText = modifiers.get(Modifiers.W_DTG_1);
3947                    if (strText != null) {
3948                        ti = new TextInfo(strText + " - ", 0, 0, modifierFont, modifierFontName);
3949                        x = bounds.left + (bounds.width() + bufferXR);
3950                        y = bounds.top + labelHeight;
3951
3952                        ti.setLocation(Math.round(x), Math.round(y));
3953                        arrMods.add(ti);
3954                    }
3955
3956                }
3957                if (modifiers.containsKey(Modifiers.W1_DTG_2)) {
3958                    strText = modifiers.get(Modifiers.W1_DTG_2);
3959                    if (strText != null) {
3960                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3961                        x = bounds.left + (bounds.width() + bufferXR);
3962                        y = bounds.top + (labelHeight * 2);
3963
3964                        ti.setLocation(Math.round(x), Math.round(y));
3965                        arrMods.add(ti);
3966                    }
3967
3968                }
3969                if (modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1)) {
3970                    strText = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
3971                    if (strText != null) {
3972                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3973                        x = bounds.left + (bounds.width() + bufferXR);
3974                        y = bounds.top + (labelHeight * 3);
3975
3976                        ti.setLocation(Math.round(x), Math.round(y));
3977                        arrMods.add(ti);
3978                    }
3979
3980                }
3981            }
3982            else if(ec == 217000)//Shore Control Station
3983            {
3984                if (modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1)) {
3985                    strText = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
3986                    if (strText != null) {
3987                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
3988                        labelWidth = Math.round(ti.getTextBounds().width());
3989                        x = (int)(bounds.left + (bounds.width() * 0.5) - (labelWidth/2));
3990                        y = bounds.top + bounds.height() + labelHeight + bufferY;
3991
3992                        ti.setLocation(Math.round(x), Math.round(y));
3993                        arrMods.add(ti);
3994                    }
3995
3996                }
3997            }
3998            else if(ec == 250600)//Known Point
3999            {
4000                if (modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1)) {
4001                    strText = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
4002                    if (strText != null) {
4003                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
4004                        labelWidth = Math.round(ti.getTextBounds().width());
4005                        x = bounds.left + (bounds.width() + bufferXR);
4006
4007                        if(!RendererSettings.getInstance().getOutlineSPControlMeasures() &&
4008                                !(attributes.containsKey(MilStdAttributes.OutlineSymbol) && Boolean.parseBoolean(attributes.get(MilStdAttributes.OutlineSymbol))))
4009                            x += bufferXR;
4010
4011                        y = bounds.top + (int) (bounds.height() * 0.30f);
4012
4013                        ti.setLocation(Math.round(x), Math.round(y));
4014                        arrMods.add(ti);
4015                    }
4016
4017                }
4018            }
4019            else if(ec == 360100 || ec == 360200 || ec == 360300)//Protection of Cultural Property
4020            {
4021                if (modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1)) {
4022                    strText = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
4023                    if (strText != null) {
4024                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
4025
4026                        //One modifier symbols and modifier goes right of center
4027                        x = (int)(bounds.left + bounds.width() + bufferXR);
4028                        y = (int)(bounds.top + (bounds.height() * 0.6));
4029
4030                        ti.setLocation(Math.round(x), Math.round(y));
4031                        arrMods.add(ti);
4032                    }
4033                }
4034            }
4035        }
4036        else if(ss == SymbolID.SymbolSet_Atmospheric)
4037        {
4038            String modX = null;
4039            if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH))
4040                modX = (modifiers.get(Modifiers.X_ALTITUDE_DEPTH));
4041
4042            if(ec == 162300)//Freezing Level
4043            {
4044                strText = "0" + (char)(176) + ":";
4045                if(modX != null)
4046                    strText += modX;
4047                else
4048                    strText += "?";
4049
4050                ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
4051                labelWidth = Math.round(ti.getTextBounds().width());
4052                //One modifier symbols and modifier goes in center
4053                x = bounds.left + (int) (bounds.width() * 0.5f);
4054                x = x - (int) (labelWidth * 0.5f);
4055                y = bounds.top + (int) (bounds.height() * 0.5f);
4056                y = y + (int) ((labelHeight - modifierFontDescent) * 0.5f);
4057
4058                ti.setLocation(Math.round(x), Math.round(y));
4059                arrMods.add(ti);
4060            }
4061            else if(ec == 162200)//tropopause Level
4062            {
4063                strText = "X?";
4064                if(modX != null)
4065                    strText = modX;
4066
4067                ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
4068                labelWidth = Math.round(ti.getTextBounds().width());
4069                //One modifier symbols and modifier goes in center
4070                x = bounds.left + (int) (bounds.width() * 0.5f);
4071                x = x - (int) (labelWidth * 0.5f);
4072                y = bounds.top + (int) (bounds.height() * 0.5f);
4073                y = y + (int) ((labelHeight - modifierFontDescent) * 0.5f);
4074
4075                ti.setLocation(Math.round(x), Math.round(y));
4076                arrMods.add(ti);
4077            }
4078            else if(ec == 110102)//tropopause Low
4079            {
4080                strText = "X?";
4081                if(modX != null)
4082                    strText = modX;
4083
4084                ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
4085                labelWidth = Math.round(ti.getTextBounds().width());
4086                //One modifier symbols and modifier goes in center
4087                x = bounds.left + (int) (bounds.width() * 0.5f);
4088                x = x - (int) (labelWidth * 0.5f);
4089                y = bounds.top + (int) (bounds.height() * 0.5f);
4090                y = y - descent;
4091
4092                ti.setLocation(Math.round(x), Math.round(y));
4093                arrMods.add(ti);
4094            }
4095            else if(ec == 110202)//tropopause High
4096            {
4097                strText = "X?";
4098                if(modX != null)
4099                    strText = modX;
4100
4101                ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
4102                labelWidth = Math.round(ti.getTextBounds().width());
4103                //One modifier symbols and modifier goes in center
4104                x = bounds.left + (int) (bounds.width() * 0.5f);
4105                x = x - (int) (labelWidth * 0.5f);
4106                y = bounds.top + (int) (bounds.height() * 0.5f);
4107                //y = y + (int) ((labelHeight * 0.5f) + (labelHeight/2));
4108                y = y + (int) (((labelHeight * 0.5f) - (labelHeight/2)) + labelHeight - descent);
4109
4110                ti.setLocation(Math.round(x), Math.round(y));
4111                arrMods.add(ti);
4112            }
4113        }
4114        // </editor-fold>
4115
4116        // <editor-fold defaultstate="collapsed" desc="DOM Arrow">
4117        Point[] domPoints = null;
4118        Rect domBounds = null;
4119
4120        if (modifiers.containsKey(Modifiers.Q_DIRECTION_OF_MOVEMENT) &&
4121                SymbolUtilities.isCBRNEvent(symbolID))//CBRN events
4122        {
4123            strText = modifiers.get(Modifiers.Q_DIRECTION_OF_MOVEMENT);
4124            if(strText != null && SymbolUtilities.isNumber(strText))
4125            {
4126                    float q = Float.parseFloat(strText);
4127                    Rect tempBounds = new Rect(bounds);
4128                    tempBounds.union(RectUtilities.getCenterX(bounds), yForY);
4129        
4130                    domPoints = createDOMArrowPoints(symbolID, tempBounds, sdi.getCenterPoint(), q, false, modifierFontHeight);
4131        
4132                    domBounds = RectUtilities.makeRect(domPoints[0].x, domPoints[0].y, 1, 1);
4133        
4134                    Point temp = null;
4135                    for (int i = 1; i < 6; i++)
4136                    {
4137                        temp = domPoints[i];
4138                        if (temp != null)
4139                        {
4140                            domBounds.union(temp.x, temp.y);
4141                        }
4142                    }
4143                    imageBounds.union(domBounds);
4144            }
4145        }
4146        // </editor-fold>
4147
4148        // <editor-fold defaultstate="collapsed" desc="Build Feint Dummy Indicator">
4149        if (SymbolUtilities.hasFDI(symbolID))
4150        {
4151            //create feint indicator /\
4152            fdiLeft = new Point((int) symbolBounds.left, (int) symbolBounds.top);
4153            fdiRight = new Point((int) (symbolBounds.left + symbolBounds.width()), (int) symbolBounds.top);
4154            fdiTop = new Point(Math.round(RectUtilities.getCenterX(symbolBounds)), Math.round(symbolBounds.top - (symbolBounds.width() * .5f)));
4155
4156
4157            fdiBounds = RectUtilities.makeRect(fdiLeft.x, fdiLeft.y, 1, 1);
4158            fdiBounds.union(fdiTop.x, fdiTop.y);
4159            fdiBounds.union(fdiRight.x, fdiRight.y);
4160
4161            float fdiStrokeWidth = Math.round(RendererSettings.getInstance().getDeviceDPI() / 96f);
4162            RectUtilities.grow(fdiBounds,Math.round(fdiStrokeWidth/2));
4163
4164            ti = new TextInfo("TEST",0,0, modifierFont, modifierFontName);
4165            if (ti != null && SymbolUtilities.isCBRNEvent(symbolID))
4166            {
4167                int shiftY = Math.round(symbolBounds.top - ti.getTextBounds().height() - 2);
4168                fdiLeft.offset(0, shiftY);
4169                fdiTop.offset(0, shiftY);
4170                fdiRight.offset(0, shiftY);
4171                fdiBounds.offset(0, shiftY);
4172            }
4173
4174            imageBounds.union(fdiBounds);
4175
4176        }
4177        // </editor-fold>
4178
4179        // <editor-fold defaultstate="collapsed" desc="Shift Points and Draw">
4180        Rect modifierBounds = null;
4181        if (arrMods != null && arrMods.size() > 0)
4182        {
4183
4184            //build modifier bounds/////////////////////////////////////////
4185            modifierBounds = arrMods.get(0).getTextOutlineBounds();
4186            int size = arrMods.size();
4187            TextInfo tempShape = null;
4188            for (int i = 1; i < size; i++)
4189            {
4190                tempShape = arrMods.get(i);
4191                modifierBounds.union(tempShape.getTextOutlineBounds());
4192            }
4193
4194        }
4195
4196        if (modifierBounds != null || domBounds != null || fdiBounds != null)
4197        {
4198
4199            if (modifierBounds != null)
4200            {
4201                imageBounds.union(modifierBounds);
4202            }
4203            if (domBounds != null)
4204            {
4205                imageBounds.union(domBounds);
4206            }
4207            if (fdiBounds != null)
4208            {
4209                imageBounds.union(fdiBounds);
4210            }
4211
4212            //shift points if needed////////////////////////////////////////
4213            if (sdi instanceof ImageInfo && (imageBounds.left < 0 || imageBounds.top < 0))
4214            {
4215                int shiftX = Math.abs(imageBounds.left);
4216                int shiftY = Math.abs(imageBounds.top);
4217
4218                //shift mobility points
4219                int size = arrMods.size();
4220                TextInfo tempShape = null;
4221                for (int i = 0; i < size; i++)
4222                {
4223                    tempShape = arrMods.get(i);
4224                    tempShape.shift(shiftX, shiftY);
4225                }
4226                if(modifierBounds != null)
4227                    modifierBounds.offset(shiftX, shiftY);
4228
4229                if (domBounds != null)
4230                {
4231                    for (int i = 0; i < 6; i++)
4232                    {
4233                        Point temp = domPoints[i];
4234                        if (temp != null)
4235                        {
4236                            temp.offset(shiftX, shiftY);
4237                        }
4238                    }
4239                    domBounds.offset(shiftX, shiftY);
4240                }
4241
4242                //If there's an FDI
4243                if (fdiBounds != null)
4244                {
4245                    fdiBounds.offset(shiftX, shiftY);
4246                    fdiLeft.offset(shiftX, shiftY);
4247                    fdiTop.offset(shiftX, shiftY);
4248                    fdiRight.offset(shiftX, shiftY);
4249                }
4250
4251                //shift image points
4252                centerPoint.offset(shiftX, shiftY);
4253                symbolBounds.offset(shiftX, shiftY);
4254                imageBounds.offset(shiftX, shiftY);
4255            }
4256
4257
4258            if (attributes.containsKey(MilStdAttributes.TextColor))
4259            {
4260                textColor = RendererUtilities.getColorFromHexString(attributes.get(MilStdAttributes.TextColor));
4261                if(alpha > -1)
4262                    textColor.setAlpha(alpha);
4263            }
4264            if (attributes.containsKey(MilStdAttributes.TextBackgroundColor))
4265            {
4266                textBackgroundColor = RendererUtilities.getColorFromHexString(attributes.get(MilStdAttributes.TextBackgroundColor));
4267                if(alpha > -1)
4268                    textBackgroundColor.setAlpha(alpha);
4269            }
4270
4271            if(sdi instanceof ImageInfo) {
4272                ii = (ImageInfo)sdi;
4273                //Render modifiers//////////////////////////////////////////////////
4274                Bitmap bmp = Bitmap.createBitmap(imageBounds.width(), imageBounds.height(), Config.ARGB_8888);
4275                Canvas ctx = new Canvas(bmp);
4276
4277                //render////////////////////////////////////////////////////////
4278                //draw original icon with potential modifiers.
4279                ctx.drawBitmap(ii.getImage(), symbolBounds.left, symbolBounds.top, null);
4280                //ctx.drawImage(ii.getImage(),imageBoundsOld.left,imageBoundsOld.top);
4281
4282
4283                renderText(ctx, arrMods, textColor, textBackgroundColor, modifierFont);
4284
4285                //draw DOM arrow
4286                if (domBounds != null)
4287                {
4288                    drawDOMArrow(ctx, domPoints, alpha, lineColor);
4289                }
4290
4291                //<editor-fold defaultstate="collapsed" desc="Draw FDI">
4292                if (fdiBounds != null) {
4293
4294                    Paint fdiPaint = new Paint();
4295                    fdiPaint.setAntiAlias(true);
4296                    fdiPaint.setColor(lineColor.toInt());/// setARGB(255, 0, 0, 0);
4297                    if (alpha > -1)
4298                        fdiPaint.setAlpha(alpha);
4299                    fdiPaint.setStyle(Style.STROKE);
4300
4301                    int dpi = RendererSettings.getInstance().getDeviceDPI();
4302                    int lineLength = dpi / 96 * 6;
4303                    int lineGap = dpi / 96 * 4;
4304
4305                    /// ///////////////////////////////////
4306                    //Divide line in 14 parts. line is 3 parts to 2 parts gap
4307                    float distance = RendererUtilities.getDistanceBetweenPoints(fdiTop,fdiLeft);
4308                    //distance = distance / 14f;
4309                    lineGap = (int)((distance / 14f) * 2);
4310                    lineLength = (int)((distance / 14f) * 3);
4311                    /// //////////////////////////////////
4312
4313                    fdiPaint.setPathEffect(new DashPathEffect(new float[]
4314                            {
4315                                    lineLength, lineGap
4316                            }, 0));
4317
4318                    float fdiStrokeWidth = Math.round(dpi / 96f);
4319                    if (fdiStrokeWidth < 2)
4320                        fdiStrokeWidth = 2;
4321
4322                    fdiPaint.setStrokeCap(Cap.ROUND);
4323                    fdiPaint.setStrokeJoin(Join.MITER);
4324                    fdiPaint.setStrokeWidth(fdiStrokeWidth);
4325
4326                    Path fdiPath = new Path();
4327
4328                    fdiPath.moveTo(fdiTop.x, fdiTop.y);
4329                    fdiPath.lineTo(fdiLeft.x, fdiLeft.y);
4330                    fdiPath.moveTo(fdiTop.x, fdiTop.y);
4331                    fdiPath.lineTo(fdiRight.x, fdiRight.y);
4332                    ctx.drawPath(fdiPath, fdiPaint);
4333
4334                    fdiBounds = null;
4335
4336                }
4337                //</editor-fold>
4338
4339                newsdi = new ImageInfo(bmp, centerPoint, symbolBounds);
4340                ctx = null;
4341            }
4342            else if(sdi instanceof SVGSymbolInfo)
4343            {
4344                float strokeWidth = Math.round(RendererSettings.getInstance().getDeviceDPI() / 96f);
4345                if(strokeWidth < 1)
4346                    strokeWidth=1;
4347                String svgStroke = RendererUtilities.colorToHexString(lineColor,false);
4348                String svgStrokeWidth = String.valueOf(strokeWidth);//"3";
4349
4350                ssi = (SVGSymbolInfo)sdi;
4351                StringBuilder sbSVG = new StringBuilder();
4352                sbSVG.append(ssi.getSVG());
4353                sbSVG.append(renderTextElements(arrMods,textColor,textBackgroundColor));
4354
4355                // <editor-fold defaultstate="collapsed" desc="DOM arrow">
4356                if (domBounds != null && domPoints.length == 6)
4357                {
4358                    SVGPath domPath = new SVGPath() ;
4359
4360                    domPath.moveTo(domPoints[0].x, domPoints[0].y);
4361                    if (domPoints[1] != null)
4362                    {
4363                        domPath.lineTo(domPoints[1].x, domPoints[1].y);
4364                    }
4365                    if (domPoints[2] != null)
4366                    {
4367                        domPath.lineTo(domPoints[2].x, domPoints[2].y);
4368                    }
4369                    sbSVG.append(domPath.toSVGElement(svgStroke,Float.parseFloat(svgStrokeWidth),null,1f,1f,null));
4370
4371                    domPath = new SVGPath();
4372
4373                    domPath.moveTo(domPoints[3].x, domPoints[3].y);
4374                    domPath.lineTo(domPoints[4].x, domPoints[4].y);
4375                    domPath.lineTo(domPoints[5].x, domPoints[5].y);
4376                    sbSVG.append(domPath.toSVGElement(null,0f,svgStroke,1f,1f,null));
4377
4378                    domBounds = null;
4379                    domPoints = null;
4380                }
4381                // </editor-fold>
4382
4383                //<editor-fold defaultstate="collapsed" desc="Draw FDI">
4384                if (fdiBounds != null)
4385                {
4386
4387                    /*int dpi = RendererSettings.getInstance().getDeviceDPI();
4388                    int lineLength = dpi / 96 * 6;
4389                    int lineGap = dpi / 96 * 4;
4390                    String svgFDIDashArray = "" + lineLength + " " + lineGap;//*/
4391
4392                    /// ///////////////////////////////////
4393                    //Divide line in 14 parts. line is 3 parts to 2 parts gap
4394                    float distance = RendererUtilities.getDistanceBetweenPoints(fdiTop,fdiLeft);
4395                    //distance = distance / 14f;
4396                    int lineGap = (int)((distance / 14f) * 2);
4397                    int lineLength = (int)((distance / 14f) * 3);
4398                    String svgFDIDashArray = "" + lineLength + " " + lineGap;
4399                    /// //////////////////////////////////
4400
4401                    SVGPath fdiPath = new SVGPath();
4402                    fdiPath.moveTo(fdiTop.x, fdiTop.y);
4403                    fdiPath.lineTo(fdiLeft.x, fdiLeft.y);
4404                    fdiPath.moveTo(fdiTop.x, fdiTop.y);
4405                    fdiPath.lineTo(fdiRight.x, fdiRight.y);//*/
4406
4407                    fdiPath.setLineDash(svgFDIDashArray);
4408
4409                    sbSVG.append(fdiPath.toSVGElement(svgStroke,Float.parseFloat(svgStrokeWidth),null,1f,1f,"round"));
4410                    //sbSVG.append(Shape2SVG.Convert(fdiPath, svgStroke, null, svgStrokeWidth, svgAlpha, svgAlpha, svgFDIDashArray));
4411                }
4412                //</editor-fold>
4413
4414                newsdi = new SVGSymbolInfo(sbSVG.toString(),centerPoint,symbolBounds,imageBounds);
4415            }
4416
4417
4418
4419
4420            // <editor-fold defaultstate="collapsed" desc="Cleanup">
4421            //ctx = null;
4422            // </editor-fold>
4423
4424            return newsdi;
4425
4426        }
4427        else
4428        {
4429            return null;
4430        }
4431        // </editor-fold>
4432
4433    }
4434
4435    /**
4436     * Process modifiers for action points
4437     */
4438    public static SymbolDimensionInfo ProcessTGSPModifiers(SymbolDimensionInfo sdi, String symbolID, Map<String,String> modifiers, Map<String,String> attributes, Color lineColor)
4439    {
4440
4441        Paint modifierFont = getFont(attributes);
4442        float[] hd = getFontHeightandDescent(modifierFont);
4443        float modifierFontHeight = hd[0];
4444        float modifierFontDescent = hd[1];
4445
4446        String modifierFontName = RendererSettings.getInstance().getModiferFontProps()[0];
4447        if(attributes != null && attributes.containsKey(MilStdAttributes.FontFamily))
4448        {
4449            String temp = attributes.get(MilStdAttributes.FontFamily);
4450            if(temp != null && !temp.isEmpty())
4451                modifierFontName = temp;
4452        }
4453
4454        // <editor-fold defaultstate="collapsed" desc="Variables">
4455        ImageInfo ii = null;
4456        SVGSymbolInfo ssi = null;
4457
4458        int bufferXL = 6;
4459        int bufferXR = 4;
4460        int bufferY = 2;
4461        int bufferText = 2;
4462        int centerOffset = 1; //getCenterX/Y function seems to go over by a pixel
4463        int x = 0;
4464        int y = 0;
4465        int x2 = 0;
4466        int y2 = 0;
4467
4468        //Feint Dummy Indicator variables
4469        Rect fdiBounds = null;
4470        Point fdiTop = null;
4471        Point fdiLeft = null;
4472        Point fdiRight = null;
4473
4474        int outlineOffset = RS.getTextOutlineWidth();
4475        int labelHeight = 0;
4476        int labelWidth = 0;
4477        int alpha = -1;
4478        SymbolDimensionInfo newsdi = null;
4479        
4480        Color textColor = lineColor;
4481        Color textBackgroundColor = null;
4482
4483        ArrayList<TextInfo> arrMods = new ArrayList<TextInfo>();
4484        boolean duplicate = false;
4485
4486        MSInfo msi = MSLookup.getInstance().getMSLInfo(symbolID);
4487
4488
4489        if (attributes.containsKey(MilStdAttributes.Alpha))
4490        {
4491            alpha = Integer.parseInt(attributes.get(MilStdAttributes.Alpha));
4492        }
4493
4494        Rect bounds = new Rect(sdi.getSymbolBounds());
4495        Rect symbolBounds = new Rect(sdi.getSymbolBounds());
4496        Point centerPoint = new Point(sdi.getCenterPoint());
4497        Rect imageBounds = new Rect(sdi.getImageBounds());
4498
4499        centerPoint = new Point(Math.round(sdi.getCenterPoint().x), Math.round(sdi.getCenterPoint().y));
4500
4501        boolean byLabelHeight = false;
4502
4503        labelHeight = Math.round(modifierFontHeight + 0.5f);
4504        int maxHeight = (symbolBounds.height());
4505        if ((labelHeight * 3) > maxHeight)
4506        {
4507            byLabelHeight = true;
4508        }
4509
4510        int descent = (int) (modifierFontDescent + 0.5f);
4511        int yForY = -1;
4512
4513        Rect labelBounds1 = null;//text.getPixelBounds(null, 0, 0);
4514        Rect labelBounds2 = null;
4515        String strText = "";
4516        String strText1 = "";
4517        String strText2 = "";
4518        TextInfo text1 = null;
4519        TextInfo text2 = null;
4520
4521        String basicID = SymbolUtilities.getBasicSymbolID(symbolID);
4522
4523        if (outlineOffset > 2)
4524        {
4525            outlineOffset = ((outlineOffset - 1) / 2);
4526        }
4527        else
4528        {
4529            outlineOffset = 0;
4530        }
4531
4532        /*bufferXL += outlineOffset;
4533         bufferXR += outlineOffset;
4534         bufferY += outlineOffset;
4535         bufferText += outlineOffset;*/
4536        // </editor-fold>
4537        // <editor-fold defaultstate="collapsed" desc="Process Modifiers">
4538        TextInfo ti = null;
4539
4540        {
4541            if (msi.getModifiers().contains(Modifiers.N_HOSTILE) && modifiers.containsKey(Modifiers.N_HOSTILE))
4542            {
4543                strText = modifiers.get(Modifiers.N_HOSTILE);
4544                if(strText != null)
4545                {
4546                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
4547        
4548                        x = bounds.left + bounds.width() + bufferXR;
4549        
4550                        if (!byLabelHeight)
4551                        {
4552                            y = ((bounds.height() / 3) * 2);//checkpoint, get box above the point
4553                            y = bounds.top + y;
4554                        }
4555                        else
4556                        {
4557                            //y = ((labelHeight + bufferText) * 3);
4558                            //y = bounds.y + y - descent;
4559                            y = bounds.top + bounds.height();
4560                        }
4561        
4562                        ti.setLocation(x, y);
4563                        arrMods.add(ti);
4564                }
4565
4566            }
4567            if (msi.getModifiers().contains(Modifiers.H_ADDITIONAL_INFO_1) && modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
4568            {
4569                strText = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
4570                if(strText != null)
4571                {
4572                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
4573                        labelWidth = Math.round(ti.getTextBounds().width());
4574        
4575                        x = bounds.left + (int) (bounds.width() * 0.5f);
4576                        x = x - (int) (labelWidth * 0.5f);
4577                        y = bounds.top - descent;
4578        
4579                        ti.setLocation(x, y);
4580                        arrMods.add(ti);
4581                }
4582            }
4583            if (msi.getModifiers().contains(Modifiers.H1_ADDITIONAL_INFO_2) && modifiers.containsKey(Modifiers.H1_ADDITIONAL_INFO_2))
4584            {
4585                strText = modifiers.get(Modifiers.H1_ADDITIONAL_INFO_2);
4586                if(strText != null)
4587                {
4588                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
4589                        labelWidth = Math.round(ti.getTextBounds().width());
4590        
4591                        x = bounds.left + (int) (bounds.width() * 0.5);
4592                        x = x - (int) (labelWidth * 0.5);
4593                    y = bounds.top + labelHeight - descent + (int) (bounds.height() * 0.07);
4594        
4595                        ti.setLocation(x, y);
4596                        arrMods.add(ti);
4597                }
4598            }
4599            if (msi.getModifiers().contains(Modifiers.A_SYMBOL_ICON))
4600            {
4601                if(modifiers.containsKey(Modifiers.A_SYMBOL_ICON))
4602                    strText = modifiers.get(Modifiers.A_SYMBOL_ICON);
4603                else if(SymbolID.getEntityCode(symbolID)==321706)//NATO Multiple Supply Class Point
4604                    strText = "ALL?";//make it clear the required 'A' value wasn't set for this symbol.
4605
4606                if(strText != null)
4607                {
4608                    ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
4609                    labelWidth = Math.round(ti.getTextBounds().width());
4610
4611                    x = bounds.left + (int) (bounds.width() * 0.5);
4612                    x = x - (int) (labelWidth * 0.5);
4613                    y = bounds.top + labelHeight - descent + (int) (bounds.height() * 0.07);
4614
4615                    ti.setLocation(x, y);
4616                    arrMods.add(ti);
4617                }
4618            }
4619            if (msi.getModifiers().contains(Modifiers.W_DTG_1) && modifiers.containsKey(Modifiers.W_DTG_1))
4620            {
4621                strText = modifiers.get(Modifiers.W_DTG_1);
4622                if(strText != null)
4623                {
4624                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
4625                        labelWidth = Math.round(ti.getTextBounds().width());
4626        
4627                        x = bounds.left - labelWidth - bufferXL;
4628                        y = bounds.top + labelHeight - descent;
4629        
4630                        ti.setLocation(x, y);
4631                        arrMods.add(ti);
4632                }
4633            }
4634            if (msi.getModifiers().contains(Modifiers.W1_DTG_2) && modifiers.containsKey(Modifiers.W1_DTG_2))
4635            {
4636                strText = modifiers.get(Modifiers.W1_DTG_2);
4637                if(strText != null)
4638                {
4639                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
4640                        labelWidth = Math.round(ti.getTextBounds().width());
4641        
4642                        x = bounds.left - labelWidth - bufferXL;
4643        
4644                        y = ((labelHeight - descent + bufferText) * 2);
4645                        y = bounds.top + y;
4646        
4647                        ti.setLocation(x, y);
4648                        arrMods.add(ti);
4649                }
4650            }
4651            if (msi.getModifiers().contains(Modifiers.T_UNIQUE_DESIGNATION_1) && modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
4652            {
4653                strText = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
4654                if(strText != null)
4655                {
4656                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
4657        
4658                        x = bounds.left + bounds.width() + bufferXR;
4659                        y = bounds.top + labelHeight - descent;
4660        
4661                        ti.setLocation(x, y);
4662                        arrMods.add(ti);
4663                }
4664            }
4665            if (msi.getModifiers().contains(Modifiers.T1_UNIQUE_DESIGNATION_2) && modifiers.containsKey(Modifiers.T1_UNIQUE_DESIGNATION_2))
4666            {
4667                strText = modifiers.get(Modifiers.T1_UNIQUE_DESIGNATION_2);
4668                if(strText != null)
4669                {
4670                        ti = new TextInfo(strText, 0, 0, modifierFont, modifierFontName);
4671                        labelWidth = Math.round(ti.getTextBounds().width());
4672        
4673                        //points
4674                        x = bounds.left + (int) (bounds.width() * 0.5);
4675                        x = x - (int) (labelWidth * 0.5);
4676                        //y = bounds.y + (bounds.height * 0.5);
4677        
4678                        y = (int) ((bounds.height() * 0.55));//633333333
4679                        y = bounds.top + y;
4680
4681                    int ec = SymbolID.getEntityCode(symbolID);
4682                    if((ec >= 281800 && ec <= 281809) || ec == 321100)
4683                    {
4684                        y = (int) ((bounds.height() * 0.63));
4685                        y = (int)bounds.top + y;
4686                    }
4687        
4688                        ti.setLocation(x, y);
4689                        arrMods.add(ti);
4690                }
4691            }
4692            // <editor-fold defaultstate="collapsed" desc="Build Feint Dummy Indicator">
4693            if (SymbolUtilities.hasFDI(symbolID))
4694            {
4695                //create feint indicator /\
4696                fdiLeft = new Point((int) symbolBounds.left, (int) symbolBounds.top);
4697                fdiRight = new Point((int) (symbolBounds.left + symbolBounds.width()), (int) symbolBounds.top);
4698                fdiTop = new Point(Math.round(RectUtilities.getCenterX(symbolBounds)), Math.round(symbolBounds.top - (symbolBounds.width() * .5f)));
4699
4700
4701                fdiBounds = RectUtilities.makeRect(fdiLeft.x, fdiLeft.y, 1, 1);
4702                fdiBounds.union(fdiTop.x, fdiTop.y);
4703                fdiBounds.union(fdiRight.x, fdiRight.y);
4704
4705                float fdiStrokeWidth = Math.round(RendererSettings.getInstance().getDeviceDPI() / 96f);
4706                RectUtilities.grow(fdiBounds,Math.round(fdiStrokeWidth/2));
4707
4708                ti = new TextInfo("TEST",0,0, modifierFont, modifierFontName);
4709                if (ti != null)
4710                {
4711                    int shiftY = Math.round(symbolBounds.top - ti.getTextBounds().height() - 2);
4712                    fdiLeft.offset(0, shiftY);
4713                    fdiTop.offset(0, shiftY);
4714                    fdiRight.offset(0, shiftY);
4715                    fdiBounds.offset(0, shiftY);
4716                }
4717
4718                imageBounds.union(fdiBounds);
4719
4720            }
4721            // </editor-fold>
4722        }
4723
4724        // </editor-fold>
4725        // <editor-fold defaultstate="collapsed" desc="Shift Points and Draw">
4726        Rect modifierBounds = null;
4727        if (arrMods != null && arrMods.size() > 0)
4728        {
4729
4730            //build modifier bounds/////////////////////////////////////////
4731            modifierBounds = arrMods.get(0).getTextOutlineBounds();
4732            int size = arrMods.size();
4733            TextInfo tempShape = null;
4734            for (int i = 1; i < size; i++)
4735            {
4736                tempShape = arrMods.get(i);
4737                modifierBounds.union(tempShape.getTextOutlineBounds());
4738            }
4739
4740        }
4741
4742        if(fdiBounds != null)
4743        {
4744            if(modifierBounds != null)
4745                modifierBounds.union(fdiBounds);
4746            else
4747                modifierBounds = fdiBounds;
4748        }
4749
4750        if (modifierBounds != null)
4751        {
4752
4753            imageBounds.union(modifierBounds);
4754
4755            //shift points if needed////////////////////////////////////////
4756            if (sdi instanceof ImageInfo && (imageBounds.left < 0 || imageBounds.top < 0))
4757            {
4758                int shiftX = Math.abs(imageBounds.left);
4759                int shiftY = Math.abs(imageBounds.top);
4760
4761                //shift mobility points
4762                int size = arrMods.size();
4763                TextInfo tempShape = null;
4764                for (int i = 0; i < size; i++)
4765                {
4766                    tempShape = arrMods.get(i);
4767                    tempShape.shift(shiftX, shiftY);
4768                }
4769                modifierBounds.offset(shiftX, shiftY);
4770
4771                //shift image points
4772                centerPoint.offset(shiftX, shiftY);
4773                symbolBounds.offset(shiftX, shiftY);
4774                imageBounds.offset(shiftX, shiftY);
4775
4776                //If there's an FDI
4777                if (fdiBounds != null)
4778                {
4779                    fdiBounds.offset(shiftX, shiftY);
4780                    fdiLeft.offset(shiftX, shiftY);
4781                    fdiTop.offset(shiftX, shiftY);
4782                    fdiRight.offset(shiftX, shiftY);
4783                }
4784            }
4785
4786            if (attributes.containsKey(MilStdAttributes.TextColor))
4787            {
4788                textColor = RendererUtilities.getColorFromHexString(attributes.get(MilStdAttributes.TextColor));
4789                if(alpha > -1)
4790                    textColor.setAlpha(alpha);
4791            }
4792            if (attributes.containsKey(MilStdAttributes.TextBackgroundColor))
4793            {
4794                textBackgroundColor = RendererUtilities.getColorFromHexString(attributes.get(MilStdAttributes.TextBackgroundColor));
4795                if(alpha > -1)
4796                    textBackgroundColor.setAlpha(alpha);
4797            }
4798
4799            if(sdi instanceof ImageInfo)
4800            {
4801                ii = (ImageInfo) sdi;
4802                //Render modifiers//////////////////////////////////////////////////
4803                Bitmap bmp = Bitmap.createBitmap(imageBounds.width(), imageBounds.height(), Config.ARGB_8888);
4804                Canvas ctx = new Canvas(bmp);
4805
4806                //draw original icon with potential modifiers.
4807                ctx.drawBitmap(ii.getImage(), symbolBounds.left, symbolBounds.top, null);
4808                //ctx.drawImage(ii.getImage(),imageBoundsOld.left,imageBoundsOld.top);
4809
4810
4811                renderText(ctx, arrMods, textColor, textBackgroundColor, modifierFont);
4812
4813                //<editor-fold defaultstate="collapsed" desc="Draw FDI">
4814                if (fdiBounds != null) {
4815
4816                    Paint fdiPaint = new Paint();
4817                    fdiPaint.setAntiAlias(true);
4818                    fdiPaint.setColor(lineColor.toInt());/// setARGB(255, 0, 0, 0);
4819                    if (alpha > -1)
4820                        fdiPaint.setAlpha(alpha);
4821                    fdiPaint.setStyle(Style.STROKE);
4822
4823                    int dpi = RendererSettings.getInstance().getDeviceDPI();
4824                    int lineLength = dpi / 96 * 6;
4825                    int lineGap = dpi / 96 * 4;
4826
4827                    /// ///////////////////////////////////
4828                    //Divide line in 14 parts. line is 3 parts to 2 parts gap
4829                    float distance = RendererUtilities.getDistanceBetweenPoints(fdiTop,fdiLeft);
4830                    //distance = distance / 14f;
4831                    lineGap = (int)((distance / 14f) * 2);
4832                    lineLength = (int)((distance / 14f) * 3);
4833                    /// //////////////////////////////////
4834
4835                    fdiPaint.setPathEffect(new DashPathEffect(new float[]
4836                            {
4837                                    lineLength, lineGap
4838                            }, 0));
4839
4840                    float fdiStrokeWidth = Math.round(dpi / 96f);
4841                    if (fdiStrokeWidth < 2)
4842                        fdiStrokeWidth = 2;
4843
4844                    fdiPaint.setStrokeCap(Cap.ROUND);
4845                    fdiPaint.setStrokeJoin(Join.MITER);
4846                    fdiPaint.setStrokeWidth(fdiStrokeWidth);
4847
4848                    Path fdiPath = new Path();
4849
4850                    fdiPath.moveTo(fdiTop.x, fdiTop.y);
4851                    fdiPath.lineTo(fdiLeft.x, fdiLeft.y);
4852                    fdiPath.moveTo(fdiTop.x, fdiTop.y);
4853                    fdiPath.lineTo(fdiRight.x, fdiRight.y);
4854                    ctx.drawPath(fdiPath, fdiPaint);
4855
4856                    fdiBounds = null;
4857
4858                }
4859                //</editor-fold>
4860
4861                newsdi = new ImageInfo(bmp, centerPoint, symbolBounds);
4862            }
4863            else if(sdi instanceof SVGSymbolInfo)
4864            {
4865                String svgStroke = RendererUtilities.colorToHexString(lineColor,false);
4866                String svgStrokeWidth = "3";
4867                String svgAlpha = null;
4868                if(alpha > -1)
4869                    svgAlpha = String.valueOf(alpha);
4870                ssi = (SVGSymbolInfo)sdi;
4871                StringBuilder sbSVG = new StringBuilder();
4872                sbSVG.append(ssi.getSVG());
4873                sbSVG.append(renderTextElements(arrMods,textColor,textBackgroundColor));
4874
4875                //<editor-fold defaultstate="collapsed" desc="Draw FDI">
4876                if (fdiBounds != null)
4877                {
4878                    /*int dpi = RendererSettings.getInstance().getDeviceDPI();
4879                    int lineLength = dpi / 96 * 6;
4880                    int lineGap = dpi / 96 * 4;
4881                    String svgFDIDashArray = "" + lineLength + " " + lineGap;//*/
4882
4883                    /// ///////////////////////////////////
4884                    //Divide line in 14 parts. line is 3 parts to 2 parts gap
4885                    float distance = RendererUtilities.getDistanceBetweenPoints(fdiTop,fdiLeft);
4886                    //distance = distance / 14f;
4887                    int lineGap = (int)((distance / 14f) * 2);
4888                    int lineLength = (int)((distance / 14f) * 3);
4889                    String svgFDIDashArray = "" + lineLength + " " + lineGap;
4890                    /// //////////////////////////////////
4891
4892                    SVGPath fdiPath = new SVGPath();
4893                    fdiPath.moveTo(fdiTop.x, fdiTop.y);
4894                    fdiPath.lineTo(fdiLeft.x, fdiLeft.y);
4895                    fdiPath.moveTo(fdiTop.x, fdiTop.y);
4896                    fdiPath.lineTo(fdiRight.x, fdiRight.y);//*/
4897
4898                    fdiPath.setLineDash(svgFDIDashArray);
4899                    sbSVG.append(fdiPath.toSVGElement(svgStroke,Float.parseFloat(svgStrokeWidth),null,1f,1f,"round"));
4900                    //sbSVG.append(Shape2SVG.Convert(fdiPath, svgStroke, null, svgStrokeWidth, svgAlpha, svgAlpha, svgFDIDashArray));
4901                }
4902                //</editor-fold>
4903
4904                newsdi = new SVGSymbolInfo(sbSVG.toString(),centerPoint,symbolBounds,imageBounds);
4905            }
4906
4907            // <editor-fold defaultstate="collapsed" desc="Cleanup">
4908            //ctx = null;
4909
4910            // </editor-fold>
4911        }
4912        // </editor-fold>
4913        return newsdi;
4914
4915    }
4916
4917    private static SymbolDimensionInfo shiftUnitPointsAndDraw(ArrayList<TextInfo> tiArray, SymbolDimensionInfo sdi, Map<String,String> attributes, Paint modifierFont)
4918    {
4919
4920        ImageInfo ii = null;
4921        SVGSymbolInfo ssi = null;
4922        SymbolDimensionInfo newsdi = null;
4923
4924        int alpha = -1;
4925
4926
4927        if (attributes != null && attributes.containsKey(MilStdAttributes.Alpha))
4928        {
4929            alpha = Integer.parseInt(attributes.get(MilStdAttributes.Alpha));
4930        }
4931
4932        Color textColor = Color.BLACK;
4933        Color textBackgroundColor = null;
4934
4935        Rect symbolBounds = new Rect(sdi.getSymbolBounds());
4936        Point centerPoint = new Point(sdi.getCenterPoint());
4937        Rect imageBounds = new Rect(sdi.getImageBounds());
4938        Rect imageBoundsOld = new Rect(sdi.getImageBounds());
4939
4940        Rect modifierBounds = null;
4941        if (tiArray != null && tiArray.size() > 0)
4942        {
4943
4944            //build modifier bounds/////////////////////////////////////////
4945            modifierBounds = tiArray.get(0).getTextOutlineBounds();
4946            int size = tiArray.size();
4947            TextInfo tempShape = null;
4948            for (int i = 1; i < size; i++)
4949            {
4950                tempShape = tiArray.get(i);
4951                modifierBounds.union(tempShape.getTextOutlineBounds());
4952            }
4953
4954        }
4955
4956        if (modifierBounds != null)
4957        {
4958
4959            imageBounds.union(modifierBounds);
4960
4961            //shift points if needed////////////////////////////////////////
4962            if (sdi instanceof ImageInfo && (imageBounds.left < 0 || imageBounds.top < 0))
4963            {
4964                int shiftX = Math.round(Math.abs(imageBounds.left)),
4965                        shiftY = Math.round(Math.abs(imageBounds.top));
4966
4967                //shift mobility points
4968                int size = tiArray.size();
4969                TextInfo tempShape = null;
4970                for (int i = 0; i < size; i++)
4971                {
4972                    tempShape = tiArray.get(i);
4973                    tempShape.shift(shiftX, shiftY);
4974                }
4975                RectUtilities.shift(modifierBounds, shiftX, shiftY);
4976                //modifierBounds.shift(shiftX,shiftY);
4977
4978                //shift image points
4979                centerPoint.offset(shiftX, shiftY);
4980                RectUtilities.shift(symbolBounds, shiftX, shiftY);
4981                RectUtilities.shift(imageBounds, shiftX, shiftY);
4982                RectUtilities.shift(imageBoundsOld, shiftX, shiftY);
4983                /*centerPoint.shift(shiftX, shiftY);
4984                 symbolBounds.shift(shiftX, shiftY);
4985                 imageBounds.shift(shiftX, shiftY);
4986                 imageBoundsOld.shift(shiftX, shiftY);//*/
4987            }
4988
4989            if (attributes != null && attributes.containsKey(MilStdAttributes.TextColor))
4990            {
4991                textColor = RendererUtilities.getColorFromHexString(attributes.get(MilStdAttributes.TextColor));
4992                if(alpha > -1)
4993                    textColor.setAlpha(alpha);
4994            }
4995            if (attributes != null && attributes.containsKey(MilStdAttributes.TextBackgroundColor))
4996            {
4997                textBackgroundColor = RendererUtilities.getColorFromHexString(attributes.get(MilStdAttributes.TextBackgroundColor));
4998                if(alpha > -1)
4999                    textBackgroundColor.setAlpha(alpha);
5000            }
5001
5002            if(sdi instanceof ImageInfo)
5003            {
5004                ii = (ImageInfo) sdi;
5005
5006                Bitmap bmp = Bitmap.createBitmap(imageBounds.width(), imageBounds.height(), Config.ARGB_8888);
5007                Canvas ctx = new Canvas(bmp);
5008
5009                //render////////////////////////////////////////////////////////
5010                //draw original icon with potential modifiers.
5011                ctx.drawBitmap(ii.getImage(), imageBoundsOld.left, imageBoundsOld.top, null);
5012                //ctx.drawImage(ii.getImage(),imageBoundsOld.left,imageBoundsOld.top);
5013
5014                renderText(ctx, tiArray, textColor, textBackgroundColor, modifierFont);
5015
5016                newsdi = new ImageInfo(bmp, centerPoint, symbolBounds);
5017            }
5018            else if(sdi instanceof SVGSymbolInfo)
5019            {
5020                ssi = (SVGSymbolInfo)sdi;
5021                StringBuilder sb = new StringBuilder();
5022                sb.append(ssi.getSVG());
5023                sb.append(renderTextElements(tiArray,textColor,textBackgroundColor));
5024                newsdi = new SVGSymbolInfo(sb.toString(),centerPoint,symbolBounds,imageBounds);
5025            }
5026        }
5027
5028        if(newsdi == null)
5029            newsdi = sdi;
5030
5031        return newsdi;
5032    }
5033    private static String renderTextElement(ArrayList<TextInfo> tiArray, Color color, Color backgroundColor)
5034    {
5035        StringBuilder sbSVG = new StringBuilder();
5036
5037        String svgStroke = RendererUtilities.colorToHexString(RendererUtilities.getIdealOutlineColor(color),false);
5038        if(backgroundColor != null)
5039            svgStroke = RendererUtilities.colorToHexString(backgroundColor,false);
5040
5041        String svgFill = RendererUtilities.colorToHexString(color,false);
5042        String svgStrokeWidth = String.valueOf(RendererSettings.getInstance().getTextOutlineWidth());
5043        for (TextInfo ti : tiArray) {
5044            sbSVG.append(Shape2SVG.Convert(ti, svgStroke,svgFill,svgStrokeWidth,null,null,null));
5045            sbSVG.append("\n");
5046        }
5047
5048        return sbSVG.toString();
5049    }
5050
5051    private static String renderTextElements(ArrayList<TextInfo> tiArray, Color color, Color backgroundColor)
5052    {
5053        String style = null;
5054        String name = tiArray.get(0).getFontName();//"SansSerif";
5055        if(!name.endsWith("serif"))
5056            name += ", sans-serif";
5057        String size = String.valueOf(tiArray.get(0).getFontSize());
5058        String weight = null;
5059        String anchor = null;//"start";
5060        if(tiArray.get(0).getFontStyle() == Typeface.BOLD)
5061            weight = "bold";
5062        StringBuilder sbSVG = new StringBuilder();
5063
5064        String svgStroke = RendererUtilities.colorToHexString(RendererUtilities.getIdealOutlineColor(color),false);
5065        if(backgroundColor != null)
5066            svgStroke = RendererUtilities.colorToHexString(backgroundColor,false);
5067
5068        String svgFill = RendererUtilities.colorToHexString(color,false);
5069        String svgStrokeWidth = String.valueOf(RendererSettings.getInstance().getTextOutlineWidth());
5070        sbSVG.append("\n<g");
5071        sbSVG.append(" font-family=\"").append(name).append('"');
5072        sbSVG.append(" font-size=\"").append(size).append("px\"");
5073        if(weight != null)
5074            sbSVG.append(" font-weight=\"").append(weight).append("\"");
5075        sbSVG.append(" alignment-baseline=\"alphabetic\"");//
5076        sbSVG.append(">");
5077
5078        for (TextInfo ti : tiArray) {
5079            sbSVG.append(Shape2SVG.ConvertForGroup(ti, svgStroke,svgFill,svgStrokeWidth,null,null,null));
5080            sbSVG.append("\n");
5081        }
5082        sbSVG.append("</g>\n");
5083
5084        return sbSVG.toString();
5085    }
5086    private static void renderText(Canvas ctx, ArrayList<TextInfo> tiArray, Color color, Color backgroundColor, Paint font)
5087    {
5088        ModifierRenderer.renderText(ctx, (TextInfo[]) tiArray.toArray(new TextInfo[0]), color, backgroundColor, font);
5089    }
5090
5091    /**
5092     * 
5093     * @param ctx
5094     * @param tiArray
5095     * @param color
5096     * @param backgroundColor 
5097     */
5098    public static void renderText(Canvas ctx, TextInfo[] tiArray, Color color, Color backgroundColor, Paint modifierFont)
5099    {
5100        /*for (TextInfo textInfo : tiArray) 
5101         {
5102         ctx.drawText(textInfo.getText(), textInfo.getLocation().x, textInfo.getLocation().y, modifierFont);    
5103         }*/
5104
5105        int size = tiArray.length;
5106
5107        int tbm = RS.getTextBackgroundMethod();
5108        int outlineWidth = RS.getTextOutlineWidth();
5109
5110        if (color == null)
5111        {
5112            color = Color.BLACK;
5113        }
5114
5115        Color outlineColor = null;
5116        
5117        if(backgroundColor != null)
5118            outlineColor = backgroundColor;
5119        else
5120            outlineColor = RendererUtilities.getIdealOutlineColor(color);
5121
5122        if (tbm == RendererSettings.TextBackgroundMethod_OUTLINE_QUICK)
5123        {
5124            synchronized (modifierFontMutex) {
5125                //draw text outline
5126                modifierFont.setStyle(Style.FILL);
5127                modifierFont.setStrokeWidth(RS.getTextOutlineWidth());
5128                modifierFont.setColor(outlineColor.toInt());
5129
5130                if (outlineWidth > 2)
5131                    outlineWidth = 2;
5132
5133                if (outlineWidth > 0) {
5134                    for (int i = 0; i < size; i++) {
5135                        TextInfo textInfo = tiArray[i];
5136                        if (outlineWidth > 0) {
5137                            for (int j = 1; j <= outlineWidth; j++) {
5138                                if (j == 1) {
5139                                    ctx.drawText(textInfo.getText(), textInfo.getLocation().x - j, textInfo.getLocation().y - j, modifierFont);
5140                                    ctx.drawText(textInfo.getText(), textInfo.getLocation().x + j, textInfo.getLocation().y - j, modifierFont);
5141                                    ctx.drawText(textInfo.getText(), textInfo.getLocation().x - j, textInfo.getLocation().y + j, modifierFont);
5142                                    ctx.drawText(textInfo.getText(), textInfo.getLocation().x + j, textInfo.getLocation().y + j, modifierFont);
5143
5144                                    ctx.drawText(textInfo.getText(), textInfo.getLocation().x - j, textInfo.getLocation().y, modifierFont);
5145                                    ctx.drawText(textInfo.getText(), textInfo.getLocation().x + j, textInfo.getLocation().y, modifierFont);
5146
5147                                } else {
5148                                    ctx.drawText(textInfo.getText(), textInfo.getLocation().x - j, textInfo.getLocation().y - j, modifierFont);
5149                                    ctx.drawText(textInfo.getText(), textInfo.getLocation().x + j, textInfo.getLocation().y - j, modifierFont);
5150                                    ctx.drawText(textInfo.getText(), textInfo.getLocation().x - j, textInfo.getLocation().y + j, modifierFont);
5151                                    ctx.drawText(textInfo.getText(), textInfo.getLocation().x + j, textInfo.getLocation().y + j, modifierFont);
5152
5153                                    ctx.drawText(textInfo.getText(), textInfo.getLocation().x - j, textInfo.getLocation().y, modifierFont);
5154                                    ctx.drawText(textInfo.getText(), textInfo.getLocation().x + j, textInfo.getLocation().y, modifierFont);
5155
5156                                    ctx.drawText(textInfo.getText(), textInfo.getLocation().x, textInfo.getLocation().y + j, modifierFont);
5157                                    ctx.drawText(textInfo.getText(), textInfo.getLocation().x, textInfo.getLocation().y - j, modifierFont);
5158                                }
5159
5160                            }
5161
5162                        }
5163
5164                    }
5165                }
5166                //draw text
5167                modifierFont.setColor(color.toInt());
5168
5169                for (int j = 0; j < size; j++) {
5170                    TextInfo textInfo = tiArray[j];
5171                    ctx.drawText(textInfo.getText(), textInfo.getLocation().x, textInfo.getLocation().y, modifierFont);
5172                /*Paint outline = new Paint();
5173                 outline.setStyle(Style.STROKE);
5174                 outline.setColor(Color.red.toInt());
5175                 outline.setAlpha(155);
5176                 outline.setStrokeWidth(1f);
5177                 ctx.drawRect(textInfo.getTextBounds(), outline);
5178                 outline.setColor(Color.blue.toInt());
5179                 ctx.drawRect(textInfo.getTextOutlineBounds(), outline);//*/
5180                }
5181            }
5182        }
5183        else if (tbm == RendererSettings.TextBackgroundMethod_OUTLINE)
5184        {
5185            synchronized (modifierFontMutex) {
5186                //draw text outline
5187                //draw text outline
5188                modifierFont.setStyle(Style.STROKE);
5189                modifierFont.setStrokeWidth(RS.getTextOutlineWidth());
5190                modifierFont.setColor(outlineColor.toInt());
5191                if (outlineWidth > 0) {
5192                    for (int i = 0; i < size; i++) {
5193                        TextInfo textInfo = tiArray[i];
5194                        ctx.drawText(textInfo.getText(), textInfo.getLocation().x, textInfo.getLocation().y, modifierFont);
5195                    }
5196                }
5197                //draw text
5198                modifierFont.setColor(color.toInt());
5199                modifierFont.setStyle(Style.FILL);
5200                for (int j = 0; j < size; j++) {
5201                    TextInfo textInfo = tiArray[j];
5202                    ctx.drawText(textInfo.getText(), textInfo.getLocation().x, textInfo.getLocation().y, modifierFont);
5203                }
5204            }
5205        }
5206        else if (tbm == RendererSettings.TextBackgroundMethod_COLORFILL)
5207        {
5208            synchronized (modifierFontMutex) {
5209                Paint rectFill = new Paint();
5210                rectFill.setStyle(Paint.Style.FILL);
5211                rectFill.setColor(outlineColor.toARGB());
5212
5213
5214                //draw rectangle
5215                for (int k = 0; k < size; k++) {
5216                    TextInfo textInfo = tiArray[k];
5217                    ctx.drawRect(textInfo.getTextOutlineBounds(), rectFill);
5218                }
5219                //draw text
5220                modifierFont.setColor(color.toInt());
5221                modifierFont.setStyle(Style.FILL);
5222                for (int j = 0; j < size; j++) {
5223                    TextInfo textInfo = tiArray[j];
5224                    ctx.drawText(textInfo.getText(), textInfo.getLocation().x, textInfo.getLocation().y, modifierFont);
5225                }
5226            }
5227        }
5228        else if (tbm == RendererSettings.TextBackgroundMethod_NONE)
5229        {
5230            synchronized (modifierFontMutex) {
5231                modifierFont.setColor(color.toInt());
5232                modifierFont.setStyle(Style.FILL);
5233                for (int j = 0; j < size; j++) {
5234                    TextInfo textInfo = tiArray[j];
5235                    ctx.drawText(textInfo.getText(), textInfo.getLocation().x, textInfo.getLocation().y, modifierFont);
5236                }
5237            }
5238        }
5239    }
5240
5241    /**
5242     *
5243     * @param symbolID
5244     * @param modifiers
5245     * @return int[] where {xposition (-1 left, 0 centered, 1 right), yposition (0 centered, 1+ goes up, 1- goes down),
5246     * centered (0-no, 1-yes)} -999 means passed modifier is not supported by this symbol
5247     */
5248    private static List<Modifier> getLabelPositionIndexes(String symbolID, Map<String,String> modifiers, Map<String,String> attributes)
5249    {
5250        List<Modifier> mods = null;
5251        if(modifiers != null && !modifiers.isEmpty())
5252            mods = new ArrayList<>();
5253        else
5254            return null;
5255
5256        int ver = SymbolID.getVersion(symbolID);
5257        int ss = SymbolID.getSymbolSet(symbolID);
5258        int x = 0;
5259        int y = 0;
5260        boolean centered = true;
5261        int p = RendererSettings.getInstance().getSPModifierPlacement();
5262        boolean strict = (RendererSettings.getInstance().getSPModifierPlacement() == RendererSettings.ModifierPlacement_STRICT);
5263        if(attributes != null && attributes.containsKey(MilStdAttributes.ModifierPlacement))
5264        {
5265            String mp = attributes.get(MilStdAttributes.ModifierPlacement);
5266            if(mp.equals("0") || mp.equals("1") || mp.equals("2"))
5267            {
5268                p = Integer.parseInt(mp);
5269                if(p == 0)
5270                    strict = true;
5271                else
5272                    strict = false;
5273            }
5274        }
5275        String temp = null;
5276        String sep = " ";
5277
5278
5279        if(ver == SymbolID.Version_2525Dch1)
5280        {
5281            if(ss == SymbolID.SymbolSet_LandUnit ||
5282                    ss == SymbolID.SymbolSet_LandCivilianUnit_Organization)
5283            {
5284
5285                //Only Command & Control has AA; ec.equals("110000").  Always in the middle of the unit.
5286                if(modifiers.containsKey(Modifiers.AA_SPECIAL_C2_HQ))
5287                {
5288                    temp = modifiers.get(Modifiers.AA_SPECIAL_C2_HQ);
5289                    if(temp != null && !temp.isEmpty())
5290                        mods.add(new Modifier("AA", temp, 0, 0, true));
5291                }
5292
5293                //Do top center label
5294                x = 0;//centered
5295                y = 9;//on top of symbol
5296                if(modifiers.containsKey(Modifiers.B_ECHELON))
5297                {
5298                    temp = modifiers.get(Modifiers.B_ECHELON);
5299                    if(temp != null && !temp.isEmpty())
5300                        mods.add(new Modifier("B", temp, x, y, centered));
5301                }
5302
5303                //Do right side labels
5304                x = 1;//on right
5305                if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
5306                {
5307                    y = 0;//center
5308                    centered = true;//vertically centered, only matters for labels on left and right side
5309                    temp = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
5310                    if(temp != null && !temp.isEmpty())
5311                        mods.add(new Modifier("H", temp, x, y, centered));
5312                }
5313                else if(!strict)
5314                {
5315                    //if no "H', bring G and M closer to the center
5316                    centered = false;
5317                }
5318
5319                if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
5320                {
5321                    y = 1;//above center
5322                    temp = modifiers.get(Modifiers.G_STAFF_COMMENTS);
5323                    if(temp != null && !temp.isEmpty())
5324                        mods.add(new Modifier("G", temp, x, y, centered));
5325                }
5326
5327                if(modifiers.containsKey(Modifiers.F_REINFORCED_REDUCED) || modifiers.containsKey(Modifiers.AS_COUNTRY))
5328                {
5329                    y = 2;
5330                    if(!strict && !modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
5331                        y--;
5332                    temp = "";
5333                    if(modifiers.containsKey(Modifiers.F_REINFORCED_REDUCED))
5334                        temp = modifiers.get(Modifiers.F_REINFORCED_REDUCED) + sep;
5335                    if(modifiers.containsKey(Modifiers.AS_COUNTRY))
5336                        temp += modifiers.get(Modifiers.AS_COUNTRY);
5337                    temp = temp.trim();
5338                    if(temp != null && !temp.isEmpty())
5339                        mods.add(new Modifier("F AS", temp, x, y, centered));
5340                }
5341
5342                if(modifiers.containsKey(Modifiers.M_HIGHER_FORMATION))
5343                {
5344                    y = -1;//below center
5345                    temp = modifiers.get(Modifiers.M_HIGHER_FORMATION);
5346                    if(temp != null && !temp.isEmpty())
5347                        mods.add(new Modifier("M", temp, x, y, centered));
5348                }
5349
5350                if(modifiers.containsKey(Modifiers.J_EVALUATION_RATING) ||
5351                        modifiers.containsKey(Modifiers.K_COMBAT_EFFECTIVENESS) ||
5352                        modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
5353                {
5354                    y = -2;
5355                    if(!strict && !modifiers.containsKey(Modifiers.M_HIGHER_FORMATION))
5356                        y++;
5357                    temp = "";
5358                    if(modifiers.containsKey(Modifiers.J_EVALUATION_RATING))
5359                        temp = modifiers.get(Modifiers.J_EVALUATION_RATING) + sep;
5360                    if(modifiers.containsKey(Modifiers.K_COMBAT_EFFECTIVENESS))
5361                        temp += modifiers.get(Modifiers.K_COMBAT_EFFECTIVENESS) + sep;
5362                    if(modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
5363                        temp += modifiers.get(Modifiers.P_IFF_SIF_AIS);
5364                    temp = temp.trim();
5365                    if(temp != null && !temp.isEmpty())
5366                        mods.add(new Modifier("J K P", temp, x, y, centered));
5367                }
5368
5369                //Do left side labels
5370                x = -1;//on left
5371                centered = false;
5372
5373                if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH) || modifiers.containsKey(Modifiers.Y_LOCATION))
5374                {
5375                    y = 1;
5376                    temp = "";
5377                    if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH))
5378                        temp = modifiers.get(Modifiers.X_ALTITUDE_DEPTH) + sep;
5379                    if(modifiers.containsKey(Modifiers.Y_LOCATION))
5380                        temp += modifiers.get(Modifiers.Y_LOCATION);
5381
5382                    temp = temp.trim();
5383                    if(temp != null && !temp.isEmpty())
5384                        mods.add(new Modifier("X Y", temp, x, y, centered));
5385                }
5386
5387                if(modifiers.containsKey(Modifiers.W_DTG_1))
5388                {
5389                    y = 2;//above center
5390                    if(!strict && !(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH) || modifiers.containsKey(Modifiers.Y_LOCATION)))
5391                        y--;
5392                    temp = modifiers.get(Modifiers.W_DTG_1);
5393                    if(temp != null && !temp.isEmpty())
5394                        mods.add(new Modifier("W", temp, x, y, centered));
5395                }
5396
5397                if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
5398                {
5399                    y = -1;//below center
5400                    temp = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
5401                    if(temp != null && !temp.isEmpty())
5402                        mods.add(new Modifier("T", temp, x, y, centered));
5403                }
5404
5405                if(modifiers.containsKey(Modifiers.Z_SPEED))
5406                {
5407                    y = -2;
5408                    if(!strict && !modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
5409                        y++;
5410                    temp = modifiers.get(Modifiers.Z_SPEED);
5411                    if(temp != null && !temp.isEmpty())
5412                        mods.add(new Modifier(Modifiers.J_EVALUATION_RATING, temp, x, y, centered));
5413                }
5414            }
5415            else if(ss == SymbolID.SymbolSet_LandEquipment ||
5416                    ss == SymbolID.SymbolSet_SignalsIntelligence_Land)
5417            {
5418                //Do top center label
5419                x = 0;//centered
5420                y = 9;//on top of symbol
5421                if(modifiers.containsKey(Modifiers.C_QUANTITY))
5422                {
5423                    temp = modifiers.get(Modifiers.C_QUANTITY);
5424                    if(temp != null && !temp.isEmpty())
5425                        mods.add(new Modifier("C", temp, x, y, centered));
5426                }
5427
5428                //Do right side labels
5429                x = 1;//on right
5430                if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1) || modifiers.containsKey(Modifiers.AF_COMMON_IDENTIFIER))
5431                {
5432                    y = 0;//center
5433                    centered = true;//vertically centered, only matters for labels on left and right side
5434                    temp = "";
5435                    if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
5436                        temp = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1) + sep;
5437                    if(modifiers.containsKey(Modifiers.AF_COMMON_IDENTIFIER))
5438                        temp += modifiers.get(Modifiers.AF_COMMON_IDENTIFIER);
5439                    temp = temp.trim();
5440                    if(temp != null && !temp.isEmpty())
5441                        mods.add(new Modifier("H AF", temp, x, y, centered));
5442                }
5443                else if(!strict)
5444                {
5445                    //if no "H', bring G and M closer to the center
5446                    centered = false;
5447                }
5448
5449                if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS) || modifiers.containsKey(Modifiers.AQ_GUARDED_UNIT))
5450                {
5451                    y = 1;//above center
5452                    temp = "";
5453                    if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
5454                        temp = modifiers.get(Modifiers.G_STAFF_COMMENTS) + sep;
5455                    if(modifiers.containsKey(Modifiers.AQ_GUARDED_UNIT))
5456                        temp += modifiers.get(Modifiers.AQ_GUARDED_UNIT);
5457                    temp = temp.trim();
5458                    if(temp != null && !temp.isEmpty())
5459                        mods.add(new Modifier("G AQ", temp, x, y, centered));
5460                }
5461
5462                if(modifiers.containsKey(Modifiers.AS_COUNTRY))
5463                {
5464                    y = 2;
5465                    if(!strict && !(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS) || modifiers.containsKey(Modifiers.AQ_GUARDED_UNIT)))
5466                        y--;
5467
5468                    temp = modifiers.get(Modifiers.AS_COUNTRY);
5469                    if(temp != null && !temp.isEmpty())
5470                        mods.add(new Modifier("AS", temp, x, y, centered));
5471                }
5472
5473                if(modifiers.containsKey(Modifiers.J_EVALUATION_RATING) ||
5474                        modifiers.containsKey(Modifiers.L_SIGNATURE_EQUIP) ||
5475                        modifiers.containsKey(Modifiers.N_HOSTILE) ||
5476                        modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
5477                {
5478                    y = -1;
5479
5480                    temp = "";
5481                    if(modifiers.containsKey(Modifiers.J_EVALUATION_RATING))
5482                        temp = modifiers.get(Modifiers.J_EVALUATION_RATING) + sep;
5483                    if(modifiers.containsKey(Modifiers.L_SIGNATURE_EQUIP))
5484                        temp += modifiers.get(Modifiers.L_SIGNATURE_EQUIP) + sep;
5485                    if(modifiers.containsKey(Modifiers.N_HOSTILE))
5486                        temp += modifiers.get(Modifiers.N_HOSTILE) + sep;
5487                    if(modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
5488                        temp += modifiers.get(Modifiers.P_IFF_SIF_AIS);
5489                    temp = temp.trim();
5490                    if(temp != null && !temp.isEmpty())
5491                        mods.add(new Modifier("J L N P", temp, x, y, centered));
5492                }
5493
5494                //Do left side labels
5495                x = -1;//on left
5496
5497                if(modifiers.containsKey(Modifiers.V_EQUIP_TYPE) ||
5498                        modifiers.containsKey(Modifiers.AD_PLATFORM_TYPE) ||
5499                        modifiers.containsKey(Modifiers.AE_EQUIPMENT_TEARDOWN_TIME))
5500                {
5501                    y = 0;//center
5502                    centered = true;//vertically centered, only matters for labels on left and right side
5503
5504                    temp = "";
5505                    if(modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
5506                        temp = modifiers.get(Modifiers.V_EQUIP_TYPE) + sep;
5507                    if(modifiers.containsKey(Modifiers.AD_PLATFORM_TYPE))
5508                        temp += modifiers.get(Modifiers.AD_PLATFORM_TYPE) + sep;
5509                    if(modifiers.containsKey(Modifiers.AE_EQUIPMENT_TEARDOWN_TIME))
5510                        temp += modifiers.get(Modifiers.AE_EQUIPMENT_TEARDOWN_TIME);
5511                    temp = temp.trim();
5512                    if(temp != null && !temp.isEmpty())
5513                        mods.add(new Modifier("V AD AE", temp, x, y, centered));
5514                }
5515                else if(!strict)
5516                {
5517                    centered = false;
5518                }
5519
5520                if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH) || modifiers.containsKey(Modifiers.Y_LOCATION))
5521                {
5522                    y = 1;
5523                    temp = "";
5524                    if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH))
5525                        temp = modifiers.get(Modifiers.X_ALTITUDE_DEPTH) + sep;
5526                    if(modifiers.containsKey(Modifiers.Y_LOCATION))
5527                        temp += modifiers.get(Modifiers.Y_LOCATION);
5528
5529                    temp = temp.trim();
5530                    mods.add(new Modifier("X Y", temp, x, y, centered));
5531                }
5532
5533                if(modifiers.containsKey(Modifiers.W_DTG_1) || modifiers.containsKey(Modifiers.AR_SPECIAL_DESIGNATOR))
5534                {
5535                    y = 2;//above center
5536                    if(!strict && !(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH) || modifiers.containsKey(Modifiers.Y_LOCATION)))
5537                        y--;
5538
5539                    temp = modifiers.get(Modifiers.W_DTG_1);
5540
5541                    if(temp != null && !temp.isEmpty())
5542                        mods.add(new Modifier("W", temp, x, y, centered));
5543                }
5544
5545                if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
5546                {
5547                    y = -1;//below center
5548                    temp = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
5549                    if(temp != null && !temp.isEmpty())
5550                        mods.add(new Modifier("T", temp, x, y, centered));
5551                }
5552
5553                if(modifiers.containsKey(Modifiers.Z_SPEED))
5554                {
5555                    y = -2;
5556                    if(!strict && !modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
5557                        y++;
5558                    temp = modifiers.get(Modifiers.Z_SPEED);
5559                    if(temp != null && !temp.isEmpty())
5560                        mods.add(new Modifier("Z", temp, x, y, centered));
5561                }
5562            }
5563            else if(ss == SymbolID.SymbolSet_LandInstallation)
5564            {
5565                //No top center label
5566
5567                //Do right side labels
5568                x = 1;//on right
5569
5570                if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
5571                {
5572                    y = 0;//center
5573                    centered = true;//vertically centered, only matters for labels on left and right side
5574                    temp = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
5575
5576                    if(temp != null && !temp.isEmpty())
5577                        mods.add(new Modifier("H", temp, x, y, centered));
5578                }
5579                else if(!strict)
5580                {
5581                    centered = false;
5582                }
5583
5584                if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
5585                {
5586                    y = 1;//above center
5587                    temp = modifiers.get(Modifiers.G_STAFF_COMMENTS);
5588
5589                    if(temp != null && !temp.isEmpty())
5590                        mods.add(new Modifier("G", temp, x, y, centered));
5591                }
5592
5593                if(modifiers.containsKey(Modifiers.AS_COUNTRY))
5594                {
5595                    y = 2;
5596                    if(!strict && !modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
5597                        y--;
5598
5599                    temp = modifiers.get(Modifiers.AS_COUNTRY);
5600                    if(temp != null && !temp.isEmpty())
5601                        mods.add(new Modifier("AS", temp, x, y, centered));
5602                }
5603
5604                if(modifiers.containsKey(Modifiers.J_EVALUATION_RATING) ||
5605                        modifiers.containsKey(Modifiers.K_COMBAT_EFFECTIVENESS) ||
5606                        modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
5607                {
5608                    y = -1;
5609
5610                    temp = "";
5611                    if(modifiers.containsKey(Modifiers.J_EVALUATION_RATING))
5612                        temp = modifiers.get(Modifiers.J_EVALUATION_RATING) + sep;
5613                    if(modifiers.containsKey(Modifiers.K_COMBAT_EFFECTIVENESS))
5614                        temp += modifiers.get(Modifiers.K_COMBAT_EFFECTIVENESS) + sep;
5615                    if(modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
5616                        temp += modifiers.get(Modifiers.P_IFF_SIF_AIS);
5617                    temp = temp.trim();
5618                    mods.add(new Modifier("J K P", temp, x, y, centered));
5619                }
5620
5621                //Do left side labels
5622                x = -1;//on left
5623
5624                if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH) || modifiers.containsKey(Modifiers.Y_LOCATION))
5625                {
5626                    y = 0;//center
5627                    centered = true;//vertically centered, only matters for labels on left and right side
5628
5629                    temp = "";
5630                    if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH))
5631                        temp = modifiers.get(Modifiers.X_ALTITUDE_DEPTH) + sep;
5632                    if(modifiers.containsKey(Modifiers.Y_LOCATION))
5633                        temp += modifiers.get(Modifiers.Y_LOCATION);
5634                    temp = temp.trim();
5635                    if(temp != null && !temp.isEmpty())
5636                        mods.add(new Modifier("X Y", temp, x, y, centered));
5637                }
5638                else if(!strict)
5639                {
5640                    centered = false;
5641                }
5642
5643                if(modifiers.containsKey(Modifiers.W_DTG_1))
5644                {
5645                    y = 1;//above center
5646
5647                    temp = modifiers.get(Modifiers.W_DTG_1);
5648
5649                    if(temp != null && !temp.isEmpty())
5650                        mods.add(new Modifier("W AR", temp, x, y, centered));
5651                }
5652
5653                if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
5654                {
5655                    y = -1;//below center
5656                    temp = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
5657                    if(temp != null && !temp.isEmpty())
5658                        mods.add(new Modifier("T", temp, x, y, centered));
5659                }
5660            }
5661            else if(ss == SymbolID.SymbolSet_Air ||
5662                    ss == SymbolID.SymbolSet_AirMissile ||
5663                    ss == SymbolID.SymbolSet_SignalsIntelligence_Air)
5664            {
5665                //No top center label
5666
5667
5668                //Do right side labels
5669                x = 1;//on right
5670                centered = false;centered = true;
5671                if(modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
5672                {
5673                    y = 0;//center
5674                    centered = true;//vertically centered, only matters for labels on left and right side
5675                    temp = modifiers.get(Modifiers.V_EQUIP_TYPE);
5676                    if(temp != null && !temp.isEmpty())
5677                        mods.add(new Modifier("V", temp, x, y, centered));
5678                }
5679                else if(!strict)
5680                {
5681                    //if no "H', bring G and M closer to the center
5682                    centered = false;
5683                }
5684
5685                if(modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
5686                {
5687                    y = 1;//above center
5688                    temp = modifiers.get(Modifiers.P_IFF_SIF_AIS);
5689
5690                    if(temp != null && !temp.isEmpty())
5691                        mods.add(new Modifier("P", temp, x, y, centered));
5692                }
5693
5694                if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1) || modifiers.containsKey(Modifiers.AS_COUNTRY))
5695                {
5696                    y = 2;
5697                    if(!strict && !modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
5698                        y--;
5699                    temp = "";
5700                    if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
5701                        temp = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1) + sep;
5702                    if(modifiers.containsKey(Modifiers.AS_COUNTRY))
5703                        temp += modifiers.get(Modifiers.AS_COUNTRY);
5704                    temp = temp.trim();
5705
5706                    if(temp != null && !temp.isEmpty())
5707                        mods.add(new Modifier("T AS", temp, x, y, centered));
5708                }
5709
5710                if(modifiers.containsKey(Modifiers.Z_SPEED)  ||
5711                        modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH))
5712                {
5713                    y = -1;//below center
5714                    if(!modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
5715                        y++;
5716
5717                    temp = "";
5718                    if(modifiers.containsKey(Modifiers.Z_SPEED))
5719                        temp = modifiers.get(Modifiers.Z_SPEED) + sep;
5720                    if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH))
5721                        temp += modifiers.get(Modifiers.X_ALTITUDE_DEPTH);
5722                    temp = temp.trim();
5723
5724                    if(temp != null && !temp.isEmpty())
5725                        mods.add(new Modifier("Z X", temp, x, y, centered));
5726                }
5727
5728                if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS) ||
5729                        modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
5730                {
5731                    y = -2 ;
5732                    if(!strict)
5733                    {
5734                        if(!(modifiers.containsKey(Modifiers.Z_SPEED)  ||
5735                                modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH)))
5736                            y++;
5737                    }
5738                    temp = "";
5739                    if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
5740                        temp = modifiers.get(Modifiers.G_STAFF_COMMENTS) + sep;
5741                    if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
5742                        temp += modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
5743                    temp = temp.trim();
5744                    if(temp != null && !temp.isEmpty())
5745                        mods.add(new Modifier("G H", temp, x, y, centered));
5746                }
5747
5748                //No left side labels
5749
5750            }
5751            else if(ss == SymbolID.SymbolSet_Space ||
5752                    ss == SymbolID.SymbolSet_SpaceMissile ||
5753                    ss == SymbolID.SymbolSet_SignalsIntelligence_Space)
5754            {
5755                //No top center label
5756
5757
5758                //Do right side labels
5759                x = 1;//on right
5760                centered = false;
5761
5762                if(modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
5763                {
5764                    y = 1;//above center
5765                    temp = modifiers.get(Modifiers.V_EQUIP_TYPE);
5766                    if(temp != null && !temp.isEmpty())
5767                        mods.add(new Modifier("V", temp, x, y, centered));
5768                }
5769
5770                if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1) || modifiers.containsKey(Modifiers.AS_COUNTRY))
5771                {
5772                    y = 2;
5773                    if(!strict && !modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
5774                        y--;
5775                    temp = "";
5776                    if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
5777                        temp = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1) + sep;
5778                    if(modifiers.containsKey(Modifiers.AS_COUNTRY))
5779                        temp += modifiers.get(Modifiers.AS_COUNTRY);
5780                    temp = temp.trim();
5781
5782                    if(temp != null && !temp.isEmpty())
5783                        mods.add(new Modifier("T AS", temp, x, y, centered));
5784                }
5785
5786                if(modifiers.containsKey(Modifiers.Z_SPEED)  ||
5787                        modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH))
5788                {
5789                    y = -1;//below center
5790                    temp = "";
5791                    if(modifiers.containsKey(Modifiers.Z_SPEED))
5792                        temp = modifiers.get(Modifiers.Z_SPEED) + sep;
5793                    if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH))
5794                        temp += modifiers.get(Modifiers.X_ALTITUDE_DEPTH);
5795                    temp = temp.trim();
5796
5797                    if(temp != null && !temp.isEmpty())
5798                        mods.add(new Modifier("Z X", temp, x, y, centered));
5799                }
5800
5801                if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS) ||
5802                        modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
5803                {
5804                    y = -2;
5805                    if(!strict &&
5806                            !(modifiers.containsKey(Modifiers.Z_SPEED) || modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH)))
5807                        y++;
5808                    temp = "";
5809                    if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
5810                        temp = modifiers.get(Modifiers.G_STAFF_COMMENTS) + sep;
5811                    if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
5812                        temp += modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
5813                    temp = temp.trim();
5814                    if(temp != null && !temp.isEmpty())
5815                        mods.add(new Modifier("G H", temp, x, y, centered));
5816                }
5817
5818                //No left side labels
5819            }
5820            else if(ss == SymbolID.SymbolSet_SeaSurface ||
5821                    ss == SymbolID.SymbolSet_SignalsIntelligence_SeaSurface)
5822            {
5823                //No top center label
5824
5825
5826                //Do right side labels
5827                x = 1;//on right
5828                centered = true;
5829                if(modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
5830                {
5831                    y = 0;//center
5832                    centered = true;//vertically centered, only matters for labels on left and right side
5833                    temp = modifiers.get(Modifiers.P_IFF_SIF_AIS);
5834                    if(temp != null && !temp.isEmpty())
5835                        mods.add(new Modifier("P", temp, x, y, centered));
5836                }
5837                else if(!strict)
5838                {
5839                    //if no "H', bring G and M closer to the center
5840                    centered = false;
5841                }
5842
5843                if(modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
5844                {
5845                    y = 1;//above center
5846                    temp = modifiers.get(Modifiers.V_EQUIP_TYPE);
5847                    if(temp != null && !temp.isEmpty())
5848                        mods.add(new Modifier("V", temp, x, y, centered));
5849                }
5850
5851                if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1) || modifiers.containsKey(Modifiers.AS_COUNTRY))
5852                {
5853                    y = 2;
5854                    if(!strict && !modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
5855                        y--;
5856                    temp = "";
5857                    if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
5858                        temp = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1) + sep;
5859                    if(modifiers.containsKey(Modifiers.AS_COUNTRY))
5860                        temp += modifiers.get(Modifiers.AS_COUNTRY);
5861                    temp = temp.trim();
5862
5863                    if(temp != null && !temp.isEmpty())
5864                        mods.add(new Modifier("T AS", temp, x, y, centered));
5865                }
5866
5867                if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS)  ||
5868                        modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
5869                {
5870                    y = -1;//below center
5871                    temp = "";
5872                    if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
5873                        temp = modifiers.get(Modifiers.G_STAFF_COMMENTS) + sep;
5874                    if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
5875                        temp += modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
5876                    temp = temp.trim();
5877
5878                    if(temp != null && !temp.isEmpty())
5879                        mods.add(new Modifier("G H", temp, x, y, centered));
5880                }
5881
5882                if(modifiers.containsKey(Modifiers.Y_LOCATION) ||
5883                        modifiers.containsKey(Modifiers.Z_SPEED))
5884                {
5885                    y = -2;
5886                    if(!strict &&
5887                            !(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS) || modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1)))
5888                        y++;
5889                    temp = "";
5890                    if(modifiers.containsKey(Modifiers.Y_LOCATION))
5891                        temp = modifiers.get(Modifiers.Y_LOCATION) + sep;
5892                    if(modifiers.containsKey(Modifiers.Z_SPEED))
5893                        temp += modifiers.get(Modifiers.Z_SPEED);
5894                    temp = temp.trim();
5895                    if(temp != null && !temp.isEmpty())
5896                        mods.add(new Modifier("Y Z", temp, x, y, centered));
5897                }
5898
5899                //Do left side labels
5900                x = -1;
5901                centered = false;
5902                if(modifiers.containsKey(Modifiers.AQ_GUARDED_UNIT) || modifiers.containsKey(Modifiers.AR_SPECIAL_DESIGNATOR))
5903                {
5904                    y = 2;//above center
5905                    if(!strict)
5906                        y--;
5907
5908                    temp = "";
5909                    if(modifiers.containsKey(Modifiers.AQ_GUARDED_UNIT))
5910                        temp = modifiers.get(Modifiers.AQ_GUARDED_UNIT) + sep;
5911                    if(modifiers.containsKey(Modifiers.AR_SPECIAL_DESIGNATOR))
5912                        temp += modifiers.get(Modifiers.AR_SPECIAL_DESIGNATOR);
5913                    temp = temp.trim();
5914
5915                    if(temp != null && !temp.isEmpty())
5916                        mods.add(new Modifier("AQ AR", temp, x, y, centered));
5917                }
5918            }
5919            else if(ss == SymbolID.SymbolSet_SeaSubsurface ||
5920                    ss == SymbolID.SymbolSet_SignalsIntelligence_SeaSubsurface)
5921            {
5922                //No top center label
5923
5924
5925                //Do right side labels
5926                x = 1;//on right
5927                centered = true;
5928                if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH))
5929                {
5930                    y = 0;//center
5931                    centered = true;//vertically centered, only matters for labels on left and right side
5932                    temp = modifiers.get(Modifiers.X_ALTITUDE_DEPTH);
5933                    if(temp != null && !temp.isEmpty())
5934                        mods.add(new Modifier("X", temp, x, y, centered));
5935                }
5936                else if(!strict)
5937                {
5938                    //if no "H', bring G and M closer to the center
5939                    centered = false;
5940                }
5941
5942                if(modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
5943                {
5944                    y = 1;//center
5945                    temp = modifiers.get(Modifiers.V_EQUIP_TYPE);
5946                    if(temp != null && !temp.isEmpty())
5947                        mods.add(new Modifier("V", temp, x, y, centered));
5948                }
5949
5950                if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1) || modifiers.containsKey(Modifiers.AS_COUNTRY))
5951                {
5952                    y = 2;
5953                    if(!strict && !modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
5954                        y--;
5955                    temp = "";
5956                    if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
5957                        temp = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1) + sep;
5958                    if(modifiers.containsKey(Modifiers.AS_COUNTRY))
5959                        temp += modifiers.get(Modifiers.AS_COUNTRY);
5960                    temp = temp.trim();
5961
5962                    if(temp != null && !temp.isEmpty())
5963                        mods.add(new Modifier("T AS", temp, x, y, centered));
5964                }
5965
5966                if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
5967                {
5968                    y = -1;
5969
5970                    temp = modifiers.get(Modifiers.G_STAFF_COMMENTS);
5971
5972                    if(temp != null && !temp.isEmpty())
5973                        mods.add(new Modifier("G", temp, x, y, centered));
5974                }
5975
5976                if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
5977                {
5978                    y = -2;//below center
5979                    if(!strict)
5980                    {
5981                        if(!modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
5982                            y++;
5983                    }
5984
5985                    temp = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
5986
5987                    if(temp != null && !temp.isEmpty())
5988                        mods.add(new Modifier("H", temp, x, y, centered));
5989                }
5990
5991                //Do left side labels
5992                x = -1;
5993                centered = false;
5994                if(modifiers.containsKey(Modifiers.AR_SPECIAL_DESIGNATOR))
5995                {
5996                    y = 3;//above center
5997                    if(!strict)
5998                    {
5999                        y--;
6000                    }
6001
6002                    temp = modifiers.get(Modifiers.AR_SPECIAL_DESIGNATOR);
6003
6004                    if(temp != null && !temp.isEmpty())
6005                        mods.add(new Modifier("AR", temp, x, y, centered));
6006                }
6007
6008            }
6009            else if(ss == SymbolID.SymbolSet_Activities)
6010            {
6011                //No top center label
6012
6013                //Do right side labels
6014                x = 1;//on right
6015                centered = false;
6016
6017                if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
6018                {
6019                    y = 1;
6020
6021                    temp = modifiers.get(Modifiers.G_STAFF_COMMENTS);
6022                    if(temp != null && !temp.isEmpty())
6023                        mods.add(new Modifier("G", temp, x, y, centered));
6024                }
6025
6026                if(modifiers.containsKey(Modifiers.AS_COUNTRY))
6027                {
6028                    y = 2;
6029                    if(!strict && !modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
6030                        y--;
6031                    temp = modifiers.get(Modifiers.AS_COUNTRY);
6032
6033                    if(temp != null && !temp.isEmpty())
6034                        mods.add(new Modifier("AS", temp, x, y, centered));
6035                }
6036
6037                if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
6038                {
6039                    y = -1;//below center
6040                    temp = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
6041                    if(temp != null && !temp.isEmpty())
6042                        mods.add(new Modifier("H", temp, x, y, centered));
6043                }
6044
6045                if(modifiers.containsKey(Modifiers.J_EVALUATION_RATING))
6046                {
6047                    y = -2;
6048                    if(!strict && !modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
6049                        y++;
6050                    temp = temp = modifiers.get(Modifiers.J_EVALUATION_RATING);
6051
6052                    if(temp != null && !temp.isEmpty())
6053                        mods.add(new Modifier("J", temp, x, y, centered));
6054                }
6055
6056                //Do left side labels
6057                x = -1;//on left
6058                centered = false;
6059
6060                if(modifiers.containsKey(Modifiers.Y_LOCATION))
6061                {
6062                    y = 1;
6063                    temp = modifiers.get(Modifiers.Y_LOCATION);
6064
6065                    if(temp != null && !temp.isEmpty())
6066                        mods.add(new Modifier("Y", temp, x, y, centered));
6067                }
6068
6069                if(modifiers.containsKey(Modifiers.W_DTG_1))
6070                {
6071                    y = 2;//above center
6072                    if(!strict && !modifiers.containsKey(Modifiers.Y_LOCATION))
6073                        y--;
6074                    temp = modifiers.get(Modifiers.W_DTG_1);
6075                    if(temp != null && !temp.isEmpty())
6076                        mods.add(new Modifier("W", temp, x, y, centered));
6077                }
6078
6079            }
6080            else if(ss == SymbolID.SymbolSet_CyberSpace)
6081            {
6082                //Do top center label
6083                x = 0;//centered
6084                y = 9;//on top of symbol
6085                if(modifiers.containsKey(Modifiers.B_ECHELON))
6086                {
6087                    temp = modifiers.get(Modifiers.B_ECHELON);
6088                    if(temp != null && !temp.isEmpty())
6089                        mods.add(new Modifier("B", temp, x, y, centered));
6090                }
6091
6092                //Do right side labels
6093                x = 1;//on right
6094                if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
6095                {
6096                    y = 0;//center
6097                    centered = true;//vertically centered, only matters for labels on left and right side
6098                    temp = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
6099                    if(temp != null && !temp.isEmpty())
6100                        mods.add(new Modifier("H", temp, x, y, centered));
6101                }
6102                else if(!strict)
6103                {
6104                    //if no "H', bring G and M closer to the center
6105                    centered = false;
6106                }
6107
6108                if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
6109                {
6110                    y = 1;//above center
6111                    temp = modifiers.get(Modifiers.G_STAFF_COMMENTS);
6112                    if(temp != null && !temp.isEmpty())
6113                        mods.add(new Modifier("G", temp, x, y, centered));
6114                }
6115
6116                if(modifiers.containsKey(Modifiers.F_REINFORCED_REDUCED) || modifiers.containsKey(Modifiers.AS_COUNTRY))
6117                {
6118                    y = 2;
6119                    if(!strict && !modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
6120                        y--;
6121                    temp = "";
6122                    if(modifiers.containsKey(Modifiers.F_REINFORCED_REDUCED))
6123                        temp = modifiers.get(Modifiers.F_REINFORCED_REDUCED) + sep;
6124                    if(modifiers.containsKey(Modifiers.AS_COUNTRY))
6125                        temp += modifiers.get(Modifiers.AS_COUNTRY);
6126                    temp = temp.trim();
6127                    if(temp != null && !temp.isEmpty())
6128                        mods.add(new Modifier("F AS", temp, x, y, centered));
6129                }
6130
6131                if(modifiers.containsKey(Modifiers.M_HIGHER_FORMATION))
6132                {
6133                    y = -1;//below center
6134                    temp = modifiers.get(Modifiers.M_HIGHER_FORMATION);
6135                    if(temp != null && !temp.isEmpty())
6136                        mods.add(new Modifier("M", temp, x, y, centered));
6137                }
6138
6139                if(modifiers.containsKey(Modifiers.K_COMBAT_EFFECTIVENESS) ||
6140                        modifiers.containsKey(Modifiers.L_SIGNATURE_EQUIP))
6141                {
6142                    y = -2;
6143                    if(!strict && !modifiers.containsKey(Modifiers.M_HIGHER_FORMATION))
6144                        y++;
6145                    temp = "";
6146                    if(modifiers.containsKey(Modifiers.K_COMBAT_EFFECTIVENESS))
6147                        temp = modifiers.get(Modifiers.K_COMBAT_EFFECTIVENESS) + sep;
6148                    if(modifiers.containsKey(Modifiers.L_SIGNATURE_EQUIP))
6149                        temp += modifiers.get(Modifiers.L_SIGNATURE_EQUIP);
6150
6151                    temp = temp.trim();
6152                    if(temp != null && !temp.isEmpty())
6153                        mods.add(new Modifier("K L", temp, x, y, centered));
6154                }
6155
6156                //Do left side labels
6157                x = -1;//on left
6158                centered = true;
6159
6160                if(modifiers.containsKey(Modifiers.Y_LOCATION))
6161                {
6162                    y = 0;
6163                    temp = modifiers.get(Modifiers.Y_LOCATION);
6164
6165                    if(temp != null && !temp.isEmpty())
6166                        mods.add(new Modifier("Y", temp, x, y, centered));
6167                }
6168                else if (!strict)
6169                {
6170                    centered = false;
6171                }
6172
6173                if(modifiers.containsKey(Modifiers.W_DTG_1))
6174                {
6175                    y = 1;//above center
6176                    temp = modifiers.get(Modifiers.W_DTG_1);
6177                    if(temp != null && !temp.isEmpty())
6178                        mods.add(new Modifier("W", temp, x, y, centered));
6179                }
6180
6181                if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1) || modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
6182                {
6183                    y = -1;//below center
6184                    temp = "";
6185                    if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
6186                        temp = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1) + sep;
6187                    if(modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
6188                        temp += modifiers.get(Modifiers.V_EQUIP_TYPE);
6189
6190                    temp = temp.trim();
6191                    if(temp != null && !temp.isEmpty())
6192                        mods.add(new Modifier("T V", temp, x, y, centered));
6193                }
6194
6195            }
6196            /*else if(ver == SymbolID.SymbolSet_MineWarfare)
6197            {
6198                //no modifiers
6199            }//*/
6200            //else//SymbolSet Unknown
6201            //processUnknownTextModifiers
6202        }
6203        else if(ver >= SymbolID.Version_2525E)
6204        {
6205            int fs = SymbolID.getFrameShape(symbolID);
6206            if(ss == SymbolID.SymbolSet_LandUnit ||
6207                    ss == SymbolID.SymbolSet_LandCivilianUnit_Organization ||
6208                    (ss == SymbolID.SymbolSet_SignalsIntelligence && fs == SymbolID.FrameShape_LandUnit))
6209            {
6210
6211                //Only Command & Control has AA; ec.equals("110000").  Always in the middle of the unit.
6212                if(modifiers.containsKey(Modifiers.AA_SPECIAL_C2_HQ))
6213                {
6214                    temp = modifiers.get(Modifiers.AA_SPECIAL_C2_HQ);
6215                    if(temp != null && !temp.isEmpty())
6216                        mods.add(new Modifier("AA", temp, 0, 0, true));
6217                }
6218                
6219                //Do top center label
6220                x = 0;//centered
6221                y = 9;//on top of symbol
6222                if(modifiers.containsKey(Modifiers.B_ECHELON))
6223                {
6224                    temp = modifiers.get(Modifiers.B_ECHELON);
6225                    if(temp != null && !temp.isEmpty())
6226                        mods.add(new Modifier("B", temp, x, y, centered));
6227                }
6228
6229                //Do right side labels
6230                x = 1;//on right
6231                if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1) ||
6232                        modifiers.containsKey(Modifiers.AF_COMMON_IDENTIFIER))
6233                {
6234                    y = 0;//center
6235                    centered = true;//vertically centered, only matters for labels on left and right side
6236                    temp = "";
6237                    if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
6238                        temp = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1) + sep;
6239                    if(modifiers.containsKey(Modifiers.AF_COMMON_IDENTIFIER))
6240                        temp += modifiers.get(Modifiers.AF_COMMON_IDENTIFIER);
6241                    temp = temp.trim();
6242                    if(temp != null && !temp.isEmpty())
6243                        mods.add(new Modifier("H AF", temp, x, y, centered));
6244                }
6245                else if(!strict)
6246                {
6247                    //if no "H', bring G and M closer to the center
6248                    centered = false;
6249                }
6250
6251                if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS) || modifiers.containsKey(Modifiers.AQ_GUARDED_UNIT))
6252                {
6253                    y = 1;//above center
6254                    temp = "";
6255                    if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
6256                        temp = modifiers.get(Modifiers.G_STAFF_COMMENTS) + sep;
6257                    if(modifiers.containsKey(Modifiers.AQ_GUARDED_UNIT))
6258                        temp += modifiers.get(Modifiers.AQ_GUARDED_UNIT);
6259                    temp = temp.trim();
6260                    if(temp != null && !temp.isEmpty())
6261                        mods.add(new Modifier("G AQ", temp, x, y, centered));
6262                }
6263
6264                if(modifiers.containsKey(Modifiers.F_REINFORCED_REDUCED) || modifiers.containsKey(Modifiers.AS_COUNTRY))
6265                {
6266                    y = 2;
6267                    if(!strict && !(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS) || modifiers.containsKey(Modifiers.AQ_GUARDED_UNIT)))
6268                        y--;
6269                    temp = "";
6270                    if(modifiers.containsKey(Modifiers.F_REINFORCED_REDUCED))
6271                        temp = modifiers.get(Modifiers.F_REINFORCED_REDUCED) + sep;
6272                    if(modifiers.containsKey(Modifiers.AS_COUNTRY))
6273                        temp += modifiers.get(Modifiers.AS_COUNTRY);
6274                    temp = temp.trim();
6275                    if(temp != null && !temp.isEmpty())
6276                        mods.add(new Modifier("F AS", temp, x, y, centered));
6277                }
6278
6279                if(modifiers.containsKey(Modifiers.M_HIGHER_FORMATION))
6280                {
6281                    y = -1;//below center
6282                    temp = modifiers.get(Modifiers.M_HIGHER_FORMATION);
6283                    if(temp != null && !temp.isEmpty())
6284                        mods.add(new Modifier("M", temp, x, y, centered));
6285                }
6286
6287                if(modifiers.containsKey(Modifiers.J_EVALUATION_RATING) ||
6288                        modifiers.containsKey(Modifiers.K_COMBAT_EFFECTIVENESS) ||
6289                        modifiers.containsKey(Modifiers.L_SIGNATURE_EQUIP) ||
6290                        modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
6291                {
6292                    y = -2;
6293                    if(!strict && !modifiers.containsKey(Modifiers.M_HIGHER_FORMATION))
6294                        y++;
6295                    temp = "";
6296                    if(modifiers.containsKey(Modifiers.J_EVALUATION_RATING))
6297                        temp = modifiers.get(Modifiers.J_EVALUATION_RATING) + sep;
6298                    if(modifiers.containsKey(Modifiers.K_COMBAT_EFFECTIVENESS))
6299                        temp += modifiers.get(Modifiers.K_COMBAT_EFFECTIVENESS) + sep;
6300                    if(modifiers.containsKey(Modifiers.L_SIGNATURE_EQUIP))
6301                        temp += modifiers.get(Modifiers.L_SIGNATURE_EQUIP) + sep;
6302                    if(modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
6303                        temp += modifiers.get(Modifiers.P_IFF_SIF_AIS);
6304                    temp = temp.trim();
6305                    if(temp != null && !temp.isEmpty())
6306                        mods.add(new Modifier("J K L P", temp, x, y, centered));
6307                }
6308
6309                //Do left side labels
6310                x = -1;//on left
6311
6312                if(modifiers.containsKey(Modifiers.V_EQUIP_TYPE) ||
6313                        modifiers.containsKey(Modifiers.AD_PLATFORM_TYPE) ||
6314                        modifiers.containsKey(Modifiers.AE_EQUIPMENT_TEARDOWN_TIME))
6315                {
6316                    y = 0;//center
6317                    centered = true;//vertically centered, only matters for labels on left and right side
6318
6319                    temp = "";
6320                    if(modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
6321                        temp = modifiers.get(Modifiers.V_EQUIP_TYPE) + sep;
6322                    if(modifiers.containsKey(Modifiers.AD_PLATFORM_TYPE))
6323                        temp += modifiers.get(Modifiers.AD_PLATFORM_TYPE) + sep;
6324                    if(modifiers.containsKey(Modifiers.AE_EQUIPMENT_TEARDOWN_TIME))
6325                        temp += modifiers.get(Modifiers.AE_EQUIPMENT_TEARDOWN_TIME);
6326                    temp = temp.trim();
6327                    if(temp != null && !temp.isEmpty())
6328                        mods.add(new Modifier("V AD AE", temp, x, y, centered));
6329                }
6330                else if(!strict)
6331                {
6332                    centered = false;
6333                }
6334
6335                if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH) || modifiers.containsKey(Modifiers.Y_LOCATION))
6336                {
6337                    y = 1;
6338                    temp = "";
6339                    if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH))
6340                        temp = modifiers.get(Modifiers.X_ALTITUDE_DEPTH) + sep;
6341                    if(modifiers.containsKey(Modifiers.Y_LOCATION))
6342                        temp += modifiers.get(Modifiers.Y_LOCATION);
6343
6344                    temp = temp.trim();
6345                    mods.add(new Modifier("X Y", temp, x, y, centered));
6346                }
6347
6348                if(modifiers.containsKey(Modifiers.W_DTG_1))
6349                {
6350                    y = 2;//above center
6351                    if(!strict && !(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH) || modifiers.containsKey(Modifiers.Y_LOCATION)))
6352                        y--;
6353
6354                    temp = modifiers.get(Modifiers.W_DTG_1);
6355
6356                    if(temp != null && !temp.isEmpty())
6357                        mods.add(new Modifier("W", temp, x, y, centered));
6358                }
6359
6360                if(modifiers.containsKey(Modifiers.C_QUANTITY) || modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
6361                {
6362                    y = -1;//below center
6363                    temp = "";
6364                    if(modifiers.containsKey(Modifiers.C_QUANTITY))
6365                        temp = modifiers.get(Modifiers.C_QUANTITY) + sep;
6366                    if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
6367                        temp += modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
6368
6369                    temp = temp.trim();
6370                    if(temp != null && !temp.isEmpty())
6371                        mods.add(new Modifier("C T", temp, x, y, centered));
6372                }
6373
6374                if(modifiers.containsKey(Modifiers.Z_SPEED))
6375                {
6376                    y = -2;
6377                    if(!strict && !(modifiers.containsKey(Modifiers.C_QUANTITY) || modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1)))
6378                        y++;
6379                    temp = modifiers.get(Modifiers.Z_SPEED);
6380                    if(temp != null && !temp.isEmpty())
6381                        mods.add(new Modifier("Z", temp, x, y, centered));
6382                }
6383            }
6384            else if(ss == SymbolID.SymbolSet_LandEquipment ||
6385                    (ss == SymbolID.SymbolSet_SignalsIntelligence && fs == SymbolID.FrameShape_LandEquipment))
6386            {
6387                //Do top center label
6388                x = 0;//centered
6389                y = 9;//on top of symbol
6390                if(modifiers.containsKey(Modifiers.C_QUANTITY))
6391                {
6392                    temp = modifiers.get(Modifiers.C_QUANTITY);
6393                    if(temp != null && !temp.isEmpty())
6394                        mods.add(new Modifier("C", temp, x, y, centered));
6395                }
6396
6397                //Do right side labels
6398                x = 1;//on right
6399                centered = false;
6400
6401                if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS) || modifiers.containsKey(Modifiers.AQ_GUARDED_UNIT))
6402                {
6403                    y = 1;//above center
6404                    temp = "";
6405                    if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
6406                        temp = modifiers.get(Modifiers.G_STAFF_COMMENTS) + sep;
6407                    if(modifiers.containsKey(Modifiers.AQ_GUARDED_UNIT))
6408                        temp += modifiers.get(Modifiers.AQ_GUARDED_UNIT);
6409                    temp = temp.trim();
6410                    if(temp != null && !temp.isEmpty())
6411                        mods.add(new Modifier("G AQ", temp, x, y, centered));
6412                }
6413
6414                if( modifiers.containsKey(Modifiers.AS_COUNTRY))
6415                {
6416                    y = 2;
6417                    if(!strict && !(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS) || modifiers.containsKey(Modifiers.AQ_GUARDED_UNIT)))
6418                        y--;
6419                    temp = modifiers.get(Modifiers.AS_COUNTRY);
6420
6421                    if(temp != null && !temp.isEmpty())
6422                        mods.add(new Modifier("AS", temp, x, y, centered));
6423                }
6424
6425                if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1) ||
6426                        modifiers.containsKey(Modifiers.AF_COMMON_IDENTIFIER))
6427                {
6428                    y = -1;
6429                    temp = "";
6430                    if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
6431                        temp = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1) + sep;
6432                    if(modifiers.containsKey(Modifiers.AF_COMMON_IDENTIFIER))
6433                        temp += modifiers.get(Modifiers.AF_COMMON_IDENTIFIER);
6434                    temp = temp.trim();
6435                    if(temp != null && !temp.isEmpty())
6436                        mods.add(new Modifier("H AF", temp, x, y, centered));
6437                }
6438
6439                if(modifiers.containsKey(Modifiers.J_EVALUATION_RATING) ||
6440                        modifiers.containsKey(Modifiers.K_COMBAT_EFFECTIVENESS) ||
6441                        modifiers.containsKey(Modifiers.L_SIGNATURE_EQUIP) ||
6442                        modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
6443                {
6444                    y = -2;
6445                    if(!strict && !(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1) ||
6446                            modifiers.containsKey(Modifiers.AF_COMMON_IDENTIFIER)))
6447                        y++;
6448                    temp = "";
6449                    if(modifiers.containsKey(Modifiers.J_EVALUATION_RATING))
6450                        temp = modifiers.get(Modifiers.J_EVALUATION_RATING) + sep;
6451                    if(modifiers.containsKey(Modifiers.K_COMBAT_EFFECTIVENESS))
6452                        temp += modifiers.get(Modifiers.K_COMBAT_EFFECTIVENESS) + sep;
6453                    if(modifiers.containsKey(Modifiers.L_SIGNATURE_EQUIP))
6454                        temp += modifiers.get(Modifiers.L_SIGNATURE_EQUIP) + sep;
6455                    if(modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
6456                        temp += modifiers.get(Modifiers.P_IFF_SIF_AIS);
6457                    temp = temp.trim();
6458                    if(temp != null && !temp.isEmpty())
6459                        mods.add(new Modifier("J K L P", temp, x, y, centered));
6460                }
6461
6462                //Do left side labels
6463                x = -1;//on left
6464
6465                if(modifiers.containsKey(Modifiers.V_EQUIP_TYPE) ||
6466                        modifiers.containsKey(Modifiers.AD_PLATFORM_TYPE) ||
6467                        modifiers.containsKey(Modifiers.AE_EQUIPMENT_TEARDOWN_TIME))
6468                {
6469                    y = 0;//center
6470                    centered = true;//vertically centered, only matters for labels on left and right side
6471
6472                    temp = "";
6473                    if(modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
6474                        temp = modifiers.get(Modifiers.V_EQUIP_TYPE) + sep;
6475                    if(modifiers.containsKey(Modifiers.AD_PLATFORM_TYPE))
6476                        temp += modifiers.get(Modifiers.AD_PLATFORM_TYPE) + sep;
6477                    if(modifiers.containsKey(Modifiers.AE_EQUIPMENT_TEARDOWN_TIME))
6478                        temp += modifiers.get(Modifiers.AE_EQUIPMENT_TEARDOWN_TIME);
6479                    temp = temp.trim();
6480                    if(temp != null && !temp.isEmpty())
6481                        mods.add(new Modifier("V AD AE", temp, x, y, centered));
6482                }
6483                else if(!strict)
6484                {
6485                    centered = false;
6486                }
6487
6488                if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH) || modifiers.containsKey(Modifiers.Y_LOCATION))
6489                {
6490                    y = 1;
6491                    temp = "";
6492                    if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH))
6493                        temp = modifiers.get(Modifiers.X_ALTITUDE_DEPTH) + sep;
6494                    if(modifiers.containsKey(Modifiers.Y_LOCATION))
6495                        temp += modifiers.get(Modifiers.Y_LOCATION);
6496
6497                    temp = temp.trim();
6498                    mods.add(new Modifier("X Y", temp, x, y, centered));
6499                }
6500
6501                if(modifiers.containsKey(Modifiers.W_DTG_1))
6502                {
6503                    y = 2;//above center
6504                    if(!strict && !(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH) || modifiers.containsKey(Modifiers.Y_LOCATION)))
6505                        y--;
6506
6507                    temp = modifiers.get(Modifiers.W_DTG_1);
6508
6509                    if(temp != null && !temp.isEmpty())
6510                        mods.add(new Modifier("W", temp, x, y, centered));
6511                }
6512
6513                if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
6514                {
6515                    y = -1;//below center
6516                    temp = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
6517
6518                    temp = temp.trim();
6519                    if(temp != null && !temp.isEmpty())
6520                        mods.add(new Modifier("T", temp, x, y, centered));
6521                }
6522
6523                if(modifiers.containsKey(Modifiers.Z_SPEED))
6524                {
6525                    y = -2;
6526                    if(!strict && !modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
6527                        y++;
6528                    temp = modifiers.get(Modifiers.Z_SPEED);
6529                    if(temp != null && !temp.isEmpty())
6530                        mods.add(new Modifier("Z", temp, x, y, centered));
6531                }
6532            }
6533            else if(ss == SymbolID.SymbolSet_LandInstallation)
6534            {
6535                //No top center label
6536
6537                //Do right side labels
6538                x = 1;//on right
6539                if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
6540                {
6541                    y = 0;//center
6542                    centered = true;//vertically centered, only matters for labels on left and right side
6543                    temp = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1) + sep;
6544
6545                    if(temp != null && !temp.isEmpty())
6546                        mods.add(new Modifier("H", temp, x, y, centered));
6547                }
6548                else if(!strict)
6549                {
6550                    //if no "H', bring G and M closer to the center
6551                    centered = false;
6552                }
6553
6554                if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS) || modifiers.containsKey(Modifiers.AQ_GUARDED_UNIT))
6555                {
6556                    y = 1;//above center
6557                    temp = "";
6558                    if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
6559                        temp = modifiers.get(Modifiers.G_STAFF_COMMENTS) + sep;
6560                    if(modifiers.containsKey(Modifiers.AQ_GUARDED_UNIT))
6561                        temp += modifiers.get(Modifiers.AQ_GUARDED_UNIT);
6562                    temp = temp.trim();
6563                    if(temp != null && !temp.isEmpty())
6564                        mods.add(new Modifier("G AQ", temp, x, y, centered));
6565                }
6566
6567                if(modifiers.containsKey(Modifiers.AS_COUNTRY))
6568                {
6569                    y = 2;
6570                    if(!strict && !(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS) || modifiers.containsKey(Modifiers.AQ_GUARDED_UNIT)))
6571                        y--;
6572                    temp = modifiers.get(Modifiers.AS_COUNTRY);
6573
6574                    if(temp != null && !temp.isEmpty())
6575                        mods.add(new Modifier("AS", temp, x, y, centered));
6576                }
6577
6578                if(modifiers.containsKey(Modifiers.M_HIGHER_FORMATION))
6579                {
6580                    y = -1;//below center
6581                    temp = modifiers.get(Modifiers.M_HIGHER_FORMATION);
6582                    if(temp != null && !temp.isEmpty())
6583                        mods.add(new Modifier("M", temp, x, y, centered));
6584                }
6585
6586                if(modifiers.containsKey(Modifiers.J_EVALUATION_RATING) ||
6587                        modifiers.containsKey(Modifiers.K_COMBAT_EFFECTIVENESS) ||
6588                        modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
6589                {
6590                    y = -2;
6591                    if(!strict && !modifiers.containsKey(Modifiers.M_HIGHER_FORMATION))
6592                        y++;
6593                    temp = "";
6594                    if(modifiers.containsKey(Modifiers.J_EVALUATION_RATING))
6595                        temp = modifiers.get(Modifiers.J_EVALUATION_RATING) + sep;
6596                    if(modifiers.containsKey(Modifiers.K_COMBAT_EFFECTIVENESS))
6597                        temp += modifiers.get(Modifiers.K_COMBAT_EFFECTIVENESS) + sep;
6598                    if(modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
6599                        temp += modifiers.get(Modifiers.P_IFF_SIF_AIS);
6600                    temp = temp.trim();
6601                    if(temp != null && !temp.isEmpty())
6602                        mods.add(new Modifier("J K P", temp, x, y, centered));
6603                }
6604
6605                //Do left side labels
6606                x = -1;//on left
6607                centered = false;
6608
6609                if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH) || modifiers.containsKey(Modifiers.Y_LOCATION))
6610                {
6611                    y = 1;
6612                    temp = "";
6613                    if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH))
6614                        temp = modifiers.get(Modifiers.X_ALTITUDE_DEPTH) + sep;
6615                    if(modifiers.containsKey(Modifiers.Y_LOCATION))
6616                        temp += modifiers.get(Modifiers.Y_LOCATION);
6617
6618                    temp = temp.trim();
6619                    mods.add(new Modifier("X Y", temp, x, y, centered));
6620                }
6621
6622                if(modifiers.containsKey(Modifiers.W_DTG_1))
6623                {
6624                    y = 2;//above center
6625                    if(!strict && !(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH) || modifiers.containsKey(Modifiers.Y_LOCATION)))
6626                        y--;
6627
6628                    temp = modifiers.get(Modifiers.W_DTG_1);
6629
6630                    if(temp != null && !temp.isEmpty())
6631                        mods.add(new Modifier("W", temp, x, y, centered));
6632                }
6633
6634                if(modifiers.containsKey(Modifiers.C_QUANTITY) || modifiers.containsKey(Modifiers.AE_EQUIPMENT_TEARDOWN_TIME))
6635                {
6636                    y = -1;//below center
6637                    temp = "";
6638                    if(modifiers.containsKey(Modifiers.C_QUANTITY))
6639                        temp = modifiers.get(Modifiers.C_QUANTITY) + sep;
6640                    if(modifiers.containsKey(Modifiers.AE_EQUIPMENT_TEARDOWN_TIME))
6641                        temp += modifiers.get(Modifiers.AE_EQUIPMENT_TEARDOWN_TIME);
6642
6643                    temp = temp.trim();
6644                    if(temp != null && !temp.isEmpty())
6645                        mods.add(new Modifier("C AE", temp, x, y, centered));
6646                }
6647
6648                if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
6649                {
6650                    y = -2;
6651                    if(!strict && !(modifiers.containsKey(Modifiers.C_QUANTITY) || modifiers.containsKey(Modifiers.AE_EQUIPMENT_TEARDOWN_TIME)))
6652                        y++;
6653                    temp = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
6654                    if(temp != null && !temp.isEmpty())
6655                        mods.add(new Modifier("T", temp, x, y, centered));
6656                }
6657            }
6658            else if(ss == SymbolID.SymbolSet_Space ||
6659                    ss == SymbolID.SymbolSet_SpaceMissile ||
6660                    ss == SymbolID.SymbolSet_Air ||
6661                    ss == SymbolID.SymbolSet_AirMissile ||
6662                    (ss == SymbolID.SymbolSet_SignalsIntelligence &&
6663                            (fs == SymbolID.FrameShape_Space || fs == SymbolID.FrameShape_Air)))
6664            {
6665                //No top center label
6666                x = 0;//centered
6667                y = 9;//on top of symbol
6668
6669                if(modifiers.containsKey(Modifiers.C_QUANTITY))
6670                {
6671                    temp = modifiers.get(Modifiers.C_QUANTITY);
6672                    if(temp != null && !temp.isEmpty())
6673                        mods.add(new Modifier("C", temp, x, y, centered));
6674                }
6675                else if(modifiers.containsKey(Modifiers.B_ECHELON))
6676                {
6677                    temp = modifiers.get(Modifiers.B_ECHELON);
6678                    if(temp != null && !temp.isEmpty())
6679                        mods.add(new Modifier("B", temp, x, y, centered));
6680                }
6681
6682
6683                //Do right side labels
6684                x = 1;//on right
6685                centered = true;
6686
6687                if(modifiers.containsKey(Modifiers.V_EQUIP_TYPE) || modifiers.containsKey(Modifiers.AF_COMMON_IDENTIFIER))
6688                {
6689                    y = 0;//
6690                    temp = "";
6691                    if(modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
6692                        temp = modifiers.get(Modifiers.V_EQUIP_TYPE) + sep;
6693                    if(modifiers.containsKey(Modifiers.AF_COMMON_IDENTIFIER))
6694                        temp += modifiers.get(Modifiers.AF_COMMON_IDENTIFIER);
6695                    temp = temp.trim();
6696
6697                    if(temp != null && !temp.isEmpty())
6698                        mods.add(new Modifier("V AF", temp, x, y, centered));
6699                }
6700                else
6701                {
6702                    centered = false;
6703                }
6704
6705                if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1) || modifiers.containsKey(Modifiers.Y_LOCATION))
6706                {
6707                    y = 1;//above center
6708                    temp = "";
6709                    if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
6710                        temp = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1) + sep;
6711                    if(modifiers.containsKey(Modifiers.Y_LOCATION))
6712                        temp += modifiers.get(Modifiers.Y_LOCATION);
6713                    temp = temp.trim();
6714
6715                    if(temp != null && !temp.isEmpty())
6716                        mods.add(new Modifier("T Y", temp, x, y, centered));
6717                }
6718
6719                if(modifiers.containsKey(Modifiers.AS_COUNTRY))
6720                {
6721                    y = 2;
6722                    if(!strict && !(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1) || modifiers.containsKey(Modifiers.Y_LOCATION)))
6723                        y--;
6724                    temp = modifiers.get(Modifiers.AS_COUNTRY);
6725
6726                    if(temp != null && !temp.isEmpty())
6727                        mods.add(new Modifier("AS", temp, x, y, centered));
6728                }
6729
6730                if(modifiers.containsKey(Modifiers.P_IFF_SIF_AIS)  ||
6731                        modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH)  ||
6732                        modifiers.containsKey(Modifiers.Z_SPEED))
6733                {
6734                    y = -1;//below center
6735                    temp = "";
6736                    if(modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
6737                        temp = modifiers.get(Modifiers.P_IFF_SIF_AIS) + sep;
6738                    if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH))
6739                        temp += modifiers.get(Modifiers.X_ALTITUDE_DEPTH) + sep;
6740                    if(modifiers.containsKey(Modifiers.Z_SPEED))
6741                        temp += modifiers.get(Modifiers.Z_SPEED);
6742
6743                    temp = temp.trim();
6744
6745                    if(temp != null && !temp.isEmpty())
6746                        mods.add(new Modifier("P X Z", temp, x, y, centered));
6747                }
6748
6749                if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS) ||
6750                        modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1) ||
6751                        modifiers.containsKey(Modifiers.J_EVALUATION_RATING))
6752                {
6753                    y = -2;//below center
6754                    if(!(modifiers.containsKey(Modifiers.P_IFF_SIF_AIS)  ||
6755                            modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH)  ||
6756                            modifiers.containsKey(Modifiers.Z_SPEED)))
6757                        y++;
6758
6759                    temp = "";
6760                    if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
6761                        temp = modifiers.get(Modifiers.G_STAFF_COMMENTS) + sep;
6762                    if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
6763                        temp += modifiers.get(Modifiers.H_ADDITIONAL_INFO_1) + sep;
6764                    if(modifiers.containsKey(Modifiers.J_EVALUATION_RATING))
6765                        temp += modifiers.get(Modifiers.J_EVALUATION_RATING);
6766                    temp = temp.trim();
6767
6768                    if(temp != null && !temp.isEmpty())
6769                        mods.add(new Modifier("G H J", temp, x, y, centered));
6770                }
6771
6772                //No left side labels
6773                x = -1;//on right
6774                centered = true;
6775
6776                if(modifiers.containsKey(Modifiers.AD_PLATFORM_TYPE))
6777                {
6778                    y = 0;//
6779                    temp = modifiers.get(Modifiers.AD_PLATFORM_TYPE);
6780
6781                    if(temp != null && !temp.isEmpty())
6782                        mods.add(new Modifier("AD", temp, x, y, centered));
6783                }
6784                else
6785                {
6786                    centered = false;
6787                }
6788
6789                if(modifiers.containsKey(Modifiers.AR_SPECIAL_DESIGNATOR))
6790                {
6791                    y = 1;//above center
6792                    temp = modifiers.get(Modifiers.AR_SPECIAL_DESIGNATOR);
6793
6794                    if(temp != null && !temp.isEmpty())
6795                        mods.add(new Modifier("AR", temp, x, y, centered));
6796                }
6797
6798                if(modifiers.containsKey(Modifiers.W_DTG_1))
6799                {
6800                    y = 2;
6801                    if(!strict && !modifiers.containsKey(Modifiers.AR_SPECIAL_DESIGNATOR))
6802                        y--;
6803                    temp = modifiers.get(Modifiers.W_DTG_1);
6804
6805                    if(temp != null && !temp.isEmpty())
6806                        mods.add(new Modifier("W", temp, x, y, centered));
6807                }
6808            }
6809            else if(ss == SymbolID.SymbolSet_SeaSurface ||
6810                    (ss == SymbolID.SymbolSet_SignalsIntelligence && fs == SymbolID.FrameShape_SeaSurface))
6811            {
6812                //No top center label
6813
6814
6815                //Do right side labels
6816                x = 1;//on right
6817                centered = false;
6818
6819                if(modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
6820                {
6821                    y = 1;//above center
6822                    temp = modifiers.get(Modifiers.V_EQUIP_TYPE);
6823
6824                    if(temp != null && !temp.isEmpty())
6825                        mods.add(new Modifier("V", temp, x, y, centered));
6826                }
6827
6828                if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
6829                {
6830                    y = 2;
6831                    if(!strict && !modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
6832                        y--;
6833                    temp = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
6834
6835                    if(temp != null && !temp.isEmpty())
6836                        mods.add(new Modifier("T", temp, x, y, centered));
6837                }
6838
6839                if(modifiers.containsKey(Modifiers.AS_COUNTRY))
6840                {
6841                    y = 3;
6842                    if(!strict)
6843                    {
6844                        if(!modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
6845                            y--;
6846                        if(!modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
6847                            y--;
6848                    }
6849
6850                    temp = modifiers.get(Modifiers.AS_COUNTRY );
6851
6852                    if(temp != null && !temp.isEmpty())
6853                        mods.add(new Modifier("AS", temp, x, y, centered));
6854                }
6855
6856                if(modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
6857                {
6858                    y = -1;//below center
6859                    temp = modifiers.get(Modifiers.P_IFF_SIF_AIS);
6860
6861                    if(temp != null && !temp.isEmpty())
6862                        mods.add(new Modifier("P", temp, x, y, centered));
6863                }
6864
6865                if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS)  ||
6866                        modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
6867                {
6868                    y = -2;//below center
6869                    if(!modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
6870                        y++;
6871
6872                    temp = "";
6873                    if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
6874                        temp = modifiers.get(Modifiers.G_STAFF_COMMENTS) + sep;
6875                    if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
6876                        temp += modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
6877                    temp = temp.trim();
6878
6879                    if(temp != null && !temp.isEmpty())
6880                        mods.add(new Modifier("G H", temp, x, y, centered));
6881                }
6882
6883                if(modifiers.containsKey(Modifiers.Y_LOCATION) ||
6884                        modifiers.containsKey(Modifiers.Z_SPEED))
6885                {
6886                    y = -3;
6887                    if(!strict)
6888                    {
6889                        if(!(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS)  ||
6890                                modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1)))
6891                            y++;
6892                        if(!modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
6893                            y++;
6894                    }
6895                    temp = "";
6896                    if(modifiers.containsKey(Modifiers.Y_LOCATION))
6897                        temp = modifiers.get(Modifiers.Y_LOCATION) + sep;
6898                    if(modifiers.containsKey(Modifiers.Z_SPEED))
6899                        temp += modifiers.get(Modifiers.Z_SPEED);
6900                    temp = temp.trim();
6901                    if(temp != null && !temp.isEmpty())
6902                        mods.add(new Modifier("Y Z", temp, x, y, centered));
6903                }
6904
6905                //No left side labels
6906                x = -1;
6907                centered = false;
6908                if(modifiers.containsKey(Modifiers.AQ_GUARDED_UNIT) ||
6909                        modifiers.containsKey(Modifiers.AR_SPECIAL_DESIGNATOR))
6910                {
6911                    y = 2;
6912                    if(!strict)
6913                    {
6914                        y--;
6915                    }
6916                    temp = "";
6917                    if(modifiers.containsKey(Modifiers.AQ_GUARDED_UNIT))
6918                        temp = modifiers.get(Modifiers.AQ_GUARDED_UNIT) + sep;
6919                    if(modifiers.containsKey(Modifiers.AR_SPECIAL_DESIGNATOR))
6920                        temp += modifiers.get(Modifiers.AR_SPECIAL_DESIGNATOR);
6921                    temp = temp.trim();
6922                    if(temp != null && !temp.isEmpty())
6923                        mods.add(new Modifier("AQ AR", temp, x, y, centered));
6924                }
6925            }
6926            else if(ss == SymbolID.SymbolSet_SeaSubsurface ||
6927                    (ss == SymbolID.SymbolSet_SignalsIntelligence && fs == SymbolID.FrameShape_SeaSubsurface))
6928            {
6929                //No top center label
6930
6931
6932                //Do right side labels
6933                x = 1;//on right
6934                centered = false;
6935
6936                if(modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
6937                {
6938                    y = 1;//above center
6939                    temp = modifiers.get(Modifiers.V_EQUIP_TYPE);
6940
6941                    if(temp != null && !temp.isEmpty())
6942                        mods.add(new Modifier("V", temp, x, y, centered));
6943                }
6944
6945                if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
6946                {
6947                    y = 2;
6948                    if(!strict && !modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
6949                        y--;
6950                    temp = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
6951
6952                    if(temp != null && !temp.isEmpty())
6953                        mods.add(new Modifier("T", temp, x, y, centered));
6954                }
6955
6956                if(modifiers.containsKey(Modifiers.AS_COUNTRY))
6957                {
6958                    y = 3;
6959                    if(!strict)
6960                    {
6961                        if(!modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
6962                            y--;
6963                        if(!modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
6964                            y--;
6965                    }
6966
6967                    temp = modifiers.get(Modifiers.AS_COUNTRY );
6968
6969                    if(temp != null && !temp.isEmpty())
6970                        mods.add(new Modifier("AS", temp, x, y, centered));
6971                }
6972
6973                if(modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
6974                {
6975                    y = -1;//below center
6976                    temp = modifiers.get(Modifiers.P_IFF_SIF_AIS);
6977
6978                    if(temp != null && !temp.isEmpty())
6979                        mods.add(new Modifier("P", temp, x, y, centered));
6980                }
6981
6982                if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS)  ||
6983                        modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
6984                {
6985                    y = -2;//below center
6986                    if(!modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
6987                        y++;
6988
6989                    temp = "";
6990                    if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
6991                        temp = modifiers.get(Modifiers.G_STAFF_COMMENTS) + sep;
6992                    if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
6993                        temp += modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
6994                    temp = temp.trim();
6995
6996                    if(temp != null && !temp.isEmpty())
6997                        mods.add(new Modifier("G H", temp, x, y, centered));
6998                }
6999
7000                if(modifiers.containsKey(Modifiers.Y_LOCATION) ||
7001                        modifiers.containsKey(Modifiers.Z_SPEED))
7002                {
7003                    y = -3;
7004                    if(!strict)
7005                    {
7006                        if(!(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS)  ||
7007                                modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1)))
7008                            y++;
7009                        if(!modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
7010                            y++;
7011                    }
7012                    temp = "";
7013                    if(modifiers.containsKey(Modifiers.Y_LOCATION))
7014                        temp = modifiers.get(Modifiers.Y_LOCATION) + sep;
7015                    if(modifiers.containsKey(Modifiers.Z_SPEED))
7016                        temp += modifiers.get(Modifiers.Z_SPEED);
7017                    temp = temp.trim();
7018                    if(temp != null && !temp.isEmpty())
7019                        mods.add(new Modifier("Y Z", temp, x, y, centered));
7020                }
7021
7022                //No left side labels
7023                x = -1;
7024                centered = false;
7025                if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH))
7026                {
7027                    y = 1;
7028                    temp = modifiers.get(Modifiers.X_ALTITUDE_DEPTH);
7029
7030                    if(temp != null && !temp.isEmpty())
7031                        mods.add(new Modifier("X", temp, x, y, centered));
7032                }
7033
7034                if(modifiers.containsKey(Modifiers.AR_SPECIAL_DESIGNATOR))
7035                {
7036                    y = 2;
7037                    if(!strict && !modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH))
7038                    {
7039                        y--;
7040                    }
7041                    temp = modifiers.get(Modifiers.AR_SPECIAL_DESIGNATOR);
7042                    temp = temp.trim();
7043                    if(temp != null && !temp.isEmpty())
7044                        mods.add(new Modifier("AR", temp, x, y, centered));
7045                }
7046            }
7047            else if(ss == SymbolID.SymbolSet_DismountedIndividuals)
7048            {
7049                //No top center label
7050
7051
7052                //Do right side labels
7053                x = 1;//on right
7054                if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
7055                {
7056                    y = 0;//center
7057                    centered = true;//vertically centered, only matters for labels on left and right side
7058                    temp = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
7059
7060                    if(temp != null && !temp.isEmpty())
7061                        mods.add(new Modifier("H", temp, x, y, centered));
7062                }
7063                else if(!strict)
7064                {
7065                    centered = false;
7066                }
7067
7068                if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
7069                {
7070                    y = 1;//above center
7071                    temp = modifiers.get(Modifiers.G_STAFF_COMMENTS);
7072
7073                    if(temp != null && !temp.isEmpty())
7074                        mods.add(new Modifier("G", temp, x, y, centered));
7075                }
7076
7077                if(modifiers.containsKey(Modifiers.AS_COUNTRY))
7078                {
7079                    y = 2;
7080                    if(!strict && !(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS)))
7081                        y--;
7082                    temp = modifiers.get(Modifiers.AS_COUNTRY);
7083
7084                    if(temp != null && !temp.isEmpty())
7085                        mods.add(new Modifier("AS", temp, x, y, centered));
7086                }
7087
7088                if(modifiers.containsKey(Modifiers.M_HIGHER_FORMATION))
7089                {
7090                    y = -1;//below center
7091                    temp = modifiers.get(Modifiers.M_HIGHER_FORMATION);
7092                    if(temp != null && !temp.isEmpty())
7093                        mods.add(new Modifier("M", temp, x, y, centered));
7094                }
7095
7096                if(modifiers.containsKey(Modifiers.J_EVALUATION_RATING) ||
7097                        modifiers.containsKey(Modifiers.K_COMBAT_EFFECTIVENESS) ||
7098                        modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
7099                {
7100                    y = -2;
7101                    if(!strict && !modifiers.containsKey(Modifiers.M_HIGHER_FORMATION))
7102                        y++;
7103                    temp = "";
7104                    if(modifiers.containsKey(Modifiers.J_EVALUATION_RATING))
7105                        temp = modifiers.get(Modifiers.J_EVALUATION_RATING) + sep;
7106                    if(modifiers.containsKey(Modifiers.K_COMBAT_EFFECTIVENESS))
7107                        temp += modifiers.get(Modifiers.K_COMBAT_EFFECTIVENESS) + sep;
7108                    if(modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
7109                        temp += modifiers.get(Modifiers.P_IFF_SIF_AIS);
7110                    temp = temp.trim();
7111                    if(temp != null && !temp.isEmpty())
7112                        mods.add(new Modifier("J K P", temp, x, y, centered));
7113                }
7114
7115                //Do left side labels
7116                x = -1;//on left
7117
7118                if(modifiers.containsKey(Modifiers.V_EQUIP_TYPE) ||
7119                        modifiers.containsKey(Modifiers.AF_COMMON_IDENTIFIER))
7120                {
7121                    y = 0;//center
7122                    centered = true;//vertically centered, only matters for labels on left and right side
7123
7124                    temp = "";
7125                    if(modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
7126                        temp = modifiers.get(Modifiers.V_EQUIP_TYPE) + sep;
7127                    if(modifiers.containsKey(Modifiers.AF_COMMON_IDENTIFIER))
7128                        temp += modifiers.get(Modifiers.AF_COMMON_IDENTIFIER);
7129                    temp = temp.trim();
7130                    if(temp != null && !temp.isEmpty())
7131                        mods.add(new Modifier("V AF", temp, x, y, centered));
7132                }
7133                else if(!strict)
7134                {
7135                    centered = false;
7136                }
7137
7138                if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH) || modifiers.containsKey(Modifiers.Y_LOCATION))
7139                {
7140                    y = 1;
7141                    temp = "";
7142                    if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH))
7143                        temp = modifiers.get(Modifiers.X_ALTITUDE_DEPTH) + sep;
7144                    if(modifiers.containsKey(Modifiers.Y_LOCATION))
7145                        temp += modifiers.get(Modifiers.Y_LOCATION);
7146
7147                    temp = temp.trim();
7148                    mods.add(new Modifier("X Y", temp, x, y, centered));
7149                }
7150
7151                if(modifiers.containsKey(Modifiers.W_DTG_1))
7152                {
7153                    y = 2;//above center
7154                    if(!strict && !(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH) || modifiers.containsKey(Modifiers.Y_LOCATION)))
7155                        y--;
7156
7157                    temp = modifiers.get(Modifiers.W_DTG_1);
7158
7159                    if(temp != null && !temp.isEmpty())
7160                        mods.add(new Modifier("W", temp, x, y, centered));
7161                }
7162
7163                if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
7164                {
7165                    y = -1;//below center
7166                    temp = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
7167
7168                    if(temp != null && !temp.isEmpty())
7169                        mods.add(new Modifier("T", temp, x, y, centered));
7170                }
7171
7172                if(modifiers.containsKey(Modifiers.Z_SPEED))
7173                {
7174                    y = -2;
7175                    if(!strict && !(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1)))
7176                        y++;
7177                    temp = modifiers.get(Modifiers.Z_SPEED);
7178                    if(temp != null && !temp.isEmpty())
7179                        mods.add(new Modifier("Z", temp, x, y, centered));
7180                }
7181            }
7182            else if(ss == SymbolID.SymbolSet_Activities)
7183            {
7184                //No top center label
7185
7186
7187                //Do right side labels
7188                x = 1;//on right
7189                if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
7190                {
7191                    y = 0;//center
7192                    centered = true;//vertically centered, only matters for labels on left and right side
7193                    temp = modifiers.get(Modifiers.G_STAFF_COMMENTS);
7194
7195                    if(temp != null && !temp.isEmpty())
7196                        mods.add(new Modifier("G", temp, x, y, centered));
7197                }
7198                else if(!strict)
7199                {
7200                    centered = false;
7201                }
7202
7203                if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
7204                {
7205                    y = 1;//above center
7206                    temp = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
7207
7208                    if(temp != null && !temp.isEmpty())
7209                        mods.add(new Modifier("T", temp, x, y, centered));
7210                }
7211
7212                if(modifiers.containsKey(Modifiers.AS_COUNTRY))
7213                {
7214                    y = 2;
7215                    if(!strict && !(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1)))
7216                        y--;
7217                    temp = modifiers.get(Modifiers.AS_COUNTRY);
7218
7219                    if(temp != null && !temp.isEmpty())
7220                        mods.add(new Modifier("AS", temp, x, y, centered));
7221                }
7222
7223                if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
7224                {
7225                    y = -1;//below center
7226                    temp = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
7227                    if(temp != null && !temp.isEmpty())
7228                        mods.add(new Modifier("H", temp, x, y, centered));
7229                }
7230
7231                if(modifiers.containsKey(Modifiers.J_EVALUATION_RATING))
7232                {
7233                    y = -2;
7234                    if(!strict && !modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
7235                        y++;
7236                    temp = modifiers.get(Modifiers.J_EVALUATION_RATING);
7237
7238                    if(temp != null && !temp.isEmpty())
7239                        mods.add(new Modifier("J", temp, x, y, centered));
7240                }
7241
7242                //Do left side labels
7243                x = -1;//on left
7244
7245                if(!strict)
7246                {
7247                    centered = false;
7248                }
7249
7250                if(modifiers.containsKey(Modifiers.Y_LOCATION))
7251                {
7252                    y = 1;
7253                    temp = modifiers.get(Modifiers.Y_LOCATION);
7254
7255                    if(temp != null && !temp.isEmpty())
7256                        mods.add(new Modifier("Y", temp, x, y, centered));
7257                }
7258
7259                if(modifiers.containsKey(Modifiers.W_DTG_1))
7260                {
7261                    y = 2;//above center
7262                    if(!strict && !(modifiers.containsKey(Modifiers.Y_LOCATION)))
7263                        y--;
7264
7265                    temp = modifiers.get(Modifiers.W_DTG_1);
7266
7267                    if(temp != null && !temp.isEmpty())
7268                        mods.add(new Modifier("W", temp, x, y, centered));
7269                }
7270
7271                if(modifiers.containsKey(Modifiers.C_QUANTITY))
7272                {
7273                    y = -1;//below center
7274                    temp = modifiers.get(Modifiers.C_QUANTITY);
7275
7276                    if(temp != null && !temp.isEmpty())
7277                        mods.add(new Modifier("C", temp, x, y, centered));
7278                }
7279
7280            }
7281            else if(ss == SymbolID.SymbolSet_CyberSpace ||
7282                    (ss == SymbolID.SymbolSet_SignalsIntelligence && fs == SymbolID.FrameShape_Cyberspace))
7283            {
7284                //Do top center label
7285                x = 0;//centered
7286                y = 9;//on top of symbol
7287                if(modifiers.containsKey(Modifiers.B_ECHELON))
7288                {
7289                    temp = modifiers.get(Modifiers.B_ECHELON);
7290                    if(temp != null && !temp.isEmpty())
7291                        mods.add(new Modifier("B", temp, x, y, centered));
7292                }
7293
7294                //Do right side labels
7295                x = 1;//on right
7296                if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
7297                {
7298                    y = 0;//center
7299                    centered = true;//vertically centered, only matters for labels on left and right side
7300                    temp = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
7301
7302                    if(temp != null && !temp.isEmpty())
7303                        mods.add(new Modifier("H", temp, x, y, centered));
7304                }
7305                else if(!strict)
7306                {
7307                    centered = false;
7308                }
7309
7310                if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
7311                {
7312                    y = 1;//above center
7313                    temp = modifiers.get(Modifiers.G_STAFF_COMMENTS);
7314
7315                    if(temp != null && !temp.isEmpty())
7316                        mods.add(new Modifier("G", temp, x, y, centered));
7317                }
7318
7319                if(modifiers.containsKey(Modifiers.F_REINFORCED_REDUCED) || modifiers.containsKey(Modifiers.AS_COUNTRY))
7320                {
7321                    y = 2;
7322                    if(!strict && !(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS)))
7323                        y--;
7324                    temp = "";
7325                    if(modifiers.containsKey(Modifiers.F_REINFORCED_REDUCED))
7326                        temp = modifiers.get(Modifiers.F_REINFORCED_REDUCED) + sep;
7327                    if(modifiers.containsKey(Modifiers.AS_COUNTRY))
7328                        temp += modifiers.get(Modifiers.AS_COUNTRY);
7329                    temp = temp.trim();
7330                    if(temp != null && !temp.isEmpty())
7331                        mods.add(new Modifier("F AS", temp, x, y, centered));
7332                }
7333
7334                if(modifiers.containsKey(Modifiers.M_HIGHER_FORMATION))
7335                {
7336                    y = -1;//below center
7337                    temp = modifiers.get(Modifiers.M_HIGHER_FORMATION);
7338                    if(temp != null && !temp.isEmpty())
7339                        mods.add(new Modifier("M", temp, x, y, centered));
7340                }
7341
7342                if(modifiers.containsKey(Modifiers.K_COMBAT_EFFECTIVENESS) || modifiers.containsKey(Modifiers.L_SIGNATURE_EQUIP))
7343                {
7344                    y = -2;
7345                    if(!strict && !modifiers.containsKey(Modifiers.M_HIGHER_FORMATION))
7346                        y++;
7347                    temp = "";
7348                    if(modifiers.containsKey(Modifiers.K_COMBAT_EFFECTIVENESS))
7349                        temp = modifiers.get(Modifiers.K_COMBAT_EFFECTIVENESS) + sep;
7350                    if(modifiers.containsKey(Modifiers.L_SIGNATURE_EQUIP))
7351                        temp += modifiers.get(Modifiers.L_SIGNATURE_EQUIP);
7352                    temp = temp.trim();
7353                    if(temp != null && !temp.isEmpty())
7354                        mods.add(new Modifier("K L", temp, x, y, centered));
7355                }
7356
7357                //Do left side labels
7358                x=-1;
7359                if(modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
7360                {
7361                    y = 0;//center
7362                    centered = true;//vertically centered, only matters for labels on left and right side
7363
7364                    temp = modifiers.get(Modifiers.V_EQUIP_TYPE);
7365
7366                    if(temp != null && !temp.isEmpty())
7367                        mods.add(new Modifier("V", temp, x, y, centered));
7368                }
7369                else if(!strict)
7370                {
7371                    centered = false;
7372                }
7373
7374                if(modifiers.containsKey(Modifiers.Y_LOCATION))
7375                {
7376                    y = 1;
7377                    temp = modifiers.get(Modifiers.Y_LOCATION);
7378
7379                    if(temp != null && !temp.isEmpty())
7380                        mods.add(new Modifier("Y", temp, x, y, centered));
7381                }
7382
7383                if(modifiers.containsKey(Modifiers.W_DTG_1))
7384                {
7385                    y = 2;//above center
7386                    if(!strict && !(modifiers.containsKey(Modifiers.Y_LOCATION)))
7387                        y--;
7388
7389                    temp = modifiers.get(Modifiers.W_DTG_1);
7390
7391                    if(temp != null && !temp.isEmpty())
7392                        mods.add(new Modifier("W", temp, x, y, centered));
7393                }
7394
7395                if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
7396                {
7397                    y = -1;//below center
7398                    temp = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
7399
7400                    if(temp != null && !temp.isEmpty())
7401                        mods.add(new Modifier("T", temp, x, y, centered));
7402                }
7403            }
7404            /*else if(ver == SymbolID.SymbolSet_MineWarfare)
7405            {
7406                //no modifiers
7407            }//*/
7408            //else//SymbolSet Unknown
7409            //processUnknownTextModifiers
7410        }
7411        else if(ver >= SymbolID.Version_APP6D)
7412        {
7413            int fs = SymbolID.getFrameShape(symbolID);
7414            if(ss == SymbolID.SymbolSet_LandUnit ||
7415                    ss == SymbolID.SymbolSet_LandCivilianUnit_Organization)
7416            {
7417
7418                //Only Command & Control has AA; ec.equals("110000").  Always in the middle of the unit.
7419                if(modifiers.containsKey(Modifiers.AA_SPECIAL_C2_HQ))
7420                {
7421                    temp = modifiers.get(Modifiers.AA_SPECIAL_C2_HQ);
7422                    if(temp != null && !temp.isEmpty())
7423                        mods.add(new Modifier("AA", temp, 0, 0, true));
7424                }
7425
7426                //Do top center label
7427                x = 0;//centered
7428                y = 9;//on top of symbol
7429                if(modifiers.containsKey(Modifiers.B_ECHELON))
7430                {
7431                    temp = modifiers.get(Modifiers.B_ECHELON);
7432                    if(temp != null && !temp.isEmpty())
7433                        mods.add(new Modifier("B", temp, x, y, centered));
7434                }
7435
7436                //Do right side labels
7437                x = 1;//on right
7438                if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1) ||
7439                        modifiers.containsKey(Modifiers.AF_COMMON_IDENTIFIER))
7440                {
7441                    y = 0;//center
7442                    centered = true;//vertically centered, only matters for labels on left and right side
7443                    temp = "";
7444                    if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
7445                        temp = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1) + sep;
7446                    if(modifiers.containsKey(Modifiers.AF_COMMON_IDENTIFIER))
7447                        temp += modifiers.get(Modifiers.AF_COMMON_IDENTIFIER);
7448                    temp = temp.trim();
7449                    if(temp != null && !temp.isEmpty())
7450                        mods.add(new Modifier("H AF", temp, x, y, centered));
7451                }
7452                else if(!strict)
7453                {
7454                    //if no "H', bring G and M closer to the center
7455                    centered = false;
7456                }
7457
7458                if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS) || modifiers.containsKey(Modifiers.AQ_GUARDED_UNIT))
7459                {
7460                    y = 1;//above center
7461                    temp = "";
7462                    if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
7463                        temp = modifiers.get(Modifiers.G_STAFF_COMMENTS) + sep;
7464                    if(modifiers.containsKey(Modifiers.AQ_GUARDED_UNIT))
7465                        temp += modifiers.get(Modifiers.AQ_GUARDED_UNIT);
7466                    temp = temp.trim();
7467                    if(temp != null && !temp.isEmpty())
7468                        mods.add(new Modifier("G AQ", temp, x, y, centered));
7469                }
7470
7471                if(modifiers.containsKey(Modifiers.F_REINFORCED_REDUCED) || modifiers.containsKey(Modifiers.AS_COUNTRY))
7472                {
7473                    y = 2;
7474                    if(!strict && !(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS) || modifiers.containsKey(Modifiers.AQ_GUARDED_UNIT)))
7475                        y--;
7476                    temp = "";
7477                    if(modifiers.containsKey(Modifiers.F_REINFORCED_REDUCED))
7478                        temp = modifiers.get(Modifiers.F_REINFORCED_REDUCED) + sep;
7479                    if(modifiers.containsKey(Modifiers.AS_COUNTRY))
7480                        temp += modifiers.get(Modifiers.AS_COUNTRY);
7481                    temp = temp.trim();
7482                    if(temp != null && !temp.isEmpty())
7483                        mods.add(new Modifier("F AS", temp, x, y, centered));
7484                }
7485
7486                if(modifiers.containsKey(Modifiers.M_HIGHER_FORMATION))
7487                {
7488                    y = -1;//below center
7489                    temp = modifiers.get(Modifiers.M_HIGHER_FORMATION);
7490                    if(temp != null && !temp.isEmpty())
7491                        mods.add(new Modifier("M", temp, x, y, centered));
7492                }
7493
7494                if(modifiers.containsKey(Modifiers.J_EVALUATION_RATING) ||
7495                        modifiers.containsKey(Modifiers.K_COMBAT_EFFECTIVENESS) ||
7496                        modifiers.containsKey(Modifiers.L_SIGNATURE_EQUIP) ||
7497                        modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
7498                {
7499                    y = -2;
7500                    if(!strict && !modifiers.containsKey(Modifiers.M_HIGHER_FORMATION))
7501                        y++;
7502                    temp = "";
7503                    if(modifiers.containsKey(Modifiers.J_EVALUATION_RATING))
7504                        temp = modifiers.get(Modifiers.J_EVALUATION_RATING) + sep;
7505                    if(modifiers.containsKey(Modifiers.K_COMBAT_EFFECTIVENESS))
7506                        temp += modifiers.get(Modifiers.K_COMBAT_EFFECTIVENESS) + sep;
7507                    if(modifiers.containsKey(Modifiers.L_SIGNATURE_EQUIP))
7508                        temp += modifiers.get(Modifiers.L_SIGNATURE_EQUIP) + sep;
7509                    if(modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
7510                        temp += modifiers.get(Modifiers.P_IFF_SIF_AIS);
7511                    temp = temp.trim();
7512                    if(temp != null && !temp.isEmpty())
7513                        mods.add(new Modifier("J K L P", temp, x, y, centered));
7514                }
7515
7516                //Do left side labels
7517                x = -1;//on left
7518
7519                if(modifiers.containsKey(Modifiers.V_EQUIP_TYPE) ||
7520                        modifiers.containsKey(Modifiers.AD_PLATFORM_TYPE) ||
7521                        modifiers.containsKey(Modifiers.AE_EQUIPMENT_TEARDOWN_TIME))
7522                {
7523                    y = 0;//center
7524                    centered = true;//vertically centered, only matters for labels on left and right side
7525
7526                    temp = "";
7527                    if(modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
7528                        temp = modifiers.get(Modifiers.V_EQUIP_TYPE) + sep;
7529                    if(modifiers.containsKey(Modifiers.AD_PLATFORM_TYPE))
7530                        temp += modifiers.get(Modifiers.AD_PLATFORM_TYPE) + sep;
7531                    if(modifiers.containsKey(Modifiers.AE_EQUIPMENT_TEARDOWN_TIME))
7532                        temp += modifiers.get(Modifiers.AE_EQUIPMENT_TEARDOWN_TIME);
7533                    temp = temp.trim();
7534                    if(temp != null && !temp.isEmpty())
7535                        mods.add(new Modifier("V AD AE", temp, x, y, centered));
7536                }
7537                else if(!strict)
7538                {
7539                    centered = false;
7540                }
7541
7542                if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH) || modifiers.containsKey(Modifiers.Y_LOCATION))
7543                {
7544                    y = 1;
7545                    temp = "";
7546                    if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH))
7547                        temp = modifiers.get(Modifiers.X_ALTITUDE_DEPTH) + sep;
7548                    if(modifiers.containsKey(Modifiers.Y_LOCATION))
7549                        temp += modifiers.get(Modifiers.Y_LOCATION);
7550
7551                    temp = temp.trim();
7552                    mods.add(new Modifier("X Y", temp, x, y, centered));
7553                }
7554
7555                if(modifiers.containsKey(Modifiers.W_DTG_1))
7556                {
7557                    y = 2;//above center
7558                    if(!strict && !(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH) || modifiers.containsKey(Modifiers.Y_LOCATION)))
7559                        y--;
7560
7561                    temp = modifiers.get(Modifiers.W_DTG_1);
7562
7563                    if(temp != null && !temp.isEmpty())
7564                        mods.add(new Modifier("W", temp, x, y, centered));
7565                }
7566
7567                if(modifiers.containsKey(Modifiers.C_QUANTITY) || modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
7568                {
7569                    y = -1;//below center
7570                    temp = "";
7571                    if(modifiers.containsKey(Modifiers.C_QUANTITY))
7572                        temp = modifiers.get(Modifiers.C_QUANTITY) + sep;
7573                    if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
7574                        temp += modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
7575
7576                    temp = temp.trim();
7577                    if(temp != null && !temp.isEmpty())
7578                        mods.add(new Modifier("C T", temp, x, y, centered));
7579                }
7580
7581                if(modifiers.containsKey(Modifiers.Z_SPEED))
7582                {
7583                    y = -2;
7584                    if(!strict && !(modifiers.containsKey(Modifiers.C_QUANTITY) || modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1)))
7585                        y++;
7586                    temp = modifiers.get(Modifiers.Z_SPEED);
7587                    if(temp != null && !temp.isEmpty())
7588                        mods.add(new Modifier("Z", temp, x, y, centered));
7589                }
7590            }
7591            else if(ss == SymbolID.SymbolSet_LandEquipment)
7592            {
7593                //Do top center label
7594                x = 0;//centered
7595                y = 9;//on top of symbol
7596                if(modifiers.containsKey(Modifiers.C_QUANTITY))
7597                {
7598                    temp = modifiers.get(Modifiers.C_QUANTITY);
7599                    if(temp != null && !temp.isEmpty())
7600                        mods.add(new Modifier("C", temp, x, y, centered));
7601                }
7602
7603                //Do right side labels
7604                x = 1;//on right
7605                centered = false;
7606
7607                if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS) || modifiers.containsKey(Modifiers.AQ_GUARDED_UNIT))
7608                {
7609                    y = 1;//above center
7610                    temp = "";
7611                    if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
7612                        temp = modifiers.get(Modifiers.G_STAFF_COMMENTS) + sep;
7613                    if(modifiers.containsKey(Modifiers.AQ_GUARDED_UNIT))
7614                        temp += modifiers.get(Modifiers.AQ_GUARDED_UNIT);
7615                    temp = temp.trim();
7616                    if(temp != null && !temp.isEmpty())
7617                        mods.add(new Modifier("G AQ", temp, x, y, centered));
7618                }
7619
7620                if( modifiers.containsKey(Modifiers.AS_COUNTRY))
7621                {
7622                    y = 2;
7623                    if(!strict && !(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS) || modifiers.containsKey(Modifiers.AQ_GUARDED_UNIT)))
7624                        y--;
7625                    temp = modifiers.get(Modifiers.AS_COUNTRY);
7626
7627                    if(temp != null && !temp.isEmpty())
7628                        mods.add(new Modifier("AS", temp, x, y, centered));
7629                }
7630
7631                if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1) ||
7632                        modifiers.containsKey(Modifiers.AE_EQUIPMENT_TEARDOWN_TIME))
7633                {
7634                    y = 0;
7635                    temp = "";
7636                    if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
7637                        temp = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1) + sep;
7638                    if(modifiers.containsKey(Modifiers.AE_EQUIPMENT_TEARDOWN_TIME))
7639                        temp += modifiers.get(Modifiers.AE_EQUIPMENT_TEARDOWN_TIME);
7640                    temp = temp.trim();
7641                    if(temp != null && !temp.isEmpty())
7642                        mods.add(new Modifier("H AE", temp, x, y, centered));
7643                }
7644
7645                if( modifiers.containsKey(Modifiers.M_HIGHER_FORMATION))
7646                {
7647                    y = -1;
7648                    if(!strict && !(modifiers.containsKey(Modifiers.M_HIGHER_FORMATION)))
7649                        y++;
7650                    temp = modifiers.get(Modifiers.M_HIGHER_FORMATION);
7651
7652                    if(temp != null && !temp.isEmpty())
7653                        mods.add(new Modifier("M", temp, x, y, centered));
7654                }
7655
7656                if(modifiers.containsKey(Modifiers.J_EVALUATION_RATING) ||
7657                        modifiers.containsKey(Modifiers.K_COMBAT_EFFECTIVENESS) ||
7658                        modifiers.containsKey(Modifiers.L_SIGNATURE_EQUIP) ||
7659                        modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
7660                {
7661                    y = -2;
7662                    if(!strict && !(modifiers.containsKey(Modifiers.M_HIGHER_FORMATION)))
7663                        y++;
7664                    temp = "";
7665                    if(modifiers.containsKey(Modifiers.J_EVALUATION_RATING))
7666                        temp = modifiers.get(Modifiers.J_EVALUATION_RATING) + sep;
7667                    if(modifiers.containsKey(Modifiers.K_COMBAT_EFFECTIVENESS))
7668                        temp += modifiers.get(Modifiers.K_COMBAT_EFFECTIVENESS) + sep;
7669                    if(modifiers.containsKey(Modifiers.L_SIGNATURE_EQUIP))
7670                        temp += modifiers.get(Modifiers.L_SIGNATURE_EQUIP) + sep;
7671                    if(modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
7672                        temp += modifiers.get(Modifiers.P_IFF_SIF_AIS);
7673                    temp = temp.trim();
7674                    if(temp != null && !temp.isEmpty())
7675                        mods.add(new Modifier("J K L P", temp, x, y, centered));
7676                }
7677
7678                //Do left side labels
7679                x = -1;//on left
7680
7681                if(modifiers.containsKey(Modifiers.V_EQUIP_TYPE) ||
7682                        modifiers.containsKey(Modifiers.AD_PLATFORM_TYPE) ||
7683                        modifiers.containsKey(Modifiers.AE_EQUIPMENT_TEARDOWN_TIME))
7684                {
7685                    y = 0;//center
7686                    centered = true;//vertically centered, only matters for labels on left and right side
7687
7688                    temp = "";
7689                    if(modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
7690                        temp = modifiers.get(Modifiers.V_EQUIP_TYPE) + sep;
7691                    if(modifiers.containsKey(Modifiers.AD_PLATFORM_TYPE))
7692                        temp += modifiers.get(Modifiers.AD_PLATFORM_TYPE) + sep;
7693                    if(modifiers.containsKey(Modifiers.AF_COMMON_IDENTIFIER))
7694                        temp += modifiers.get(Modifiers.AF_COMMON_IDENTIFIER);
7695                    temp = temp.trim();
7696                    if(temp != null && !temp.isEmpty())
7697                        mods.add(new Modifier("V AD AF", temp, x, y, centered));
7698                }
7699                else if(!strict)
7700                {
7701                    centered = false;
7702                }
7703
7704                if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH) || modifiers.containsKey(Modifiers.Y_LOCATION))
7705                {
7706                    y = 1;
7707                    temp = "";
7708                    if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH))
7709                        temp = modifiers.get(Modifiers.X_ALTITUDE_DEPTH) + sep;
7710                    if(modifiers.containsKey(Modifiers.Y_LOCATION))
7711                        temp += modifiers.get(Modifiers.Y_LOCATION);
7712
7713                    temp = temp.trim();
7714                    mods.add(new Modifier("X Y", temp, x, y, centered));
7715                }
7716
7717                if(modifiers.containsKey(Modifiers.W_DTG_1))
7718                {
7719                    y = 2;//above center
7720                    if(!strict && !(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH) || modifiers.containsKey(Modifiers.Y_LOCATION)))
7721                        y--;
7722
7723                    temp = modifiers.get(Modifiers.W_DTG_1);
7724
7725                    if(temp != null && !temp.isEmpty())
7726                        mods.add(new Modifier("W", temp, x, y, centered));
7727                }
7728
7729                if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
7730                {
7731                    y = -1;//below center
7732                    temp = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
7733
7734                    temp = temp.trim();
7735                    if(temp != null && !temp.isEmpty())
7736                        mods.add(new Modifier("T", temp, x, y, centered));
7737                }
7738
7739                if(modifiers.containsKey(Modifiers.Z_SPEED))
7740                {
7741                    y = -2;
7742                    if(!strict && !modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
7743                        y++;
7744                    temp = modifiers.get(Modifiers.Z_SPEED);
7745                    if(temp != null && !temp.isEmpty())
7746                        mods.add(new Modifier("Z", temp, x, y, centered));
7747                }
7748            }
7749            else if(ss == SymbolID.SymbolSet_LandInstallation)
7750            {
7751                //No top center label
7752
7753                //Do right side labels
7754                x = 1;//on right
7755                if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1) || modifiers.containsKey(Modifiers.AE_EQUIPMENT_TEARDOWN_TIME))
7756                {
7757                    y = 0;//center
7758                    centered = true;//vertically centered, only matters for labels on left and right side
7759                    temp = "";
7760                    if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
7761                        temp = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1) + sep;
7762                    if(modifiers.containsKey(Modifiers.AE_EQUIPMENT_TEARDOWN_TIME))
7763                        temp += modifiers.get(Modifiers.AE_EQUIPMENT_TEARDOWN_TIME);
7764                    temp = temp.trim();
7765
7766                    if(temp != null && !temp.isEmpty())
7767                        mods.add(new Modifier("H AE", temp, x, y, centered));
7768                }
7769                else if(!strict)
7770                {
7771                    //if no "H', bring G and M closer to the center
7772                    centered = false;
7773                }
7774
7775                if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS) || modifiers.containsKey(Modifiers.AQ_GUARDED_UNIT))
7776                {
7777                    y = 1;//above center
7778                    temp = "";
7779                    if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
7780                        temp = modifiers.get(Modifiers.G_STAFF_COMMENTS) + sep;
7781                    if(modifiers.containsKey(Modifiers.AQ_GUARDED_UNIT))
7782                        temp += modifiers.get(Modifiers.AQ_GUARDED_UNIT);
7783                    temp = temp.trim();
7784                    if(temp != null && !temp.isEmpty())
7785                        mods.add(new Modifier("G AQ", temp, x, y, centered));
7786                }
7787
7788                if(modifiers.containsKey(Modifiers.AS_COUNTRY))
7789                {
7790                    y = 2;
7791                    if(!strict && !(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS) || modifiers.containsKey(Modifiers.AQ_GUARDED_UNIT)))
7792                        y--;
7793                    temp = modifiers.get(Modifiers.AS_COUNTRY);
7794
7795                    if(temp != null && !temp.isEmpty())
7796                        mods.add(new Modifier("AS", temp, x, y, centered));
7797                }
7798
7799                if(modifiers.containsKey(Modifiers.M_HIGHER_FORMATION))
7800                {
7801                    y = -1;//below center
7802                    temp = modifiers.get(Modifiers.M_HIGHER_FORMATION);
7803                    if(temp != null && !temp.isEmpty())
7804                        mods.add(new Modifier("M", temp, x, y, centered));
7805                }
7806
7807                if(modifiers.containsKey(Modifiers.J_EVALUATION_RATING) ||
7808                        modifiers.containsKey(Modifiers.K_COMBAT_EFFECTIVENESS) ||
7809                        modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
7810                {
7811                    y = -2;
7812                    if(!strict && !modifiers.containsKey(Modifiers.M_HIGHER_FORMATION))
7813                        y++;
7814                    temp = "";
7815                    if(modifiers.containsKey(Modifiers.J_EVALUATION_RATING))
7816                        temp = modifiers.get(Modifiers.J_EVALUATION_RATING) + sep;
7817                    if(modifiers.containsKey(Modifiers.K_COMBAT_EFFECTIVENESS))
7818                        temp += modifiers.get(Modifiers.K_COMBAT_EFFECTIVENESS);
7819                    temp = temp.trim();
7820                    if(temp != null && !temp.isEmpty())
7821                        mods.add(new Modifier("J K P", temp, x, y, centered));
7822                }
7823
7824                //Do left side labels
7825                x = -1;//on left
7826                centered = false;
7827
7828                if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH) || modifiers.containsKey(Modifiers.Y_LOCATION))
7829                {
7830                    y = 0;//center
7831                    centered = true;//vertically centered, only matters for labels on left and right side
7832
7833                    temp = "";
7834                    if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH))
7835                        temp = modifiers.get(Modifiers.X_ALTITUDE_DEPTH) + sep;
7836                    if(modifiers.containsKey(Modifiers.Y_LOCATION))
7837                        temp += modifiers.get(Modifiers.Y_LOCATION);
7838                    temp = temp.trim();
7839                    if(temp != null && !temp.isEmpty())
7840                        mods.add(new Modifier("X Y", temp, x, y, centered));
7841                }
7842                else if(!strict)
7843                {
7844                    centered = false;
7845                }
7846
7847                if(modifiers.containsKey(Modifiers.W_DTG_1))
7848                {
7849                    y = 1;//above center
7850
7851                    temp = modifiers.get(Modifiers.W_DTG_1);
7852
7853                    if(temp != null && !temp.isEmpty())
7854                        mods.add(new Modifier("W AR", temp, x, y, centered));
7855                }
7856
7857                if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
7858                {
7859                    y = -1;//below center
7860                    temp = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
7861                    if(temp != null && !temp.isEmpty())
7862                        mods.add(new Modifier("T", temp, x, y, centered));
7863                }
7864            }
7865            else if(ss == SymbolID.SymbolSet_Air ||
7866                    ss == SymbolID.SymbolSet_AirMissile)
7867            {
7868                //No top center label
7869
7870
7871                //Do right side labels
7872                x = 1;//on right
7873                centered = false;
7874
7875                centered = true;
7876                if(modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
7877                {
7878                    y = 0;//center
7879                    centered = true;//vertically centered, only matters for labels on left and right side
7880                    temp = modifiers.get(Modifiers.V_EQUIP_TYPE);
7881                    if(temp != null && !temp.isEmpty())
7882                        mods.add(new Modifier("V", temp, x, y, centered));
7883                }
7884                else if(!strict)
7885                {
7886                    //if no "H', bring G and M closer to the center
7887                    centered = false;
7888                }
7889
7890                if(modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
7891                {
7892                    y = 1;//above center
7893                    temp = modifiers.get(Modifiers.P_IFF_SIF_AIS);
7894
7895                    if(temp != null && !temp.isEmpty())
7896                        mods.add(new Modifier("P", temp, x, y, centered));
7897                }
7898
7899                if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1) || modifiers.containsKey(Modifiers.AS_COUNTRY))
7900                {
7901                    y = 2;
7902                    if(!strict && !modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
7903                        y--;
7904                    temp = "";
7905                    if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
7906                        temp = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1) + sep;
7907                    if(modifiers.containsKey(Modifiers.AS_COUNTRY))
7908                        temp += modifiers.get(Modifiers.AS_COUNTRY);
7909                    temp = temp.trim();
7910
7911                    if(temp != null && !temp.isEmpty())
7912                        mods.add(new Modifier("T AS", temp, x, y, centered));
7913                }
7914
7915                if(modifiers.containsKey(Modifiers.Z_SPEED)  ||
7916                        modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH))
7917                {
7918                    y = -1;//below center
7919
7920                    temp = "";
7921                    if(modifiers.containsKey(Modifiers.Z_SPEED))
7922                        temp = modifiers.get(Modifiers.Z_SPEED) + sep;
7923                    if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH))
7924                        temp += modifiers.get(Modifiers.X_ALTITUDE_DEPTH);
7925                    temp = temp.trim();
7926
7927                    if(temp != null && !temp.isEmpty())
7928                        mods.add(new Modifier("Z X", temp, x, y, centered));
7929                }
7930
7931                if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS) ||
7932                        modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
7933                {
7934                    y = -2;
7935                    if(!strict)
7936                    {
7937                        if(!(modifiers.containsKey(Modifiers.Z_SPEED)  ||
7938                                modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH)))
7939                            y++;
7940                    }
7941                    temp = "";
7942                    if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
7943                        temp = modifiers.get(Modifiers.G_STAFF_COMMENTS) + sep;
7944                    if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
7945                        temp += modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
7946                    temp = temp.trim();
7947                    if(temp != null && !temp.isEmpty())
7948                        mods.add(new Modifier("G H", temp, x, y, centered));
7949                }
7950
7951                //No left side labels
7952
7953            }
7954            else if(ss == SymbolID.SymbolSet_Space ||
7955                    ss == SymbolID.SymbolSet_SpaceMissile)
7956            {
7957                //No top center label
7958
7959
7960                //Do right side labels
7961                x = 1;//on right
7962                centered = false;
7963
7964                if(modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
7965                {
7966                    y = 1;//above center
7967                    temp = modifiers.get(Modifiers.V_EQUIP_TYPE);
7968                    if(temp != null && !temp.isEmpty())
7969                        mods.add(new Modifier("V", temp, x, y, centered));
7970                }
7971
7972                if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1) || modifiers.containsKey(Modifiers.AS_COUNTRY))
7973                {
7974                    y = 2;
7975                    if(!strict && !modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
7976                        y--;
7977                    temp = "";
7978                    if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
7979                        temp = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1) + sep;
7980                    if(modifiers.containsKey(Modifiers.AS_COUNTRY))
7981                        temp += modifiers.get(Modifiers.AS_COUNTRY);
7982                    temp = temp.trim();
7983
7984                    if(temp != null && !temp.isEmpty())
7985                        mods.add(new Modifier("T AS", temp, x, y, centered));
7986                }
7987
7988                if(modifiers.containsKey(Modifiers.Z_SPEED)  ||
7989                        modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH))
7990                {
7991                    y = -1;//below center
7992                    temp = "";
7993                    if(modifiers.containsKey(Modifiers.Z_SPEED))
7994                        temp = modifiers.get(Modifiers.Z_SPEED) + sep;
7995                    if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH))
7996                        temp += modifiers.get(Modifiers.X_ALTITUDE_DEPTH);
7997                    temp = temp.trim();
7998
7999                    if(temp != null && !temp.isEmpty())
8000                        mods.add(new Modifier("Z X", temp, x, y, centered));
8001                }
8002
8003                if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS) ||
8004                        modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
8005                {
8006                    y = -2;
8007                    if(!strict &&
8008                            !(modifiers.containsKey(Modifiers.Z_SPEED) || modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH)))
8009                        y++;
8010                    temp = "";
8011                    if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
8012                        temp = modifiers.get(Modifiers.G_STAFF_COMMENTS) + sep;
8013                    if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
8014                        temp += modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
8015                    temp = temp.trim();
8016                    if(temp != null && !temp.isEmpty())
8017                        mods.add(new Modifier("G H", temp, x, y, centered));
8018                }
8019
8020                //No left side labels
8021            }
8022            else if(ss == SymbolID.SymbolSet_SeaSurface)
8023            {
8024                //No top center label
8025
8026
8027                //Do right side labels
8028                x = 1;//on right
8029                centered = true;
8030                if(modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
8031                {
8032                    y = 0;//center
8033                    centered = true;//vertically centered, only matters for labels on left and right side
8034                    temp = modifiers.get(Modifiers.P_IFF_SIF_AIS);
8035                    if(temp != null && !temp.isEmpty())
8036                        mods.add(new Modifier("P", temp, x, y, centered));
8037                }
8038                else if(!strict)
8039                {
8040                    //if no "X', bring V and G closer to the center
8041                    centered = false;
8042                }
8043
8044                if(modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
8045                {
8046                    y = 1;//above center
8047                    temp = modifiers.get(Modifiers.V_EQUIP_TYPE);
8048                    if(temp != null && !temp.isEmpty())
8049                        mods.add(new Modifier("V", temp, x, y, centered));
8050                }
8051
8052                if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1) || modifiers.containsKey(Modifiers.AS_COUNTRY))
8053                {
8054                    y = 2;
8055                    if(!strict && !modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
8056                        y--;
8057                    temp = "";
8058                    if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
8059                        temp = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1) + sep;
8060                    if(modifiers.containsKey(Modifiers.AS_COUNTRY))
8061                        temp += modifiers.get(Modifiers.AS_COUNTRY);
8062                    temp = temp.trim();
8063
8064                    if(temp != null && !temp.isEmpty())
8065                        mods.add(new Modifier("T AS", temp, x, y, centered));
8066                }
8067
8068
8069                if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS)  ||
8070                        modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
8071                {
8072                    y = -1;//below center
8073                    temp = "";
8074                    if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
8075                        temp = modifiers.get(Modifiers.G_STAFF_COMMENTS) + sep;
8076                    if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
8077                        temp += modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
8078                    temp = temp.trim();
8079
8080                    if(temp != null && !temp.isEmpty())
8081                        mods.add(new Modifier("G H", temp, x, y, centered));
8082                }
8083
8084                if(modifiers.containsKey(Modifiers.Y_LOCATION) ||
8085                        modifiers.containsKey(Modifiers.Z_SPEED))
8086                {
8087                    y = -2;
8088                    if(!strict &&
8089                            !(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS) || modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1)))
8090                        y++;
8091                    temp = "";
8092                    if(modifiers.containsKey(Modifiers.Y_LOCATION))
8093                        temp = modifiers.get(Modifiers.Y_LOCATION) + sep;
8094                    if(modifiers.containsKey(Modifiers.Z_SPEED))
8095                        temp += modifiers.get(Modifiers.Z_SPEED);
8096                    temp = temp.trim();
8097                    if(temp != null && !temp.isEmpty())
8098                        mods.add(new Modifier("Y Z", temp, x, y, centered));
8099                }
8100
8101                //No left side labels
8102                x = -1;
8103                centered = false;
8104                if(modifiers.containsKey(Modifiers.AQ_GUARDED_UNIT) ||
8105                        modifiers.containsKey(Modifiers.AR_SPECIAL_DESIGNATOR))
8106                {
8107                    y = 2;
8108                    if(!strict)
8109                    {
8110                        y--;
8111                    }
8112                    temp = "";
8113                    if(modifiers.containsKey(Modifiers.AQ_GUARDED_UNIT))
8114                        temp = modifiers.get(Modifiers.AQ_GUARDED_UNIT) + sep;
8115                    if(modifiers.containsKey(Modifiers.AR_SPECIAL_DESIGNATOR))
8116                        temp += modifiers.get(Modifiers.AR_SPECIAL_DESIGNATOR);
8117                    temp = temp.trim();
8118                    if(temp != null && !temp.isEmpty())
8119                        mods.add(new Modifier("AQ AR", temp, x, y, centered));
8120                }
8121            }
8122            else if(ss == SymbolID.SymbolSet_SeaSubsurface)
8123            {
8124                //No top center label
8125
8126
8127                //Do right side labels
8128                x = 1;//on right
8129                centered = true;
8130                if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH))
8131                {
8132                    y = 0;//center
8133                    centered = true;//vertically centered, only matters for labels on left and right side
8134                    temp = modifiers.get(Modifiers.X_ALTITUDE_DEPTH);
8135                    if(temp != null && !temp.isEmpty())
8136                        mods.add(new Modifier("X", temp, x, y, centered));
8137                }
8138                else if(!strict)
8139                {
8140                    //if no "H', bring G and M closer to the center
8141                    centered = false;
8142                }
8143
8144                if(modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
8145                {
8146                    y = 1;//center
8147                    temp = modifiers.get(Modifiers.V_EQUIP_TYPE);
8148                    if(temp != null && !temp.isEmpty())
8149                        mods.add(new Modifier("V", temp, x, y, centered));
8150                }
8151
8152                if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1) || modifiers.containsKey(Modifiers.AS_COUNTRY))
8153                {
8154                    y = 2;
8155                    if(!strict && !modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
8156                        y--;
8157                    temp = "";
8158                    if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
8159                        temp = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1) + sep;
8160                    if(modifiers.containsKey(Modifiers.AS_COUNTRY))
8161                        temp += modifiers.get(Modifiers.AS_COUNTRY);
8162                    temp = temp.trim();
8163
8164                    if(temp != null && !temp.isEmpty())
8165                        mods.add(new Modifier("T AS", temp, x, y, centered));
8166                }
8167
8168                if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS)  ||
8169                        modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
8170                {
8171                    y = -1;//below center
8172
8173                    temp = "";
8174                    if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
8175                        temp = modifiers.get(Modifiers.G_STAFF_COMMENTS) + sep;
8176                    if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
8177                        temp += modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
8178                    temp = temp.trim();
8179
8180                    if(temp != null && !temp.isEmpty())
8181                        mods.add(new Modifier("G H", temp, x, y, centered));
8182                }
8183
8184                if(modifiers.containsKey(Modifiers.Y_LOCATION) ||
8185                        modifiers.containsKey(Modifiers.Z_SPEED))
8186                {
8187                    y = -2;
8188                    if(!strict)
8189                    {
8190                        if(!(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS)  ||
8191                                modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1)))
8192                            y++;
8193                    }
8194                    temp = "";
8195                    if(modifiers.containsKey(Modifiers.Y_LOCATION))
8196                        temp = modifiers.get(Modifiers.Y_LOCATION) + sep;
8197                    if(modifiers.containsKey(Modifiers.Z_SPEED))
8198                        temp += modifiers.get(Modifiers.Z_SPEED);
8199                    temp = temp.trim();
8200                    if(temp != null && !temp.isEmpty())
8201                        mods.add(new Modifier("Y Z", temp, x, y, centered));
8202                }
8203
8204                //No left side labels
8205                x = -1;
8206                centered = false;
8207
8208                if(modifiers.containsKey(Modifiers.AR_SPECIAL_DESIGNATOR))
8209                {
8210                    y = 2;
8211                    if(!strict && !modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH))
8212                    {
8213                        y--;
8214                    }
8215                    temp = modifiers.get(Modifiers.AR_SPECIAL_DESIGNATOR);
8216                    temp = temp.trim();
8217                    if(temp != null && !temp.isEmpty())
8218                        mods.add(new Modifier("AR", temp, x, y, centered));
8219                }
8220            }
8221            else if(ss == SymbolID.SymbolSet_DismountedIndividuals)
8222            {
8223                //Do bottom center label
8224                x = 0;//centered
8225                y = -9;//on bottom of symbol
8226                if(modifiers.containsKey(Modifiers.C_QUANTITY))
8227                {
8228                    temp = modifiers.get(Modifiers.C_QUANTITY);
8229                    if(temp != null && !temp.isEmpty())
8230                        mods.add(new Modifier("C", temp, x, y, centered));
8231                }
8232
8233                //Do right side labels
8234                x = 1;//on right
8235                if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
8236                {
8237                    y = 0;//center
8238                    centered = true;//vertically centered, only matters for labels on left and right side
8239                    temp = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
8240
8241                    if(temp != null && !temp.isEmpty())
8242                        mods.add(new Modifier("H", temp, x, y, centered));
8243                }
8244                else if(!strict)
8245                {
8246                    centered = false;
8247                }
8248
8249                if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
8250                {
8251                    y = 1;//above center
8252                    temp = modifiers.get(Modifiers.G_STAFF_COMMENTS);
8253
8254                    if(temp != null && !temp.isEmpty())
8255                        mods.add(new Modifier("G", temp, x, y, centered));
8256                }
8257
8258                if(modifiers.containsKey(Modifiers.AS_COUNTRY))
8259                {
8260                    y = 2;
8261                    if(!strict && !(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS)))
8262                        y--;
8263                    temp = modifiers.get(Modifiers.AS_COUNTRY);
8264
8265                    if(temp != null && !temp.isEmpty())
8266                        mods.add(new Modifier("AS", temp, x, y, centered));
8267                }
8268
8269                if(modifiers.containsKey(Modifiers.M_HIGHER_FORMATION))
8270                {
8271                    y = -1;//below center
8272                    temp = modifiers.get(Modifiers.M_HIGHER_FORMATION);
8273                    if(temp != null && !temp.isEmpty())
8274                        mods.add(new Modifier("M", temp, x, y, centered));
8275                }
8276
8277                if(modifiers.containsKey(Modifiers.J_EVALUATION_RATING) ||
8278                        modifiers.containsKey(Modifiers.K_COMBAT_EFFECTIVENESS) ||
8279                        modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
8280                {
8281                    y = -2;
8282                    if(!strict && !modifiers.containsKey(Modifiers.M_HIGHER_FORMATION))
8283                        y++;
8284                    temp = "";
8285                    if(modifiers.containsKey(Modifiers.J_EVALUATION_RATING))
8286                        temp = modifiers.get(Modifiers.J_EVALUATION_RATING) + sep;
8287                    if(modifiers.containsKey(Modifiers.K_COMBAT_EFFECTIVENESS))
8288                        temp += modifiers.get(Modifiers.K_COMBAT_EFFECTIVENESS) + sep;
8289                    if(modifiers.containsKey(Modifiers.P_IFF_SIF_AIS))
8290                        temp += modifiers.get(Modifiers.P_IFF_SIF_AIS);
8291                    temp = temp.trim();
8292                    if(temp != null && !temp.isEmpty())
8293                        mods.add(new Modifier("J K P", temp, x, y, centered));
8294                }
8295
8296                //Do left side labels
8297                x = -1;//on left
8298
8299                if(modifiers.containsKey(Modifiers.V_EQUIP_TYPE) ||
8300                        modifiers.containsKey(Modifiers.AF_COMMON_IDENTIFIER))
8301                {
8302                    y = 0;//center
8303                    centered = true;//vertically centered, only matters for labels on left and right side
8304
8305                    temp = "";
8306                    if(modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
8307                        temp = modifiers.get(Modifiers.V_EQUIP_TYPE) + sep;
8308                    if(modifiers.containsKey(Modifiers.AF_COMMON_IDENTIFIER))
8309                        temp += modifiers.get(Modifiers.AF_COMMON_IDENTIFIER);
8310                    temp = temp.trim();
8311                    if(temp != null && !temp.isEmpty())
8312                        mods.add(new Modifier("V AF", temp, x, y, centered));
8313                }
8314                else if(!strict)
8315                {
8316                    centered = false;
8317                }
8318
8319                if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH) || modifiers.containsKey(Modifiers.Y_LOCATION))
8320                {
8321                    y = 1;
8322                    temp = "";
8323                    if(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH))
8324                        temp = modifiers.get(Modifiers.X_ALTITUDE_DEPTH) + sep;
8325                    if(modifiers.containsKey(Modifiers.Y_LOCATION))
8326                        temp += modifiers.get(Modifiers.Y_LOCATION);
8327
8328                    temp = temp.trim();
8329                    mods.add(new Modifier("X Y", temp, x, y, centered));
8330                }
8331
8332                if(modifiers.containsKey(Modifiers.W_DTG_1))
8333                {
8334                    y = 2;//above center
8335                    if(!strict && !(modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH) || modifiers.containsKey(Modifiers.Y_LOCATION)))
8336                        y--;
8337
8338                    temp = modifiers.get(Modifiers.W_DTG_1);
8339
8340                    if(temp != null && !temp.isEmpty())
8341                        mods.add(new Modifier("W", temp, x, y, centered));
8342                }
8343
8344                if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
8345                {
8346                    y = -1;//below center
8347                    temp = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
8348
8349                    if(temp != null && !temp.isEmpty())
8350                        mods.add(new Modifier("T", temp, x, y, centered));
8351                }
8352
8353                if(modifiers.containsKey(Modifiers.Z_SPEED))
8354                {
8355                    y = -2;
8356                    if(!strict && !(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1)))
8357                        y++;
8358                    temp = modifiers.get(Modifiers.Z_SPEED);
8359                    if(temp != null && !temp.isEmpty())
8360                        mods.add(new Modifier("Z", temp, x, y, centered));
8361                }
8362            }
8363            else if(ss == SymbolID.SymbolSet_Activities)
8364            {
8365                //No top center label
8366
8367                //Do right side labels
8368                x = 1;//on right
8369                centered = false;
8370
8371                if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
8372                {
8373                    y = 1;
8374
8375                    temp = modifiers.get(Modifiers.G_STAFF_COMMENTS);
8376                    if(temp != null && !temp.isEmpty())
8377                        mods.add(new Modifier("G", temp, x, y, centered));
8378                }
8379
8380                if(modifiers.containsKey(Modifiers.AS_COUNTRY))
8381                {
8382                    y = 2;
8383                    if(!strict && !modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
8384                        y--;
8385                    temp = modifiers.get(Modifiers.AS_COUNTRY);
8386
8387                    if(temp != null && !temp.isEmpty())
8388                        mods.add(new Modifier("AS", temp, x, y, centered));
8389                }
8390
8391                if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
8392                {
8393                    y = -1;//below center
8394                    temp = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
8395                    if(temp != null && !temp.isEmpty())
8396                        mods.add(new Modifier("H", temp, x, y, centered));
8397                }
8398
8399                if(modifiers.containsKey(Modifiers.J_EVALUATION_RATING))
8400                {
8401                    y = -2;
8402                    if(!strict && !modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
8403                        y++;
8404                    temp = temp = modifiers.get(Modifiers.J_EVALUATION_RATING);
8405
8406                    if(temp != null && !temp.isEmpty())
8407                        mods.add(new Modifier("J", temp, x, y, centered));
8408                }
8409
8410                //Do left side labels
8411                x = -1;//on left
8412                centered = false;
8413
8414                if(modifiers.containsKey(Modifiers.Y_LOCATION))
8415                {
8416                    y = 1;
8417                    temp = modifiers.get(Modifiers.Y_LOCATION);
8418
8419                    if(temp != null && !temp.isEmpty())
8420                        mods.add(new Modifier("Y", temp, x, y, centered));
8421                }
8422
8423                if(modifiers.containsKey(Modifiers.W_DTG_1))
8424                {
8425                    y = 2;//above center
8426                    if(!strict && !modifiers.containsKey(Modifiers.Y_LOCATION))
8427                        y--;
8428                    temp = modifiers.get(Modifiers.W_DTG_1);
8429                    if(temp != null && !temp.isEmpty())
8430                        mods.add(new Modifier("W", temp, x, y, centered));
8431                }
8432
8433            }
8434            else if(ss == SymbolID.SymbolSet_CyberSpace)
8435            {
8436                //Do top center label
8437                x = 0;//centered
8438                y = 9;//on top of symbol
8439                if(modifiers.containsKey(Modifiers.B_ECHELON))
8440                {
8441                    temp = modifiers.get(Modifiers.B_ECHELON);
8442                    if(temp != null && !temp.isEmpty())
8443                        mods.add(new Modifier("B", temp, x, y, centered));
8444                }
8445
8446                //Do right side labels
8447                x = 1;//on right
8448                if(modifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1))
8449                {
8450                    y = 0;//center
8451                    centered = true;//vertically centered, only matters for labels on left and right side
8452                    temp = modifiers.get(Modifiers.H_ADDITIONAL_INFO_1);
8453
8454                    if(temp != null && !temp.isEmpty())
8455                        mods.add(new Modifier("H", temp, x, y, centered));
8456                }
8457                else if(!strict)
8458                {
8459                    centered = false;
8460                }
8461
8462                if(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS))
8463                {
8464                    y = 1;//above center
8465                    temp = modifiers.get(Modifiers.G_STAFF_COMMENTS);
8466
8467                    if(temp != null && !temp.isEmpty())
8468                        mods.add(new Modifier("G", temp, x, y, centered));
8469                }
8470
8471                if(modifiers.containsKey(Modifiers.F_REINFORCED_REDUCED) || modifiers.containsKey(Modifiers.AS_COUNTRY))
8472                {
8473                    y = 2;
8474                    if(!strict && !(modifiers.containsKey(Modifiers.G_STAFF_COMMENTS)))
8475                        y--;
8476                    temp = "";
8477                    if(modifiers.containsKey(Modifiers.F_REINFORCED_REDUCED))
8478                        temp = modifiers.get(Modifiers.F_REINFORCED_REDUCED) + sep;
8479                    if(modifiers.containsKey(Modifiers.AS_COUNTRY))
8480                        temp += modifiers.get(Modifiers.AS_COUNTRY);
8481                    temp = temp.trim();
8482                    if(temp != null && !temp.isEmpty())
8483                        mods.add(new Modifier("F AS", temp, x, y, centered));
8484                }
8485
8486                if(modifiers.containsKey(Modifiers.M_HIGHER_FORMATION))
8487                {
8488                    y = -1;//below center
8489                    temp = modifiers.get(Modifiers.M_HIGHER_FORMATION);
8490                    if(temp != null && !temp.isEmpty())
8491                        mods.add(new Modifier("M", temp, x, y, centered));
8492                }
8493
8494                if(modifiers.containsKey(Modifiers.K_COMBAT_EFFECTIVENESS) || modifiers.containsKey(Modifiers.L_SIGNATURE_EQUIP))
8495                {
8496                    y = -2;
8497                    if(!strict && !modifiers.containsKey(Modifiers.M_HIGHER_FORMATION))
8498                        y++;
8499                    temp = "";
8500                    if(modifiers.containsKey(Modifiers.K_COMBAT_EFFECTIVENESS))
8501                        temp = modifiers.get(Modifiers.K_COMBAT_EFFECTIVENESS) + sep;
8502                    if(modifiers.containsKey(Modifiers.L_SIGNATURE_EQUIP))
8503                        temp += modifiers.get(Modifiers.L_SIGNATURE_EQUIP);
8504                    temp = temp.trim();
8505                    if(temp != null && !temp.isEmpty())
8506                        mods.add(new Modifier("K L", temp, x, y, centered));
8507                }
8508
8509                //Do left side labels
8510                x=-1;
8511                if(modifiers.containsKey(Modifiers.V_EQUIP_TYPE))
8512                {
8513                    y = 0;//center
8514                    centered = true;//vertically centered, only matters for labels on left and right side
8515
8516                    temp = modifiers.get(Modifiers.V_EQUIP_TYPE);
8517
8518                    if(temp != null && !temp.isEmpty())
8519                        mods.add(new Modifier("V", temp, x, y, centered));
8520                }
8521                else if(!strict)
8522                {
8523                    centered = false;
8524                }
8525
8526                if(modifiers.containsKey(Modifiers.Y_LOCATION))
8527                {
8528                    y = 1;
8529                    temp = modifiers.get(Modifiers.Y_LOCATION);
8530
8531                    if(temp != null && !temp.isEmpty())
8532                        mods.add(new Modifier("Y", temp, x, y, centered));
8533                }
8534
8535                if(modifiers.containsKey(Modifiers.W_DTG_1))
8536                {
8537                    y = 2;//above center
8538                    if(!strict && !(modifiers.containsKey(Modifiers.Y_LOCATION)))
8539                        y--;
8540
8541                    temp = modifiers.get(Modifiers.W_DTG_1);
8542
8543                    if(temp != null && !temp.isEmpty())
8544                        mods.add(new Modifier("W", temp, x, y, centered));
8545                }
8546
8547                if(modifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1))
8548                {
8549                    y = -1;//below center
8550                    temp = modifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1);
8551
8552                    if(temp != null && !temp.isEmpty())
8553                        mods.add(new Modifier("T", temp, x, y, centered));
8554                }
8555            }
8556            /*else if(ver == SymbolID.SymbolSet_MineWarfare)
8557            {
8558                //no modifiers
8559            }//*/
8560            //else//SymbolSet Unknown
8561            //processUnknownTextModifiers
8562        }
8563
8564        return mods;
8565    }
8566
8567
8568    /**
8569     * @param bounds     bounds of the core icon
8570     * @param labelWidth height of the label to be placed
8571     * @param location   -1 left, 0 center, 1 right
8572     * @returns
8573     */
8574    private static double getLabelXPosition(Rect bounds, int labelWidth, int location, float modifierFontHeight)
8575    {
8576        int buffer = (int)modifierFontHeight/2;
8577
8578        double x = 0;
8579        if(location == 1)//on right
8580        {
8581            x = bounds.left + bounds.width() + buffer;
8582        }
8583        else if(location == -1)//left
8584        {
8585            x = bounds.left - labelWidth - buffer;
8586        }
8587        else if(location == 0)
8588        {
8589            x = Math.round((bounds.left + (bounds.width() * 0.5f)) - (labelWidth * 0.5f));
8590        }
8591        return x;
8592    }
8593
8594    /**
8595     *
8596     * @param bounds bounds of the core icon
8597     * @param labelHeight height of the label to be placed
8598     * @param descent descent of the label to be placed
8599     * @param bufferText spacing buffer if desired
8600     * @param centered if true, there will be a center label location identified by 0
8601     * @param location positive 1, 2, 3 to be above symbol mid-point or negative values to be below
8602     * @returns y position
8603     */
8604    private static double getLabelYPosition(Rect bounds, int labelHeight, int descent, int bufferText, boolean centered, int location) {
8605        double y = 0;
8606        if (bounds != null && !bounds.isEmpty())
8607        {
8608            if(centered)
8609            {
8610                switch (location)
8611                {
8612                    case 3://3 above center
8613                        y = (bounds.height());
8614                        y = ((y * 0.5) + (labelHeight * 0.5));
8615                        y = y - ((labelHeight + bufferText) * 3);
8616                        y = bounds.top + y;
8617                        break;
8618                    case 2://2 above center
8619                        y = (bounds.height());
8620                        y = ((y * 0.5) + (labelHeight * 0.5));
8621                        y = y - ((labelHeight + bufferText) * 2);
8622                        y = bounds.top + y;
8623                        break;
8624                    case 1://1 above center
8625                        y = (bounds.height());
8626                        y = ((y * 0.5) + (labelHeight * 0.5));
8627                        y = y - ((labelHeight + bufferText));
8628                        y = bounds.top + y;
8629                        break;
8630                    case 0: //centered
8631                        y = (bounds.height());
8632                        y = ((y * 0.5) + ((labelHeight - descent) * 0.5));
8633                        y = bounds.top + y;
8634                        break;
8635                    case -1://1 below center
8636                        y = (bounds.height());
8637                        y = ((y * 0.5) + (labelHeight * 0.5));
8638                        y = y + ((labelHeight + bufferText - descent));
8639                        y = bounds.top + y;
8640                        break;
8641                    case -2://2 below center
8642                        y = (bounds.height());
8643                        y = ((y * 0.5) + (labelHeight * 0.5));
8644                        y = y + ((labelHeight + bufferText) * 2) - (descent);
8645                        y = bounds.top + y;
8646                        break;
8647                    case -3://3 below center
8648                        y = (bounds.height());
8649                        y = ((y * 0.5) + (labelHeight * 0.5));
8650                        y = y + ((labelHeight + bufferText) * 3) - (descent);
8651                        y = bounds.top + y;
8652                        break;
8653                }
8654            }
8655            else//split between top and bottom
8656            {
8657                switch (location)
8658                {
8659                    case 3:
8660                        y = (bounds.top + ((bounds.height() / 2) - descent - labelHeight*2 - bufferText));
8661                        break;
8662                    case 2:
8663                        y = (bounds.top + ((bounds.height() / 2) - descent - labelHeight - bufferText));
8664                        break;
8665                    case 1:
8666                        y = (bounds.top + ((bounds.height() / 2) - descent));
8667                        break;
8668                    case -1:
8669                        y = (bounds.top + (bounds.height() / 2) + (labelHeight - descent + bufferText));
8670                        break;
8671                    case -2:
8672                        y = (bounds.top + (bounds.height() / 2) + ((labelHeight*2 - descent + bufferText)));
8673                        break;
8674                    case -3:
8675                        y = (bounds.top + (bounds.height() / 2) + ((labelHeight*3 - descent + bufferText)));
8676                        break;
8677                }
8678            }
8679            if(location == 9)//on top of symbol
8680            {
8681                y = Math.round(bounds.top - bufferText - descent);
8682            }
8683            if(location == -9)//on bottom of symbol
8684            {
8685                y = (int)Math.round(bounds.top + bounds.height() + bufferText + labelHeight - descent);
8686            }
8687        }
8688        return y;
8689    }
8690
8691    /**
8692     * Currently, modifiers are based on Symbol Set.
8693     * The exception is SIGINT which required a frame shape value in 2525E+
8694     * The SSMC couldn't come to an agreement on if frame shape should dictate modifiers.
8695     * Currently, I'm keeping it tied to Symbol Set.
8696     * @param symbolID
8697     * @return
8698     */
8699    private static boolean isCOnTop(String symbolID)
8700    {
8701        boolean onTop = false;
8702
8703        int version = SymbolID.getVersion(symbolID);
8704        int ss = SymbolID.getSymbolSet(symbolID);
8705        char frame = SymbolID.getFrameShape(symbolID);
8706
8707        if(SymbolUtilities.hasModifier(symbolID,Modifiers.C_QUANTITY)) {
8708
8709            if(version >= SymbolID.Version_2525E)
8710            {
8711
8712                if (ss == SymbolID.SymbolSet_Air ||
8713                        ss == SymbolID.SymbolSet_AirMissile ||
8714                        ss == SymbolID.SymbolSet_Space ||
8715                        ss == SymbolID.SymbolSet_SpaceMissile ||
8716                        ss == SymbolID.SymbolSet_LandEquipment)
8717                {
8718                    onTop = true;
8719                }
8720                else if(ss == SymbolID.SymbolSet_SignalsIntelligence &&
8721                        (frame == SymbolID.FrameShape_Air ||
8722                        frame == SymbolID.FrameShape_Space ||
8723                        frame == SymbolID.FrameShape_LandEquipment || frame == SymbolID.FrameShape_LandUnit || frame == '0'))
8724                {
8725                    onTop = true;
8726                }
8727
8728            }// else if <= SymbolID.Version_2525Dch1
8729            else if (ss == SymbolID.SymbolSet_LandEquipment ||
8730                    ss == SymbolID.SymbolSet_SignalsIntelligence_Land)
8731            {
8732                onTop = true;
8733            }
8734        }
8735        return onTop;
8736    }
8737    public static boolean hasDisplayModifiers(String symbolID, Map<String,String> modifiers)
8738    {
8739        boolean hasModifiers = false;
8740        int ss = SymbolID.getSymbolSet(symbolID);
8741        int status = SymbolID.getStatus(symbolID);
8742        int context = SymbolID.getContext(symbolID);
8743
8744        if(ss == SymbolID.SymbolSet_ControlMeasure)//check control measure
8745        {
8746            if (SymbolUtilities.isCBRNEvent(symbolID) == true && modifiers.containsKey(Modifiers.Q_DIRECTION_OF_MOVEMENT))
8747            {
8748                hasModifiers = true;
8749            }
8750            else if(SymbolUtilities.hasFDI(symbolID))
8751                hasModifiers = true;
8752        }
8753        else if(ss != SymbolID.SymbolSet_Atmospheric &&
8754                ss != SymbolID.SymbolSet_Oceanographic &&
8755                ss != SymbolID.SymbolSet_MeteorologicalSpace)
8756        {//checking units
8757
8758            if(context > 0) //Exercise or Simulation
8759                hasModifiers = true;
8760
8761            //echelon or mobility,
8762            if (SymbolID.getAmplifierDescriptor(symbolID) > 0 || modifiers.containsKey(Modifiers.Q_DIRECTION_OF_MOVEMENT))
8763                hasModifiers = true;
8764
8765            if(modifiers.containsKey(Modifiers.AJ_SPEED_LEADER))
8766                hasModifiers = true;
8767
8768            if(modifiers.containsKey(Modifiers.AO_ENGAGEMENT_BAR))
8769                hasModifiers = true;
8770
8771            //HQ/Taskforce
8772            if(SymbolID.getHQTFD(symbolID) > 0)
8773                hasModifiers = true;
8774
8775            if(status > 1)//Fully capable, damaged, destroyed
8776                hasModifiers = true;
8777        }//no display modifiers for single point weather
8778
8779
8780
8781        return hasModifiers;
8782    }
8783
8784    public static boolean hasTextModifiers(String symbolID, Map<String,String> modifiers)
8785    {
8786
8787        int ss = SymbolID.getSymbolSet(symbolID);
8788        int ec = SymbolID.getEntityCode(symbolID);
8789        if(ss == SymbolID.SymbolSet_Atmospheric)
8790        {
8791            switch(ec)
8792            {
8793                case 110102: //tropopause low
8794                case 110202: //tropopause high
8795                case 162200: //tropopause level ?
8796                case 162300: //freezing level ?
8797                    return true;
8798                default:
8799                        return false;
8800            }
8801        }
8802        else if(ss == SymbolID.SymbolSet_Oceanographic || ss == SymbolID.SymbolSet_MeteorologicalSpace)
8803        {
8804            return false;
8805        }
8806        else if (ss == SymbolID.SymbolSet_ControlMeasure)
8807        {
8808            MSInfo msi = MSLookup.getInstance().getMSLInfo(symbolID);
8809
8810            if( msi.getModifiers().size() > 0 && modifiers != null && modifiers.size() > 0)
8811                return true;
8812            else
8813                return false;
8814        }
8815        else
8816        {
8817
8818            if (SymbolUtilities.getStandardIdentityModifier(symbolID) != null)
8819            {
8820                return true;
8821            }
8822
8823            int cc = SymbolID.getCountryCode(symbolID);
8824            if (cc > 0 && !GENCLookup.getInstance().get3CharCode(cc).isEmpty())
8825            {
8826                return true;
8827            }//*/
8828
8829            else if (modifiers.size() > 0)
8830            {
8831                return true;
8832            }
8833        }
8834        return false;
8835    }
8836
8837    /**
8838     * Rerturns either the default font from RendererSettings or font based on properties
8839     * set in MilStdAttributes.
8840     * @param attributes
8841     * @return
8842     */
8843    private static Paint getFont(Map<String,String> attributes)
8844    {
8845        Paint p = null;
8846        Typeface tf = null;
8847
8848        p = RendererSettings.getInstance().getModiferFont();
8849
8850        String[] props = RendererSettings.getInstance().getModiferFontProps();
8851
8852        String ff = props[0];
8853        int fstyle = Integer.parseInt(props[1]);// modifierFont.getTypeface().getStyle();
8854        float fsize = Float.parseFloat(props[2]);// modifierFont.getTextSize();
8855        String temp = null;
8856
8857
8858        if(attributes.containsKey(MilStdAttributes.FontFamily) ||
8859                attributes.containsKey(MilStdAttributes.FontStyle) ||
8860                attributes.containsKey(MilStdAttributes.FontSize))
8861        {
8862            if(attributes.containsKey(MilStdAttributes.FontStyle))
8863            {
8864                temp = attributes.get(MilStdAttributes.FontStyle);
8865                if (temp != null && !temp.isEmpty()) {
8866                    fstyle = Integer.parseInt(temp);
8867                }
8868            }
8869            if(attributes.containsKey(MilStdAttributes.FontSize))
8870            {
8871                temp = attributes.get(MilStdAttributes.FontSize);
8872                if (temp != null && !temp.isEmpty()) {
8873                    fsize = Float.parseFloat(temp);
8874                }
8875            }
8876            if(attributes.containsKey(MilStdAttributes.FontFamily))
8877            {
8878                temp = attributes.get(MilStdAttributes.FontFamily);
8879                if (temp != null && !temp.isEmpty()) {
8880                    ff =  temp;//Typeface.create(temp,fstyle);
8881                }
8882            }
8883            tf = Typeface.create(ff,fstyle);
8884            if(tf == null)
8885                tf = Typeface.create(props[0],fstyle);
8886            if(tf == null)
8887                return null;
8888
8889            p = new Paint();
8890            p.setTextSize(fsize);
8891            p.setAntiAlias(true);
8892            p.setTypeface(tf);
8893            p.setStrokeCap(Cap.BUTT);
8894            p.setStrokeJoin(Join.MITER);
8895            p.setStrokeMiter(3f);
8896
8897            return p;
8898        }
8899        else
8900            return _modifierFont;
8901
8902    }
8903
8904    private static float[] getFontHeightandDescent(Paint font)
8905    {
8906        float[] hd = {0f,0f};
8907
8908        if(font != null) {
8909            Paint.FontMetrics fm = font.getFontMetrics();
8910            //_modifierFontHeight = fm.top + fm.bottom;
8911            hd[0] = fm.bottom - fm.top;
8912            hd[1] = fm.descent;
8913        }
8914        return hd;
8915    }
8916
8917}