001package armyc2.c2sd.renderer;
002
003import android.graphics.Bitmap;
004import android.graphics.Bitmap.Config;
005import android.graphics.Canvas;
006import android.graphics.DashPathEffect;
007import android.graphics.Paint;
008import android.graphics.Paint.Cap;
009import android.graphics.Paint.Join;
010import android.graphics.Paint.Style;
011import android.graphics.Path;
012import android.graphics.Path.Direction;
013import android.graphics.Point;
014import android.graphics.Rect;
015import android.graphics.RectF;
016import android.util.SparseArray;
017
018import java.util.ArrayList;
019import java.util.List;
020import java.util.Locale;
021import java.util.logging.Level;
022
023import armyc2.c2sd.renderer.utilities.Color;
024import armyc2.c2sd.renderer.utilities.ErrorLogger;
025import armyc2.c2sd.renderer.utilities.ImageInfo;
026import armyc2.c2sd.renderer.utilities.MilStdAttributes;
027import armyc2.c2sd.renderer.utilities.ModifiersTG;
028import armyc2.c2sd.renderer.utilities.ModifiersUnits;
029import armyc2.c2sd.renderer.utilities.PathUtilties;
030import armyc2.c2sd.renderer.utilities.RectUtilities;
031import armyc2.c2sd.renderer.utilities.RendererSettings;
032import armyc2.c2sd.renderer.utilities.RendererUtilities;
033import armyc2.c2sd.renderer.utilities.SymbolDef;
034import armyc2.c2sd.renderer.utilities.SymbolDefTable;
035import armyc2.c2sd.renderer.utilities.SymbolUtilities;
036import armyc2.c2sd.renderer.utilities.TextInfo;
037import armyc2.c2sd.renderer.utilities.UnitFontLookup;
038
039public class ModifierRenderer
040{
041
042    private static Paint _modifierFont = null;
043    private static float _modifierFontHeight = 10f;
044    private static float _modifierFontDescent = 2f;
045    private static RendererSettings RS = RendererSettings.getInstance();
046    private static int tgTextModifierKeys[] = {2,3,4,5,6,9,10,11,12,13,14,15};
047
048    private static final Object _ModifierFontMutex = new Object();
049    public static void setModifierFont(Paint font, float height, float descent)
050    {
051        synchronized (_ModifierFontMutex) {
052            _modifierFont = font;
053            _modifierFontHeight = height;
054            _modifierFontDescent = descent;
055        }
056    }
057
058    public static ImageInfo processUnitDisplayModifiers(ImageInfo ii, String symbolID, SparseArray<String> modifiers, Boolean hasTextModifiers, SparseArray<String> attributes)
059    {
060
061        ImageInfo newii = null;
062        Rect symbolBounds = new Rect(ii.getSymbolBounds());
063        Rect imageBounds = new Rect(ii.getImageBounds());
064        Point centerPoint = new Point(ii.getCenterPoint());
065        Point symbolCenter = new Point(symbolBounds.centerX(), symbolBounds.centerY());
066        TextInfo tiEchelon = null;
067        TextInfo tiAM = null;
068        Rect echelonBounds = null;
069        Rect amBounds = null;
070        Color textColor = Color.BLACK;
071        Color textBackgroundColor = null;
072        Color lineColor = SymbolUtilities.getLineColorOfAffiliation(symbolID);
073        int buffer = 0;
074        int alpha = -1;
075        //ctx = null;
076        int offsetX = 0;
077        int offsetY = 0;
078        int symStd = RS.getSymbologyStandard();
079        if (attributes.indexOfKey(MilStdAttributes.SymbologyStandard) >= 0)
080        {
081            symStd = Integer.parseInt(attributes.get(MilStdAttributes.SymbologyStandard));
082        }
083        if (attributes.indexOfKey(MilStdAttributes.Alpha) >= 0)
084        {
085            alpha = Integer.parseInt(attributes.get(MilStdAttributes.Alpha));
086            textColor.setAlpha(alpha);
087        }
088        if (attributes.indexOfKey(MilStdAttributes.TextColor) >= 0)
089        {
090            textColor = SymbolUtilities.getColorFromHexString(attributes.get(MilStdAttributes.TextColor));
091            if(alpha > -1)
092                textColor.setAlpha(alpha);
093        }
094        if (attributes.indexOfKey(MilStdAttributes.TextBackgroundColor) >= 0)
095        {
096            textBackgroundColor = SymbolUtilities.getColorFromHexString(attributes.get(MilStdAttributes.TextBackgroundColor));
097            if(alpha > -1)
098                textBackgroundColor.setAlpha(alpha);
099        }
100        if (attributes.indexOfKey(MilStdAttributes.LineColor) >= 0)
101        {
102            lineColor = SymbolUtilities.getColorFromHexString(attributes.get(MilStdAttributes.LineColor));
103        }
104
105
106        // <editor-fold defaultstate="collapsed" desc="Build Mobility Modifiers">
107        RectF mobilityBounds = null;
108        
109        List<Path> shapes = new ArrayList<Path>();
110        Path mobilityPath = null;
111        Path mobilityPathFill = null;
112        if (symbolID.charAt(10) == ('M') && SymbolUtilities.canUnitHaveModifier(symbolID, ModifiersUnits.R_MOBILITY_INDICATOR) ||
113                symbolID.charAt(10) == ('N')  && SymbolUtilities.canUnitHaveModifier(symbolID, ModifiersUnits.AG_AUX_EQUIP_INDICATOR) )
114        {
115
116            //Draw Mobility
117            int fifth = (int) ((symbolBounds.width() * 0.2) + 0.5f);
118            mobilityPath = new Path();
119            int x = 0;
120            int y = 0;
121            int centerX = 0;
122            int bottomY = 0;
123            int height = 0;
124            int width = 0;
125            int middleY = 0;
126            int wheelOffset = 2;
127            int wheelSize = fifth;//10;
128            int rrHeight = fifth;//10;
129            int rrArcWidth = (int) ((fifth * 1.5) + 0.5f);//16;
130
131            String mobility = symbolID.substring(10, 12);
132            x = (int) symbolBounds.left + 1;
133            y = (int) symbolBounds.top;
134            height = Math.round(symbolBounds.height());
135            width = Math.round(symbolBounds.width()) - 3;
136            bottomY = y + height + 2;
137
138            if (symbolID.charAt(10) == ('M'))
139            {
140                bottomY = y + height + 2;
141
142                //wheelSize = width / 7;
143                //rrHeight = width / 7;
144                //rrArcWidth = width / 7;
145                if (mobility.equals("MO"))
146                {
147                    //line
148                    PathUtilties.addLine(mobilityPath, x, bottomY, x + width, bottomY);
149
150                    //left circle
151                    PathUtilties.addEllipse(mobilityPath, x, bottomY + wheelOffset, wheelSize, wheelSize);
152
153                    //right circle
154                    PathUtilties.addEllipse(mobilityPath, x + width - wheelSize, bottomY + wheelOffset, wheelSize, wheelSize);
155                }
156                else if (mobility.equals("MP"))
157                {
158                    //line
159                    PathUtilties.addLine(mobilityPath, x, bottomY, x + width, bottomY);
160
161                    //left circle
162                    PathUtilties.addEllipse(mobilityPath, x, bottomY + wheelOffset, wheelSize, wheelSize);
163
164                    //right circle
165                    PathUtilties.addEllipse(mobilityPath, x + width - wheelSize, bottomY + wheelOffset, wheelSize, wheelSize);
166
167                    //center wheel
168                    PathUtilties.addEllipse(mobilityPath, x + (width / 2) - (wheelSize / 2), bottomY + wheelOffset, wheelSize, wheelSize);
169                }
170                else if (mobility.equals("MQ"))
171                {
172                    //round rectangle
173                    PathUtilties.addRoundedRect(mobilityPath, x, bottomY, width, rrHeight, rrHeight/2, rrHeight);
174
175                }
176                else if (mobility.equals("MR"))
177                {
178                    //round rectangle
179                    PathUtilties.addRoundedRect(mobilityPath, x, bottomY, width, rrHeight, wheelSize/2, rrHeight);
180
181                    //left circle
182                    PathUtilties.addEllipse(mobilityPath, x - wheelSize - wheelSize, bottomY, wheelSize, wheelSize);
183                }
184                else if (mobility.equals("MS"))
185                {
186                    //line
187                    PathUtilties.addLine(mobilityPath, x + wheelSize, bottomY + (wheelSize / 2),
188                            x + width - wheelSize, bottomY + (wheelSize / 2));
189
190                    //left circle
191                    PathUtilties.addEllipse(mobilityPath, x, bottomY, wheelSize, wheelSize);
192
193                    //right circle
194                    PathUtilties.addEllipse(mobilityPath, x + width - wheelSize, bottomY, wheelSize, wheelSize);
195                }
196                else if (mobility.equals("MT"))
197                {
198
199                    //line
200                    PathUtilties.addLine(mobilityPath, x, bottomY, x + width, bottomY);
201
202                    //left circle
203                    PathUtilties.addEllipse(mobilityPath, x + wheelSize, bottomY + wheelOffset, wheelSize, wheelSize);
204
205                    //left circle2
206                    PathUtilties.addEllipse(mobilityPath, x, bottomY + wheelOffset, wheelSize, wheelSize);
207
208                    //right circle
209                    PathUtilties.addEllipse(mobilityPath, x + width - wheelSize, bottomY + wheelOffset, wheelSize, wheelSize);
210
211                    //right circle2
212                    PathUtilties.addEllipse(mobilityPath, x + width - wheelSize - wheelSize, bottomY + wheelOffset, wheelSize, wheelSize);
213
214                }
215                else if (mobility.equals("MU"))
216                {
217                        float halfWidth = (rrArcWidth * 0.5f);
218                    mobilityPath.moveTo(x, bottomY);
219                    mobilityPath.lineTo(x + halfWidth, bottomY + halfWidth);
220                    mobilityPath.lineTo(x + width, bottomY + halfWidth);
221                }
222                else if (mobility.equals("MV"))
223                {
224                    mobilityPath.moveTo(x, bottomY);
225
226                    mobilityPath.cubicTo(x, bottomY, x - rrHeight, bottomY + rrHeight/2, x, bottomY + rrHeight);
227                    //mobilityPath.bezierCurveTo(x, bottomY, x-rrArcWidth, bottomY+3, x, bottomY+rrHeight);
228
229                    mobilityPath.lineTo(x + width, bottomY + rrHeight);
230
231                    mobilityPath.cubicTo(x + width, bottomY + rrHeight, x + width + rrHeight, bottomY + rrHeight/2, x + width, bottomY);
232                    //shapeMobility.curveTo(x + width, bottomY + rrHeight, x+ width + rrArcWidth, bottomY+3, x + width, bottomY);
233                }
234                else if (mobility.equals("MW"))
235                {
236                    centerX = Math.round(RectUtilities.getCenterX(symbolBounds));
237                    int angleWidth = rrHeight / 2;
238                    mobilityPath.moveTo(centerX, bottomY + rrHeight + 2);
239                    mobilityPath.lineTo(centerX - angleWidth, bottomY);
240                    mobilityPath.lineTo(centerX - angleWidth*2, bottomY + rrHeight + 2);
241
242                    mobilityPath.moveTo(centerX, bottomY + rrHeight + 2);
243                    mobilityPath.lineTo(centerX + angleWidth, bottomY);
244                    mobilityPath.lineTo(centerX + angleWidth*2, bottomY + rrHeight + 2);
245                }
246                else if (mobility.equals("MX"))
247                {
248                    centerX = Math.round(RectUtilities.getCenterX(symbolBounds));
249                    PathUtilties.addLine(mobilityPath, x + width, bottomY, x, bottomY);
250                    //var line = new SO.Line(x + width, bottomY,x, bottomY);
251
252                    float quarterX = (centerX - x) / 2;
253                    //var quarterY = (((bottomY + rrHeight) - bottomY)/2);
254
255                    mobilityPath.moveTo(x, bottomY);
256                    mobilityPath.cubicTo(x + quarterX, bottomY + rrHeight, centerX + quarterX, bottomY + rrHeight, x + width, bottomY);
257                    //shapes.push(new SO.BCurve(x, bottomY,x+quarterX, bottomY+rrHeight, centerX + quarterX, bottomY + rrHeight, x + width, bottomY));
258                }
259
260                else if (mobility.equals("MY"))
261                {
262                    float incrementX = width / 7;
263                    middleY = (bottomY + (rrHeight / 2));
264
265                    x = Math.round(x + (incrementX / 2));
266                    float r = Math.round(incrementX / 2);
267
268                    //mobilityPath.arcTo(oval, sAngle, sAngle, moveTo);
269                    PathUtilties.arc(mobilityPath, x, middleY, r, 180, 180);
270                    PathUtilties.arc(mobilityPath, x + incrementX, middleY, r, 180, -180, false);
271                    PathUtilties.arc(mobilityPath, x + incrementX * 2, middleY, r, 180, 180, false);
272                    PathUtilties.arc(mobilityPath, x + incrementX * 3, middleY, r, 180, -180, false);
273                    PathUtilties.arc(mobilityPath, x + incrementX * 4, middleY, r, 180, 180, false);
274                    PathUtilties.arc(mobilityPath, x + incrementX * 5, middleY, r, 180, -180, false);
275                    PathUtilties.arc(mobilityPath, x + incrementX * 6, middleY, r, 180, 180, false);
276
277                }
278
279            }
280            //Draw Towed Array Sonar
281            else if (symbolID.charAt(10) == ('N'))
282            {
283
284                int boxHeight = (int) ((rrHeight * 0.8f) + 0.5f);
285                bottomY = y + height + (boxHeight / 7);
286                mobilityPathFill = new Path();
287                offsetY = boxHeight / 7;//1;
288                centerX = Math.round(symbolBounds.left + (symbolBounds.right - symbolBounds.left) / 2);
289                int squareOffset = Math.round(boxHeight * 0.5f);
290                middleY = ((boxHeight / 2) + bottomY) + offsetY;//+1 for offset from symbol
291                if (symbolID.substring(10, 12).equals("NS"))
292                {
293                    //subtract 0.5 becase lines 1 pixel thick get aliased into
294                    //a line two pixels wide.
295                    //line
296                    PathUtilties.addLine(mobilityPath, centerX - 1, bottomY - 1, centerX - 1, bottomY + boxHeight + offsetY);
297                    //shapes.push(new SO.Line(centerX-1,bottomY-1,centerX-1, bottomY + rrHeight + 3));
298                    //shapeLines.append(new Line2D.Double(centerX,bottomY - 2,centerX, bottomY + rrHeight + 1), false);
299                    //line
300                    PathUtilties.addLine(mobilityPath, x, middleY, x + width, middleY);
301                    //shapes.push(new SO.Line(x,middleY,x + width, middleY));
302                    //shapeLines.append(new Line2D.Double(x,middleY,x + width, middleY), false);
303                    //square
304                    mobilityPathFill.addRect(PathUtilties.makeRectF(x - squareOffset, bottomY + offsetY, boxHeight, boxHeight), Direction.CW);
305                    //shapes.push(new SO.Rectangle(x-squareOffset, bottomY+offsetY, 5, 5));
306                    //shapeSquares.append(new Rectangle2D.Double(x-squareOffset, bottomY, 5, 5), false);
307                    //square
308                    mobilityPathFill.addRect(PathUtilties.makeRectF(Math.round(centerX - squareOffset), bottomY + offsetY, boxHeight, boxHeight), Direction.CW);
309                    //shapes.push(new SO.Rectangle(Math.round(centerX-squareOffset), bottomY+offsetY, 5, 5));
310                    //shapeSquares.append(new Rectangle2D.Double(centerX-squareOffset, bottomY, 5, 5), false);
311                    //square
312                    mobilityPathFill.addRect(PathUtilties.makeRectF(x + width - squareOffset, bottomY + offsetY, boxHeight, boxHeight), Direction.CW);
313                    //shapes.push(new SO.Rectangle(x + width - squareOffset, bottomY+offsetY, 5, 5));
314                    //shapeSquares.append(new Rectangle2D.Double(x + width - squareOffset, bottomY, 5, 5), false);
315                }
316                else if (symbolID.substring(10, 12).equals("NL"))
317                {
318                    int leftX = x + (centerX - x) / 2,
319                            rightX = centerX + (x + width - centerX) / 2;
320
321                    //line vertical left
322                    PathUtilties.addLine(mobilityPath, leftX, bottomY - 1, leftX, bottomY + offsetY + boxHeight + offsetY);
323                    //shapes.push(new SO.Line(leftX,bottomY - 1,leftX, bottomY + rrHeight + 3));
324                    //shapeLines.append(new Line2D.Double(leftX,bottomY - 2,leftX, bottomY + rrHeight + 1), false);
325                    //line vertical right
326                    PathUtilties.addLine(mobilityPath, rightX, bottomY - 1, rightX, bottomY + offsetY + boxHeight + offsetY);
327                    //shapes.push(new SO.Line(rightX,bottomY - 1,rightX, bottomY + rrHeight + 3));
328                    //shapeLines.append(new Line2D.Double(rightX,bottomY - 2,rightX, bottomY + rrHeight + 1), false);
329                    //line horizontal
330                    PathUtilties.addLine(mobilityPath, x, middleY, x + width, middleY);
331                    //shapes.push(new SO.Line(x,middleY,x + width, middleY));
332                    //shapeLines.append(new Line2D.Double(x,middleY,x + width, middleY), false);
333                    //square left
334                    mobilityPathFill.addRect(PathUtilties.makeRectF(x - squareOffset, bottomY + offsetY, boxHeight, boxHeight), Direction.CW);
335                    //shapes.push(new SO.Rectangle(x-squareOffset, bottomY+offsetY, 5, 5));
336                    //shapeSquares.append(new Rectangle2D.Double(x-squareOffset, bottomY, 5, 5), false);
337                    //square middle
338                    mobilityPathFill.addRect(PathUtilties.makeRectF(centerX - squareOffset, bottomY + offsetY, boxHeight, boxHeight), Direction.CW);
339                    //shapes.push(new SO.Rectangle(centerX-squareOffset, bottomY+offsetY, 5, 5));
340                    //shapeSquares.append(new Rectangle2D.Double(centerX-squareOffset, bottomY, 5, 5), false);
341                    //square right
342                    mobilityPathFill.addRect(PathUtilties.makeRectF(x + width - squareOffset, bottomY + offsetY, boxHeight, boxHeight), Direction.CW);
343                    //shapes.push(new SO.Rectangle(x + width - squareOffset, bottomY+offsetY, 5, 5));
344                    //shapeSquares.append(new Rectangle2D.Double(x + width - squareOffset, bottomY, 5, 5), false);
345                    //square middle left
346                    mobilityPathFill.addRect(PathUtilties.makeRectF(leftX - squareOffset, bottomY + offsetY, boxHeight, boxHeight), Direction.CW);
347                    //shapes.push(new SO.Rectangle(leftX - squareOffset, bottomY+offsetY, 5, 5));
348                    //shapeSquares.append(new Rectangle2D.Double(leftX - squareOffset, bottomY, 5, 5), false);
349                    //square middle right
350                    mobilityPathFill.addRect(PathUtilties.makeRectF(rightX - squareOffset, bottomY + offsetY, boxHeight, boxHeight), Direction.CW);
351                    //shapes.push(new SO.Rectangle(rightX - squareOffset, bottomY+offsetY, 5, 5));
352                    //shapeSquares.append(new Rectangle2D.Double(rightX - squareOffset, bottomY, 5, 5), false);
353
354                }
355            }
356
357            //get mobility bounds
358            if (mobilityPath != null)
359            {
360
361                //build mobility bounds
362                mobilityBounds = new RectF();
363                mobilityPath.computeBounds(mobilityBounds, true);
364
365                RectF mobilityFillBounds = new RectF();
366                if (mobilityPathFill != null)
367                {
368                    mobilityPathFill.computeBounds(mobilityFillBounds, true);
369                    mobilityBounds.union(mobilityFillBounds);
370                }
371
372                //grow by one because we use a line thickness of 2.
373                mobilityBounds.set(mobilityBounds.left - 1, mobilityBounds.top - 1, mobilityBounds.right + 1, mobilityBounds.bottom + 1);
374                imageBounds.union(RectUtilities.makeRectFromRectF(mobilityBounds));
375            }
376        }
377        // </editor-fold>
378
379        // <editor-fold defaultstate="collapsed" desc="Build Echelon">
380        //Draw Echelon
381        String strEchelon = SymbolUtilities.getEchelon(symbolID);//symbolID.substring(11, 12);
382        if (strEchelon != null)
383        {
384            strEchelon = SymbolUtilities.getEchelonText(strEchelon);
385        }
386        if (strEchelon != null && SymbolUtilities.hasInstallationModifier(symbolID) == false
387                && SymbolUtilities.canUnitHaveModifier(symbolID, ModifiersUnits.B_ECHELON))
388        {
389
390            if (strEchelon != null)
391            {
392                int echelonOffset = 2,
393                        outlineOffset = RS.getTextOutlineWidth();
394
395                tiEchelon = new TextInfo(strEchelon, 0, 0, _modifierFont);
396                echelonBounds = tiEchelon.getTextBounds();
397
398                int y = Math.round(symbolBounds.left - echelonOffset);
399                int x = Math.round(symbolBounds.left + (symbolBounds.width() / 2)
400                        - (echelonBounds.width() / 2));
401                tiEchelon.setLocation(x, y);
402
403                //There will never be lowercase characters in an echelon so trim that fat.    
404                //Remove the descent from the bounding box.
405                tiEchelon.getTextOutlineBounds();//.shiftBR(0,Math.round(-(echelonBounds.height()*0.3)));                         
406
407                //make echelon bounds a little more spacious for things like nearby labels and Task Force.
408                RectUtilities.grow(echelonBounds, outlineOffset);
409                //tiEchelon.getTextOutlineBounds();
410//                RectUtilities.shift(echelonBounds, x, -outlineOffset);
411                //echelonBounds.shift(0,-outlineOffset);// - Math.round(echelonOffset/2));
412                tiEchelon.setLocation(x, y - outlineOffset);
413
414                imageBounds.union(echelonBounds);
415            }
416        }
417        // </editor-fold>
418
419        // <editor-fold defaultstate="collapsed" desc="Build Affiliation Modifier">
420        //Draw Echelon
421        String affiliationModifier = null;
422        if (RS.getDrawAffiliationModifierAsLabel() == false)
423        {
424            affiliationModifier = SymbolUtilities.getUnitAffiliationModifier(symbolID, symStd);
425        }
426        if (affiliationModifier != null)
427        {
428
429            int amOffset = 2;
430            int outlineOffset = RS.getTextOutlineWidth();
431
432            tiAM = new TextInfo(affiliationModifier, 0, 0, _modifierFont);
433            amBounds = tiAM.getTextBounds();
434
435            int x, y;
436
437            if (echelonBounds != null
438                    && ((echelonBounds.left + echelonBounds.width() > symbolBounds.left + symbolBounds.width())))
439            {
440                y = Math.round(symbolBounds.top - amOffset);
441                x = echelonBounds.left + echelonBounds.width();
442            }
443            else
444            {
445                y = Math.round(symbolBounds.top - amOffset);
446                x = Math.round(symbolBounds.left + symbolBounds.width());
447            }
448            tiAM.setLocation(x, y);
449
450            //adjust for outline.
451            RectUtilities.grow(amBounds, outlineOffset);
452            RectUtilities.shift(amBounds, 0, -outlineOffset);
453            tiAM.setLocation(x, y - outlineOffset);
454
455            imageBounds.union(amBounds);
456        }
457        // </editor-fold>
458
459        // <editor-fold defaultstate="collapsed" desc="Build Task Force">
460        Rect tfBounds = null;
461        Rect tfRectangle = null;
462        if (SymbolUtilities.isTaskForce(symbolID) && SymbolUtilities.canUnitHaveModifier(symbolID, ModifiersUnits.D_TASK_FORCE_INDICATOR))
463        {
464            if (echelonBounds != null)
465            {
466                tfRectangle = new Rect(echelonBounds.left,
467                        echelonBounds.top,// + outlineOffset,
468                        echelonBounds.right,
469                        symbolBounds.top-1);
470                tfBounds = new Rect(tfRectangle);
471            }
472            else
473            {
474                int height = Math.round(symbolBounds.height() / 4);
475                int width = Math.round(symbolBounds.width() / 3);
476
477                tfRectangle = RectUtilities.makeRect((int) symbolBounds.left + width,
478                        (int) symbolBounds.top - height,
479                        width,
480                        height);
481
482                tfBounds = RectUtilities.makeRect(tfRectangle.left + -1,
483                        tfRectangle.top - 1,
484                        tfRectangle.width() + 2,
485                        tfRectangle.height() + 2);
486
487            }
488            imageBounds.union(tfBounds);
489        }
490        // </editor-fold>
491
492        // <editor-fold defaultstate="collapsed" desc="Build Feint Dummy Indicator">
493        Rect fdiBounds = null;
494        Point fdiTop = null;
495        Point fdiLeft = null;
496        Point fdiRight = null;
497
498        if ((SymbolUtilities.isFeintDummy(symbolID)
499                || SymbolUtilities.isFeintDummyInstallation(symbolID))
500                && SymbolUtilities.canUnitHaveModifier(symbolID, ModifiersUnits.AB_FEINT_DUMMY_INDICATOR))
501        {
502            //create feint indicator /\
503            fdiLeft = new Point((int) symbolBounds.left, (int) symbolBounds.top);
504            fdiRight = new Point((int) (symbolBounds.left + symbolBounds.width()), (int) symbolBounds.top);
505
506            char affiliation = symbolID.charAt(1);
507            if (affiliation == ('F')
508                    || affiliation == ('A')
509                    || affiliation == ('D')
510                    || affiliation == ('M')
511                    || affiliation == ('J')
512                    || affiliation == ('K'))
513            {
514                fdiTop = new Point(Math.round(RectUtilities.getCenterX(symbolBounds)), Math.round(symbolBounds.top - (symbolBounds.height() * .75f)));
515            }
516            else
517            {
518                fdiTop = new Point(Math.round(RectUtilities.getCenterX(symbolBounds)), Math.round(symbolBounds.top - (symbolBounds.height() * .54f)));
519            }
520
521            fdiBounds = RectUtilities.makeRect(fdiLeft.x, fdiLeft.y, 1, 1);
522            fdiBounds.union(fdiTop.x, fdiTop.y);
523            fdiBounds.union(fdiRight.x, fdiRight.y);
524
525            if (echelonBounds != null)
526            {
527                int shiftY = Math.round(symbolBounds.top - echelonBounds.height() - 2);
528                fdiLeft.offset(0, shiftY);
529                fdiTop.offset(0, shiftY);
530                fdiRight.offset(0, shiftY);
531                fdiBounds.offset(0, shiftY);
532            }
533
534            imageBounds.union(fdiBounds);
535
536        }
537        // </editor-fold>
538
539        // <editor-fold defaultstate="collapsed" desc="Build Installation">
540        Rect instRectangle = null;
541        Rect instBounds = null;
542        if (SymbolUtilities.hasInstallationModifier(symbolID)
543                && SymbolUtilities.canUnitHaveModifier(symbolID, ModifiersUnits.AC_INSTALLATION))
544        {//the actual installation symbols have the modifier
545            //built in.  everything else, we have to draw it.
546            //
547            ////get indicator dimensions////////////////////////////////
548            int width;
549            int height;
550            char affiliation = SymbolUtilities.getAffiliation(symbolID);
551
552            if (affiliation == 'F'
553                    || affiliation == 'A'
554                    || affiliation == 'D'
555                    || affiliation == 'M'
556                    || affiliation == 'J'
557                    || affiliation == 'K')
558            {
559                //4th height, 3rd width
560                height = Math.round(symbolBounds.height() / 4);
561                width = Math.round(symbolBounds.width() / 3);
562            }
563            else if (affiliation == 'H' || affiliation == 'S')//hostile,suspect
564            {
565                //6th height, 3rd width
566                height = Math.round(symbolBounds.height() / 6);
567                width = Math.round(symbolBounds.width() / 3);
568            }
569            else if (affiliation == 'N' || affiliation == 'L')//neutral,exercise neutral
570            {
571                //6th height, 3rd width
572                height = Math.round(symbolBounds.height() / 6);
573                width = Math.round(symbolBounds.width() / 3);
574            }
575            else if (affiliation == 'P'
576                    || affiliation == 'U'
577                    || affiliation == 'G'
578                    || affiliation == 'W')
579            {
580                //6th height, 3rd width
581                height = Math.round(symbolBounds.height() / 6);
582                width = Math.round(symbolBounds.width() / 3);
583            }
584            else
585            {
586                //6th height, 3rd width
587                height = Math.round(symbolBounds.height() / 6);
588                width = Math.round(symbolBounds.width() / 3);
589            }
590
591//                    if(width * 3 < symbolBounds.width())
592//                        width++;
593            //set installation position/////////////////////////////////
594            //set position of indicator
595            if (affiliation == 'F'
596                    || affiliation == 'A'
597                    || affiliation == 'D'
598                    || affiliation == 'M'
599                    || affiliation == 'J'
600                    || affiliation == 'K'
601                    || affiliation == 'N'
602                    || affiliation == 'L')
603            {
604                instRectangle = RectUtilities.makeRect((int) (symbolBounds.left + width),
605                        (int) (symbolBounds.top - height),
606                        width,
607                        height);
608            }
609            else if (affiliation == 'H' || affiliation == 'S')//hostile,suspect
610            {
611                instRectangle = RectUtilities.makeRect((int) symbolBounds.left + width,
612                        Math.round((int) symbolBounds.top - (height * 0.15f)),
613                        width,
614                        height);
615            }
616            else if (affiliation == 'P'
617                    || affiliation == 'U'
618                    || affiliation == 'G'
619                    || affiliation == 'W')
620            {
621                instRectangle = RectUtilities.makeRect((int) symbolBounds.left + width,
622                        Math.round(symbolBounds.top - (height * 0.3f)),
623                        width,
624                        height);
625            }
626            else
627            {
628                instRectangle = RectUtilities.makeRect((int) symbolBounds.left + width,
629                        Math.round(symbolBounds.top - (height * 0.3f)),
630                        width,
631                        height);
632            }
633
634            /*instRectangle = new SO.Rectangle(symbolBounds.left + width,
635             symbolBounds.top - height,
636             width,
637             height);//*/
638            //generate installation bounds//////////////////////////////
639            instBounds = new Rect(instRectangle.left + -1,
640                    instRectangle.top - 1,
641                    instRectangle.width() + 2,
642                    instRectangle.height() + 2);
643
644            imageBounds.union(instBounds);
645
646        }
647        // </editor-fold>
648
649        // <editor-fold defaultstate="collapsed" desc="Build HQ Staff">
650        Point pt1HQ = null;
651        Point pt2HQ = null;
652        Rect hqBounds = null;
653        //Draw HQ Staff
654        if (SymbolUtilities.isHQ(symbolID)
655                && SymbolUtilities.canUnitHaveModifier(symbolID, ModifiersUnits.S_HQ_STAFF_OR_OFFSET_INDICATOR))
656        {
657
658            char affiliation = symbolID.charAt(1);
659            //get points for the HQ staff
660            if (affiliation == ('F')
661                    || affiliation == ('A')
662                    || affiliation == ('D')
663                    || affiliation == ('M')
664                    || affiliation == ('J')
665                    || affiliation == ('K')
666                    || affiliation == ('N')
667                    || affiliation == ('L'))
668            {
669                pt1HQ = new Point((int) symbolBounds.left + 1,
670                        (int) (symbolBounds.top + symbolBounds.height() - 1));
671                pt2HQ = new Point((int) pt1HQ.x, (int) (pt1HQ.y + symbolBounds.height()));
672            }
673            else
674            {
675                pt1HQ = new Point((int) symbolBounds.left + 1,
676                        (int) (symbolBounds.top + (symbolBounds.height() / 2)));
677                pt2HQ = new Point((int) pt1HQ.x, (int) (pt1HQ.y + symbolBounds.height()));
678            }
679
680            //create bounding rectangle for HQ staff.
681            hqBounds = new Rect(pt1HQ.x, pt1HQ.y, pt1HQ.x + 2, pt2HQ.y);
682            //adjust the image bounds accordingly.
683            imageBounds.union(hqBounds);
684            //imageBounds.shiftBR(0,pt2HQ.y-imageBounds.bottom);
685            //adjust symbol center
686            centerPoint.set(pt2HQ.x, pt2HQ.y);
687        }
688
689        // </editor-fold>         
690        // <editor-fold defaultstate="collapsed" desc="Build DOM Arrow">
691        Point[] domPoints = null;
692        Rect domBounds = null;
693        if (modifiers.indexOfKey(ModifiersUnits.Q_DIRECTION_OF_MOVEMENT) >= 0
694                && SymbolUtilities.canUnitHaveModifier(symbolID, ModifiersUnits.Q_DIRECTION_OF_MOVEMENT))
695        {
696                String strQ = modifiers.get(ModifiersUnits.Q_DIRECTION_OF_MOVEMENT);
697                
698                if(strQ != null && SymbolUtilities.isNumber(strQ))
699                {
700                    float q = Float.valueOf(strQ);
701        
702                    boolean isY = (modifiers.indexOfKey(ModifiersUnits.Y_LOCATION) >= 0);
703        
704                    domPoints = createDOMArrowPoints(symbolID, symbolBounds, symbolCenter, q, isY);
705        
706                    domBounds = new Rect(domPoints[0].x, domPoints[0].y, 1, 1);
707        
708                    Point temp = null;
709                    for (int i = 1; i < 6; i++)
710                    {
711                        temp = domPoints[i];
712                        if (temp != null)
713                        {
714                            domBounds.union(temp.x, temp.y);
715                        }
716                    }
717                    imageBounds.union(domBounds);
718                }
719        }
720
721        // </editor-fold>
722        // <editor-fold defaultstate="collapsed" desc="Build Operational Condition Indicator">
723        Rect ociBounds = null;
724        RectF ociBoundsF = null;
725        Rect ociShape = null;
726        Path ociSlashShape = null;
727        int ociOffset = 4;
728        if (mobilityBounds != null)
729        {
730            ociOffset = Math.round(mobilityBounds.bottom - symbolBounds.bottom) + 4;
731        }
732        if(RendererSettings.getInstance().getOperationalConditionModifierType() == RendererSettings.OperationalConditionModifierType_BAR)
733        {
734            ociShape = processOperationalConditionIndicator(symbolID, symbolBounds, ociOffset);
735            if (ociShape != null)
736            {
737                Rect temp = new Rect(ociShape);
738                RectUtilities.grow(temp, 2);
739                ociBounds = temp;
740                imageBounds.union(ociBounds);
741            }
742        }
743        else//slash
744        {
745            ociSlashShape = processOperationalConditionIndicatorSlash(symbolID, symbolBounds);
746            if (ociSlashShape != null)
747            {
748                //build mobility bounds
749                ociBoundsF = new RectF();
750                ociBounds = new Rect();
751                ociSlashShape.computeBounds(ociBoundsF, true);
752                ociBoundsF.roundOut(ociBounds);
753                imageBounds.union(ociBounds);
754                ociBounds = null;
755            }
756        }
757
758
759        // </editor-fold>
760        // 
761        // <editor-fold defaultstate="collapsed" desc="Shift Modifiers">
762        //adjust points if necessary
763        if (imageBounds.left < 0 || imageBounds.top < 0)
764        {
765            int shiftX = Math.abs(imageBounds.left);
766            int shiftY = Math.abs(imageBounds.top);
767
768            if (hqBounds != null)
769            {
770                pt1HQ.offset(shiftX, shiftY);
771                pt2HQ.offset(shiftX, shiftY);
772            }
773            if (echelonBounds != null)
774            {
775                tiEchelon.setLocation(tiEchelon.getLocation().x + shiftX, tiEchelon.getLocation().y + shiftY);
776            }
777            if (amBounds != null)
778            {
779                tiAM.setLocation(tiAM.getLocation().x + shiftX, tiAM.getLocation().y + shiftY);
780            }
781            if (tfBounds != null)
782            {
783                tfRectangle.offset(shiftX, shiftY);
784                tfBounds.offset(shiftX, shiftY);
785            }
786            if (instBounds != null)
787            {
788                instRectangle.offset(shiftX, shiftY);
789                instBounds.offset(shiftX, shiftY);
790            }
791            if (fdiBounds != null)
792            {
793                fdiBounds.offset(shiftX, shiftY);
794                fdiLeft.offset(shiftX, shiftY);
795                fdiTop.offset(shiftX, shiftY);
796                fdiRight.offset(shiftX, shiftY);
797            }
798            if (ociBounds != null)
799            {
800                ociBounds.offset(shiftX, shiftY);
801                ociShape.offset(shiftX, shiftY);
802            }
803            if(ociBoundsF != null)
804            {
805                ociBoundsF.offset(shiftX, shiftY);
806                ociSlashShape.offset(shiftX, shiftY);
807            }
808            if (domBounds != null)
809            {
810                for (int i = 0; i < 6; i++)
811                {
812                    Point temp = domPoints[i];
813                    if (temp != null)
814                    {
815                        temp.offset(shiftX, shiftY);
816                    }
817                }
818                domBounds.offset(shiftX, shiftY);
819            }
820            if (mobilityBounds != null)
821            {
822                //shift mobility points
823                mobilityPath.offset(shiftX, shiftY);
824                if (mobilityPathFill != null)
825                {
826                    mobilityPathFill.offset(shiftX, shiftY);
827                }
828
829                mobilityBounds.offset(shiftX, shiftY);
830            }
831
832            centerPoint.offset(shiftX, shiftY);
833            symbolBounds.offset(shiftX, shiftY);
834            imageBounds.offset(shiftX, shiftY);
835        }
836        // </editor-fold>
837
838        // <editor-fold defaultstate="collapsed" desc="Draw Modifiers">
839        /*if(useBuffer.equalstrue)
840         {
841         buffer = _bufferDisplayModifiers;
842         ctx = buffer.getContext('2d');
843         ctx.clearRect(0,0,250,250);
844         }
845         else
846         {
847         buffer = this.createBuffer(imageBounds.getWidth(),imageBounds.getHeight());
848         ctx = buffer.getContext('2d');
849         //}*/
850        Bitmap bmp = Bitmap.createBitmap(imageBounds.width(), imageBounds.height(), Config.ARGB_8888);
851        Canvas ctx = new Canvas(bmp);
852
853        if (echelonBounds != null || amBounds != null)
854        {
855            //   ctx.font = RendererSettings.getModifierFont();
856        }
857
858        //render////////////////////////////////////////////////////////
859        Paint paint = new Paint();
860        paint.setStyle(Style.STROKE);
861        //paint.setColor(Color.black.toInt());
862        paint.setColor(lineColor.toInt());
863        if(alpha > -1)
864            paint.setAlpha(alpha);
865        paint.setStrokeWidth(2.0f);
866
867        if (hqBounds != null)
868        {
869            ctx.drawLine(pt1HQ.x, pt1HQ.y, pt2HQ.x, pt2HQ.y, paint);
870        }
871
872        if (tfBounds != null)
873        {
874            ctx.drawRect(tfRectangle, paint);
875        }
876
877        if (instBounds != null)
878        {
879            paint.setStyle(Style.FILL);
880            ctx.drawRect(instRectangle, paint);
881        }
882
883        if (echelonBounds != null)
884        {
885            TextInfo[] aTiEchelon =
886            {
887                tiEchelon
888            };
889            renderText(ctx, aTiEchelon, textColor, textBackgroundColor);
890
891            echelonBounds = null;
892            tiEchelon = null;
893        }
894
895        if (amBounds != null)
896        {
897            TextInfo[] aTiAM =
898            {
899                tiAM
900            };
901            renderText(ctx, aTiAM, textColor, textBackgroundColor);
902            amBounds = null;
903            tiAM = null;
904        }
905
906        if (fdiBounds != null)
907        {
908
909            Paint fdiPaint = new Paint();
910            fdiPaint.setAntiAlias(true);
911            fdiPaint.setColor(lineColor.toInt());/// setARGB(255, 0, 0, 0);
912            if(alpha > -1)
913                fdiPaint.setAlpha(alpha);
914            fdiPaint.setStyle(Style.STROKE);
915
916            fdiPaint.setPathEffect(new DashPathEffect(new float[]
917            {
918                6, 4
919            }, 0));
920
921            if (symbolBounds.width() > 19)
922            {
923                fdiPaint.setPathEffect(new DashPathEffect(new float[]
924                {
925                    6, 4
926                }, 0));
927            }
928            else
929            {
930                fdiPaint.setPathEffect(new DashPathEffect(new float[]
931                {
932                    5, 3
933                }, 0));
934            }
935            fdiPaint.setStrokeCap(Cap.BUTT);
936            fdiPaint.setStrokeJoin(Join.MITER);
937            fdiPaint.setStrokeWidth(2);
938
939            Path fdiPath = new Path();
940
941            fdiPath.moveTo(fdiLeft.x, fdiLeft.y);
942            fdiPath.lineTo(fdiTop.x, fdiTop.y);
943            fdiPath.lineTo(fdiRight.x, fdiRight.y);
944            ctx.drawPath(fdiPath, fdiPaint);
945
946            fdiBounds = null;
947
948        }
949
950        if (mobilityBounds != null)
951        {
952            Paint mobilityPaint = new Paint();
953            mobilityPaint.setStyle(Style.STROKE);
954            //mobilityPaint.setColor(Color.black.toInt());
955            mobilityPaint.setColor(lineColor.toInt());
956            if(alpha > -1)
957                mobilityPaint.setAlpha(alpha);
958            
959            //ctx.lineCap = "butt";
960            //ctx.lineJoin = "miter";
961            if (symbolID.charAt(10) == ('M'))
962            {
963                mobilityPaint.setStrokeWidth(3f);
964                mobilityPaint.setAntiAlias(true);
965            }
966            else //NS or NL
967            {
968                mobilityPaint.setStrokeWidth(3f);
969                //mobilityPaint.setAntiAlias(true);
970            }
971
972            ctx.drawPath(mobilityPath, mobilityPaint);
973
974            if (mobilityPathFill != null)
975            {
976                mobilityPaint.setStyle(Style.FILL);
977                ctx.drawPath(mobilityPathFill, mobilityPaint);
978            }
979
980            mobilityBounds = null;
981
982        }
983
984        if (ociBounds != null)
985        {
986            Paint ociPaint = new Paint();
987
988            int statusColor = 0;
989            char status = symbolID.charAt(3);
990            if (status == ('C'))//Fully Capable
991            {
992                statusColor = Color.green.toInt();
993            }
994            else if (status == ('D'))//Damage
995            {
996                statusColor = Color.yellow.toInt();
997            }
998            else if (status == ('X'))
999            {
1000                statusColor = Color.red.toInt();
1001            }
1002            else if (status == ('F'))//full to capacity(hospital)
1003            {
1004                statusColor = Color.blue.toInt();
1005            }
1006
1007            ociPaint.setColor(Color.black.toInt());
1008            ociPaint.setStyle(Style.FILL);
1009
1010            if(alpha > -1)
1011                ociPaint.setAlpha(alpha);
1012            ctx.drawRect(ociBounds, ociPaint);
1013            ociPaint.setColor(statusColor);
1014            if(alpha > -1)
1015                ociPaint.setAlpha(alpha);
1016            ctx.drawRect(ociShape, ociPaint);
1017
1018            ociBounds = null;
1019            ociShape = null;
1020        }
1021
1022        //draw original icon.        
1023        //ctx.drawImage(ii.getImage(),symbolBounds.left, symbolBounds.top);
1024        ctx.drawBitmap(ii.getImage(), null, symbolBounds, null);
1025
1026        if (domBounds != null)
1027        {
1028            drawDOMArrow(ctx, domPoints, alpha, lineColor);
1029
1030            domBounds = null;
1031            domPoints = null;
1032        }
1033
1034        if(ociBoundsF != null)
1035        {
1036            Paint ociPaint = new Paint();
1037            int size = symbolBounds.width();
1038            float ociStrokeWidth = 3f;
1039
1040            ociStrokeWidth = size/20f;
1041            if(ociStrokeWidth < 1f)
1042                ociStrokeWidth = 1f;
1043            /*if(size > 50 && size < 100)
1044                ociStrokeWidth = 5f;
1045            else if(size >= 100 && size < 200)
1046                ociStrokeWidth = 7f;
1047            else if(size >= 200)
1048                ociStrokeWidth = 10f;*/
1049            //ociPaint.setColor(Color.black.toInt());
1050            ociPaint.setColor(lineColor.toInt());
1051            if(alpha > -1)
1052                ociPaint.setAlpha(alpha);
1053            ociPaint.setStrokeWidth(ociStrokeWidth);
1054            ociPaint.setStrokeCap(Cap.BUTT);
1055            ociPaint.setStyle(Style.STROKE);
1056            ociPaint.setAntiAlias(true);
1057            ctx.drawPath(ociSlashShape,ociPaint);
1058
1059            ociBoundsF = null;
1060            ociSlashShape = null;
1061        }
1062
1063        // </editor-fold>
1064        newii = new ImageInfo(bmp, centerPoint, symbolBounds);
1065
1066        // <editor-fold defaultstate="collapsed" desc="Cleanup">
1067        // </editor-fold>
1068        //return newii;    
1069        if (newii != null)
1070        {
1071            return newii;
1072        }
1073        else
1074        {
1075            return null;
1076        }
1077
1078    }
1079    
1080    private static double getYPositionForSCC(String symbolID)
1081    {
1082        double yPosition = 0.32;
1083        String temp = symbolID.substring(4, 10);
1084        char affiliation = symbolID.charAt(1);
1085
1086        if(temp.equals("WMGC--"))//GROUND (BOTTOM) MILCO
1087        {
1088            if(affiliation == 'H' || 
1089                    affiliation == 'S')//suspect
1090                yPosition = 0.29;
1091            else if(affiliation == 'N' ||
1092                    affiliation == 'L')//exercise neutral
1093                yPosition = 0.32;
1094            else if(affiliation == 'F' ||
1095                    affiliation == 'A' ||//assumed friend
1096                    affiliation == 'D' ||//exercise friend
1097                    affiliation == 'M' ||//exercise assumed friend
1098                    affiliation == 'K' ||//faker
1099                    affiliation == 'J')//joker
1100                yPosition = 0.32;
1101            else
1102                yPosition = 0.34;
1103        }
1104        else if(temp.equals("WMMC--"))//MOORED MILCO
1105        {
1106            if(affiliation == 'H' || 
1107                    affiliation == 'S')//suspect
1108                yPosition = 0.25;
1109            else if(affiliation == 'N' ||
1110                    affiliation == 'L')//exercise neutral
1111                yPosition = 0.25;
1112            else if(affiliation == 'F' ||
1113                    affiliation == 'A' ||//assumed friend
1114                    affiliation == 'D' ||//exercise friend
1115                    affiliation == 'M' ||//exercise assumed friend
1116                    affiliation == 'K' ||//faker
1117                    affiliation == 'J')//joker
1118                yPosition = 0.25;
1119            else
1120                yPosition = 0.28;
1121        }
1122        else if(temp.equals("WMFC--"))//FLOATING MILCO
1123        {
1124            if(affiliation == 'H' || 
1125                    affiliation == 'S')//suspect
1126                yPosition = 0.29;
1127            else if(affiliation == 'N' ||
1128                    affiliation == 'L')//exercise neutral
1129                yPosition = 0.32;
1130            else if(affiliation == 'F' ||
1131                    affiliation == 'A' ||//assumed friend
1132                    affiliation == 'D' ||//exercise friend
1133                    affiliation == 'M' ||//exercise assumed friend
1134                    affiliation == 'K' ||//faker
1135                    affiliation == 'J')//joker
1136                yPosition = 0.32;
1137            else
1138                yPosition = 0.34;
1139        }
1140        else if(temp.equals("WMC---"))//GENERAL MILCO
1141        {
1142            if(affiliation == 'H' || 
1143                    affiliation == 'S')//suspect
1144                yPosition = 0.33;
1145            else if(affiliation == 'N' ||
1146                    affiliation == 'L')//exercise neutral
1147                yPosition = 0.36;
1148            else if(affiliation == 'F' ||
1149                    affiliation == 'A' ||//assumed friend
1150                    affiliation == 'D' ||//exercise friend
1151                    affiliation == 'M' ||//exercise assumed friend
1152                    affiliation == 'K' ||//faker
1153                    affiliation == 'J')//joker
1154                yPosition = 0.36;
1155            else
1156                yPosition = 0.36;
1157        }
1158        
1159        return yPosition;
1160    }
1161
1162    /**
1163     *
1164     * @param {type} symbolID
1165     * @param {type} bounds symbolBounds SO.Rectangle
1166     * @param {type} center SO.Point Location where symbol is centered.
1167     * @param {type} angle in degrees
1168     * @param {Boolean} isY Boolean.
1169     * @returns {Array} of SO.Point. First 3 items are the line. Last three are
1170     * the arrowhead.
1171     */
1172    private static Point[] createDOMArrowPoints(String symbolID, Rect bounds, Point center, float angle, boolean isY)
1173    {
1174        Point[] arrowPoints = new Point[6];
1175        Point pt1 = null;
1176        Point pt2 = null;
1177        Point pt3 = null;
1178
1179        char affiliation = symbolID.charAt(1);
1180        int length = 40;
1181        if (SymbolUtilities.isNBC(symbolID))
1182        {
1183            length = Math.round(bounds.height() / 2);
1184        }
1185        else if((SymbolUtilities.isHQ(symbolID)) &&
1186                (affiliation==('F') ||
1187                        affiliation==('A') ||
1188                        affiliation==('D') ||
1189                        affiliation==('M') ||
1190                        affiliation==('J') ||
1191                        affiliation==('K') ||
1192                        affiliation==('N') ||
1193                        affiliation==('L')) == false)
1194        {
1195            length = (int)Math.round(bounds.height() * 0.7);
1196        }
1197        else
1198        {
1199            length = bounds.height();
1200        }
1201
1202        //get endpoint
1203        int dx2, dy2,
1204                x1, y1,
1205                x2, y2;
1206
1207        x1 = Math.round(center.x);
1208        y1 = Math.round(center.y);
1209
1210        pt1 = new Point(x1, y1);
1211        char scheme = symbolID.charAt(0);
1212        if (SymbolUtilities.isHQ(symbolID)==false && SymbolUtilities.isNBC(symbolID)
1213                || (scheme == 'S' && symbolID.charAt(2) == ('G')) ||
1214                scheme == 'O' || scheme == 'E')
1215        {
1216            //drawStaff = true;
1217            if(SymbolUtilities.isHQ(symbolID)==false)//has HQ staff to start from
1218            {
1219                y1 = bounds.top + bounds.height();
1220                pt1 = new Point(x1, y1);
1221
1222                if (isY == true && SymbolUtilities.isNBC(symbolID))//make room for y modifier
1223                {
1224                    int yModifierOffset = (int) _modifierFontHeight;
1225
1226                    yModifierOffset += RS.getTextOutlineWidth();
1227
1228                    pt1.offset(0, yModifierOffset);
1229                }
1230
1231                y1 = y1 + length;
1232                pt2 = new Point(x1, y1);
1233            }
1234            else
1235            {
1236                x1 = bounds.left+1;
1237                pt2 = new Point(x1, y1);
1238                if(affiliation == 'F' ||
1239                        affiliation == 'A' ||
1240                        affiliation == 'D' ||
1241                        affiliation == 'M' ||
1242                        affiliation == 'J' ||
1243                        affiliation == 'K' ||
1244                        affiliation == 'N' ||
1245                        affiliation == 'L')
1246                {
1247                    /*y1 = bounds.top + bounds.height();
1248                    pt1 = new Point(x1, y1);
1249                    y1 = y1 + length;
1250                    pt2 = new Point(x1, y1);//*/
1251
1252                    pt1.x = x1;
1253                    y1 = bounds.top + (bounds.height());
1254                    pt1.y = y1;
1255                    x2 = x1;
1256                    pt2.x = x2;
1257                    y1 = pt1.y + bounds.height();
1258                    pt2.y = y1;//*/
1259
1260                }
1261                else
1262                {
1263                    pt1.x = x1;
1264                    y1 = bounds.top + (bounds.height() / 2);
1265                    pt1.y = y1;
1266                    x2 = x1;
1267                    pt2.x = x2;
1268                    y1 = pt1.y + bounds.height();
1269                    pt2.y = y1;
1270                }
1271            }
1272        }
1273
1274            //get endpoint given start point and an angle
1275        //x2 = x1 + (length * Math.cos(radians)));
1276        //y2 = y1 + (length * Math.sin(radians)));
1277        angle = angle - 90;//in java, east is zero, we want north to be zero
1278        double radians = 0;
1279        radians = (angle * (Math.PI / 180));//convert degrees to radians
1280
1281        dx2 = x1 + (int) (length * Math.cos(radians));
1282        dy2 = y1 + (int) (length * Math.sin(radians));
1283        x2 = Math.round(dx2);
1284        y2 = Math.round(dy2);
1285
1286        //create arrowhead//////////////////////////////////////////////////////
1287        float arrowWidth = 16.0f,//8.0f,//6.5f;//7.0f;//6.5f;//10.0f//default
1288                theta = 0.423f;//higher value == shorter arrow head//*/
1289
1290        if (length < 50)
1291        {
1292            theta = 0.55f;
1293        }
1294        /*float arrowWidth = length * .09f,// 16.0f,//8.0f,//6.5f;//7.0f;//6.5f;//10.0f//default
1295         theta = length * .0025f;//0.423f;//higher value == shorter arrow head
1296         if(arrowWidth < 8)
1297         arrowWidth = 8f;//*/
1298
1299        int[] xPoints = new int[3];//3
1300        int[] yPoints = new int[3];//3
1301        int[] vecLine = new int[2];//2
1302        int[] vecLeft = new int[2];//2
1303        double fLength;
1304        double th;
1305        double ta;
1306        double baseX, baseY;
1307
1308        xPoints[0] = x2;
1309        yPoints[0] = y2;
1310
1311        //build the line vector
1312        vecLine[0] = (xPoints[0] - x1);
1313        vecLine[1] = (yPoints[0] - y1);
1314
1315        //build the arrow base vector - normal to the line
1316        vecLeft[0] = -vecLine[1];
1317        vecLeft[1] = vecLine[0];
1318
1319        //setup length parameters
1320        fLength = Math.sqrt(vecLine[0] * vecLine[0] + vecLine[1] * vecLine[1]);
1321        th = arrowWidth / (2.0 * fLength);
1322        ta = arrowWidth / (2.0 * (Math.tan(theta) / 2.0) * fLength);
1323
1324        //find base of the arrow
1325        baseX = (xPoints[0] - ta * vecLine[0]);
1326        baseY = (yPoints[0] - ta * vecLine[1]);
1327
1328        //build the points on the sides of the arrow
1329        xPoints[1] = (int) Math.round(baseX + th * vecLeft[0]);
1330        yPoints[1] = (int) Math.round(baseY + th * vecLeft[1]);
1331        xPoints[2] = (int) Math.round(baseX - th * vecLeft[0]);
1332        yPoints[2] = (int) Math.round(baseY - th * vecLeft[1]);
1333
1334        //line.lineTo((int)baseX, (int)baseY);
1335        pt3 = new Point((int) Math.round(baseX), (int) Math.round(baseY));
1336
1337        //arrowHead = new Polygon(xPoints, yPoints, 3);
1338        arrowPoints[0] = pt1;
1339        arrowPoints[1] = pt2;
1340        arrowPoints[2] = pt3;
1341        arrowPoints[3] = new Point(xPoints[0], yPoints[0]);
1342        arrowPoints[4] = new Point(xPoints[1], yPoints[1]);
1343        arrowPoints[5] = new Point(xPoints[2], yPoints[2]);
1344
1345        return arrowPoints;
1346
1347    }
1348
1349    private static void drawDOMArrow(Canvas ctx, Point[] domPoints, int alpha, Color lineColor)
1350    {
1351        Paint domPaint = new Paint();
1352        domPaint.setStrokeCap(Cap.BUTT);
1353        domPaint.setStrokeJoin(Join.MITER);
1354        domPaint.setStrokeWidth(3);
1355        domPaint.setColor(lineColor.toInt());
1356        domPaint.setStyle(Style.STROKE);
1357        if(alpha > -1)
1358            domPaint.setAlpha(alpha);
1359
1360        Path domPath = new Path();
1361        domPath.moveTo(domPoints[0].x, domPoints[0].y);
1362        if (domPoints[1] != null)
1363        {
1364            domPath.lineTo(domPoints[1].x, domPoints[1].y);
1365        }
1366        if (domPoints[2] != null)
1367        {
1368            domPath.lineTo(domPoints[2].x, domPoints[2].y);
1369        }
1370        ctx.drawPath(domPath, domPaint);
1371
1372        domPath.reset();
1373        domPaint.setStyle(Style.FILL);
1374        domPath.moveTo(domPoints[3].x, domPoints[3].y);
1375        domPath.lineTo(domPoints[4].x, domPoints[4].y);
1376        domPath.lineTo(domPoints[5].x, domPoints[5].y);
1377        ctx.drawPath(domPath, domPaint);
1378    }
1379
1380    private static Rect processOperationalConditionIndicator(String symbolID, Rect symbolBounds, int offsetY)
1381    {
1382        //create Operational Condition Indicator
1383        //set color
1384        Rect bar = null;
1385        char status;
1386        Color statusColor;
1387        int barSize = 0;
1388        int pixelSize = symbolBounds.height();
1389
1390        status = symbolID.charAt(3);
1391
1392        if (status == 'C' || status == 'D' || status == 'X' || status == 'F')
1393        {
1394            if (pixelSize > 0)
1395            {
1396                barSize = Math.round(pixelSize / 5);
1397            }
1398
1399            if (barSize < 2)
1400            {
1401                barSize = 2;
1402            }
1403
1404            offsetY += Math.round(symbolBounds.top + symbolBounds.height());
1405
1406            bar = RectUtilities.makeRect(symbolBounds.left + 2, offsetY, Math.round(symbolBounds.width()) - 4, barSize);
1407        }
1408
1409        return bar;
1410    }
1411
1412    private static Path processOperationalConditionIndicatorSlash(String symbolID, Rect symbolBounds)
1413    {
1414        //create Operational Condition Indicator
1415        Path path = null;
1416        char status;
1417        status = symbolID.charAt(3);
1418
1419        if (status == 'D' || status == 'X')
1420        {
1421            int fillCode = UnitFontLookup.getFillCode(symbolID,RendererSettings.Symbology_2525C);
1422            float widthRatio = UnitFontLookup.getUnitRatioWidth(fillCode);
1423            float heightRatio = UnitFontLookup.getUnitRatioHeight(fillCode);
1424
1425            float slashHeight = (symbolBounds.height() / heightRatio * 1.47f);
1426            float slashWidth = (symbolBounds.width() / widthRatio * 0.85f);
1427            float centerX = symbolBounds.exactCenterX();
1428            float centerY = symbolBounds.exactCenterY();
1429            path = new Path();
1430            if(status == 'D')//Damaged /
1431            {
1432                path.moveTo(centerX - (slashWidth/2),centerY+(slashHeight/2));
1433                path.lineTo(centerX + (slashWidth/2),centerY-(slashHeight/2));
1434            }
1435            else if(status == 'X')//Destroyed X
1436            {
1437                path.moveTo(centerX - (slashWidth/2),centerY+(slashHeight/2));
1438                path.lineTo(centerX + (slashWidth/2),centerY-(slashHeight/2));
1439                path.moveTo(centerX - (slashWidth/2),centerY-(slashHeight/2));
1440                path.lineTo(centerX + (slashWidth/2),centerY+(slashHeight/2));
1441            }
1442            return path;
1443
1444        }
1445
1446        return path;
1447    }
1448
1449    public static ImageInfo processUnitTextModifiers(ImageInfo ii, String symbolID, SparseArray<String> modifiers, SparseArray<String> attributes)
1450    {
1451
1452        int bufferXL = 5;
1453        int bufferXR = 5;
1454        int bufferY = 2;
1455        int bufferText = 2;
1456        int x = 0;
1457        int y = 0;//best y
1458        int cpofNameX = 0;
1459        ImageInfo newii = null;
1460        int alpha = -1;
1461        
1462        Color textColor = Color.BLACK;
1463        Color textBackgroundColor = null;
1464
1465        ArrayList<TextInfo> tiArray = new ArrayList<TextInfo>(modifiers.size());
1466
1467        int descent = (int) (_modifierFontDescent + 0.5);
1468
1469        int symStd = RS.getSymbologyStandard();
1470        if (attributes.indexOfKey(MilStdAttributes.SymbologyStandard) >= 0)
1471        {
1472            symStd = Integer.parseInt(attributes.get(MilStdAttributes.SymbologyStandard));
1473        }
1474        if (attributes.indexOfKey(MilStdAttributes.Alpha) >= 0)
1475        {
1476            alpha = Integer.parseInt(attributes.get(MilStdAttributes.Alpha));
1477        }
1478
1479        Rect labelBounds = null;
1480        int labelWidth, labelHeight;
1481
1482        Rect bounds = new Rect(ii.getSymbolBounds());
1483        Rect symbolBounds = new Rect(ii.getSymbolBounds());
1484        Point centerPoint = new Point(ii.getCenterPoint());
1485        Rect imageBounds = new Rect(ii.getImageBounds());
1486        Rect imageBoundsOld = new Rect(ii.getImageBounds());
1487
1488        String echelon = SymbolUtilities.getEchelon(symbolID);
1489        String echelonText = SymbolUtilities.getEchelonText(echelon);
1490        String amText = SymbolUtilities.getUnitAffiliationModifier(symbolID, symStd);
1491
1492        //make room for echelon & mobility.
1493        if (modifiers.indexOfKey(ModifiersUnits.Q_DIRECTION_OF_MOVEMENT) < 0 || SymbolUtilities.canUnitHaveModifier(symbolID, ModifiersUnits.Q_DIRECTION_OF_MOVEMENT)==false)
1494        {
1495            //if no DOM, we can just use the image bounds
1496            bounds = RectUtilities.makeRect(imageBounds.left, symbolBounds.top,
1497                    imageBounds.width(), symbolBounds.height());
1498        }
1499        else //dom exists so we need to change our math
1500        {
1501            if (echelonText != null || amText != null)
1502            {
1503                bounds = RectUtilities.makeRect(imageBounds.left, bounds.top,
1504                        imageBounds.width(), bounds.height());
1505            }
1506            else if (symbolID.substring(10, 12).equals("MR"))
1507            {
1508                x = -(Math.round((symbolBounds.width() - 1) / 7) * 2);
1509                if (x < bounds.left)
1510                {
1511                    bounds.set(x, 0, bounds.right, bounds.bottom);
1512                    //bounds.shiftTL(x,0);
1513                }
1514            }
1515        }
1516
1517        cpofNameX = bounds.left + bounds.width() + bufferXR;
1518
1519        //check if text is too tall:
1520        boolean byLabelHeight = false;
1521        labelHeight = (int) (_modifierFontHeight + 0.5);/* RendererUtilities.measureTextHeight(RendererSettings.getModifierFontName(),
1522         RendererSettings.getModifierFontSize(),
1523         RendererSettings.getModifierFontStyle()).fullHeight;*/
1524
1525        int maxHeight = (bounds.height());
1526        if ((labelHeight * 3) > maxHeight)
1527        {
1528            byLabelHeight = true;
1529        }
1530
1531        //Affiliation Modifier being drawn as a display modifier
1532        String affiliationModifier = null;
1533        if (RS.getDrawAffiliationModifierAsLabel() == true)
1534        {
1535            affiliationModifier = SymbolUtilities.getUnitAffiliationModifier(symbolID, symStd);
1536        }
1537        if (affiliationModifier != null)
1538        {   //Set affiliation modifier
1539            modifiers.put(ModifiersUnits.E_FRAME_SHAPE_MODIFIER, affiliationModifier);
1540            //modifiers[ModifiersUnits.E_FRAME_SHAPE_MODIFIER] = affiliationModifier;
1541        }//*/
1542
1543        //Check for Valid Country Code
1544        if (SymbolUtilities.hasValidCountryCode(symbolID))
1545        {
1546            modifiers.put(ModifiersUnits.CC_COUNTRY_CODE, symbolID.substring(12, 14));
1547            //modifiers[ModifiersUnits.CC_COUNTRY_CODE] = symbolID.substring(12,14);
1548        }
1549
1550        //            int y0 = 0;//W            E/F
1551        //            int y1 = 0;//X/Y          G
1552        //            int y2 = 0;//V/AD/AE      H/AF
1553        //            int y3 = 0;//T            M CC
1554        //            int y4 = 0;//Z            J/K/L/N/P
1555        //
1556        //            y0 = bounds.y - 0;
1557        //            y1 = bounds.y - labelHeight;
1558        //            y2 = bounds.y - (labelHeight + (int)bufferText) * 2;
1559        //            y3 = bounds.y - (labelHeight + (int)bufferText) * 3;
1560        //            y4 = bounds.y - (labelHeight + (int)bufferText) * 4;
1561        // <editor-fold defaultstate="collapsed" desc="Build Modifiers">
1562        String modifierValue = null;
1563        TextInfo tiTemp = null;
1564        //if(ModifiersUnits.C_QUANTITY in modifiers 
1565        if (modifiers.indexOfKey(ModifiersUnits.C_QUANTITY) >= 0
1566                && SymbolUtilities.canUnitHaveModifier(symbolID, ModifiersUnits.C_QUANTITY))
1567        {
1568            String text = modifiers.get(ModifiersUnits.C_QUANTITY);
1569            if(text != null)
1570            {
1571                    //bounds = armyc2.c2sd.renderer.utilities.RendererUtilities.getTextOutlineBounds(_modifierFont, text, new SO.Point(0,0));
1572                    tiTemp = new TextInfo(text, 0, 0, _modifierFont);
1573                    labelBounds = tiTemp.getTextBounds();
1574                    labelWidth = labelBounds.width();
1575                    x = Math.round((symbolBounds.left + (symbolBounds.width() * 0.5f)) - (labelWidth * 0.5f));
1576                    y = Math.round(symbolBounds.top - bufferY - descent);
1577                    tiTemp.setLocation(x, y);
1578                    tiArray.add(tiTemp);
1579            }
1580        }
1581
1582        //if(ModifiersUnits.X_ALTITUDE_DEPTH in modifiers || ModifiersUnits.Y_LOCATION in modifiers)
1583        if (modifiers.indexOfKey(ModifiersUnits.X_ALTITUDE_DEPTH) >= 0 || modifiers.indexOfKey(ModifiersUnits.Y_LOCATION) >= 0)
1584        {
1585            modifierValue = null;
1586
1587            String xm = null,
1588                    ym = null;
1589
1590            if (modifiers.indexOfKey(ModifiersUnits.X_ALTITUDE_DEPTH) >= 0 && SymbolUtilities.canUnitHaveModifier(symbolID, ModifiersUnits.X_ALTITUDE_DEPTH))
1591            {
1592                xm = modifiers.get(ModifiersUnits.X_ALTITUDE_DEPTH);// xm = modifiers.X;
1593            }
1594            if (modifiers.indexOfKey(ModifiersUnits.Y_LOCATION) >= 0)
1595            {
1596                ym = modifiers.get(ModifiersUnits.Y_LOCATION);// ym = modifiers.Y;
1597            }
1598            if (xm == null && ym != null)
1599            {
1600                modifierValue = ym;
1601            }
1602            else if (xm != null && ym == null)
1603            {
1604                modifierValue = xm;
1605            }
1606            else if (xm != null && ym != null)
1607            {
1608                modifierValue = xm + "  " + ym;
1609            }
1610
1611            if(modifierValue != null)
1612            {
1613                    tiTemp = new TextInfo(modifierValue, 0, 0, _modifierFont);
1614                    labelBounds = tiTemp.getTextBounds();
1615                    labelWidth = labelBounds.width();
1616        
1617                    if (!byLabelHeight)
1618                    {
1619                        x = bounds.left - labelBounds.width() - bufferXL;
1620                        y = bounds.top + labelHeight - descent;
1621                    }
1622                    else
1623                    {
1624                        x = bounds.left - labelBounds.width() - bufferXL;
1625        
1626                        y = (bounds.height());
1627                        y = (int) ((y * 0.5) + (labelHeight * 0.5));
1628        
1629                        y = y - ((labelHeight + bufferText));
1630                        y = bounds.top + y;
1631                    }
1632        
1633                    tiTemp.setLocation(x, y);
1634                    tiArray.add(tiTemp);
1635            }
1636        }
1637
1638        if (modifiers.indexOfKey(ModifiersUnits.G_STAFF_COMMENTS) >= 0 && SymbolUtilities.canUnitHaveModifier(symbolID, ModifiersUnits.G_STAFF_COMMENTS))
1639        {
1640            modifierValue = modifiers.get(ModifiersUnits.G_STAFF_COMMENTS);
1641
1642            if(modifierValue != null)
1643            {
1644                    tiTemp = new TextInfo(modifierValue, 0, 0, _modifierFont);
1645                    labelBounds = tiTemp.getTextBounds();
1646                    labelWidth = labelBounds.width();
1647        
1648                    x = bounds.left + bounds.width() + bufferXR;
1649                    if (!byLabelHeight)
1650                    {
1651                        y = bounds.top + labelHeight - descent;
1652                    }
1653                    else
1654                    {
1655                        y = (bounds.height());
1656                        y = (int) ((y * 0.5) + (labelHeight * 0.5));
1657        
1658                        y = y - ((labelHeight + bufferText));
1659                        y = bounds.top + y;
1660                    }
1661        
1662                    tiTemp.setLocation(x, y);
1663                    tiArray.add(tiTemp);
1664        
1665                    //Concession for cpof name label
1666                    if ((x + labelWidth + 3) > cpofNameX)
1667                    {
1668                        cpofNameX = x + labelWidth + 3;
1669                    }
1670            }
1671        }
1672
1673        if ((modifiers.indexOfKey(ModifiersUnits.V_EQUIP_TYPE) >= 0) ||
1674                (modifiers.indexOfKey(ModifiersUnits.AD_PLATFORM_TYPE) >= 0) ||
1675                (modifiers.indexOfKey(ModifiersUnits.AE_EQUIPMENT_TEARDOWN_TIME) >= 0))
1676        {
1677            String vm = null,
1678                    adm = null,
1679                    aem = null;
1680
1681            if (modifiers.indexOfKey(ModifiersUnits.V_EQUIP_TYPE) >= 0 && SymbolUtilities.canUnitHaveModifier(symbolID, ModifiersUnits.V_EQUIP_TYPE))
1682            {
1683                vm = modifiers.get(ModifiersUnits.V_EQUIP_TYPE);
1684            }
1685            if (modifiers.indexOfKey(ModifiersUnits.AD_PLATFORM_TYPE) >= 0 && SymbolUtilities.canUnitHaveModifier(symbolID, ModifiersUnits.AD_PLATFORM_TYPE))
1686            {
1687                adm = modifiers.get(ModifiersUnits.AD_PLATFORM_TYPE);
1688            }
1689            if (modifiers.indexOfKey(ModifiersUnits.AE_EQUIPMENT_TEARDOWN_TIME) >= 0 && SymbolUtilities.canUnitHaveModifier(symbolID, ModifiersUnits.AE_EQUIPMENT_TEARDOWN_TIME))
1690            {
1691                aem = modifiers.get(ModifiersUnits.AE_EQUIPMENT_TEARDOWN_TIME);
1692            }
1693
1694            modifierValue = "";
1695            if(vm != null && vm.equals("") == false)
1696                modifierValue = vm;
1697            if(adm != null && adm.equals("") == false)
1698                modifierValue += " " + adm;
1699            if(aem != null && aem.equals("") == false)
1700                modifierValue += " " + aem;
1701
1702            if(modifierValue != null)
1703                modifierValue = modifierValue.trim();
1704            if(modifierValue != null && modifierValue.equals("") == false)
1705            {
1706                    tiTemp = new TextInfo(modifierValue, 0, 0, _modifierFont);
1707                    labelBounds = tiTemp.getTextBounds();
1708                    labelWidth = labelBounds.width();
1709        
1710                    x = bounds.left - labelBounds.width() - bufferXL;
1711        
1712                    y = (bounds.height());
1713                    y = (int) ((y * 0.5f) + ((labelHeight - descent) * 0.5f));
1714                    y = bounds.top + y;
1715        
1716                    tiTemp.setLocation(x, y);
1717                    tiArray.add(tiTemp);
1718            }
1719        }
1720
1721        if (modifiers.indexOfKey(ModifiersUnits.H_ADDITIONAL_INFO_1) >= 0 || modifiers.indexOfKey(ModifiersUnits.AF_COMMON_IDENTIFIER) >= 0)
1722        {
1723            modifierValue = "";
1724            String hm = "",
1725                    afm = "";
1726
1727            hm = modifiers.get(ModifiersUnits.H_ADDITIONAL_INFO_1);
1728            if (modifiers.indexOfKey(ModifiersUnits.H_ADDITIONAL_INFO_1) >= 0)
1729            {
1730                hm = modifiers.get(ModifiersUnits.H_ADDITIONAL_INFO_1);
1731            }
1732            if (modifiers.indexOfKey(ModifiersUnits.AF_COMMON_IDENTIFIER) >= 0 && SymbolUtilities.canUnitHaveModifier(symbolID, ModifiersUnits.AF_COMMON_IDENTIFIER))
1733            {
1734                afm = modifiers.get(ModifiersUnits.AF_COMMON_IDENTIFIER);
1735            }
1736
1737            modifierValue = hm + " " + afm;
1738            modifierValue = modifierValue.trim();
1739
1740            if(modifierValue != null && modifierValue.equals("") == false)
1741            {
1742                    tiTemp = new TextInfo(modifierValue, 0, 0, _modifierFont);
1743                    labelBounds = tiTemp.getTextBounds();
1744                    labelWidth = labelBounds.width();
1745        
1746                    x = bounds.left + bounds.width() + bufferXR;
1747        
1748                    y = (bounds.height());
1749                    y = (int) ((y * 0.5) + ((labelHeight - descent) * 0.5));
1750                    y = bounds.top + y;
1751        
1752                    tiTemp.setLocation(x, y);
1753                    tiArray.add(tiTemp);
1754        
1755                    //Concession for cpof name label
1756                    if ((x + labelWidth + 3) > cpofNameX)
1757                    {
1758                        cpofNameX = x + labelWidth + 3;
1759                    }
1760            }
1761        }
1762
1763        if (modifiers.indexOfKey(ModifiersUnits.T_UNIQUE_DESIGNATION_1) >= 0)
1764        {
1765            modifierValue = modifiers.get(ModifiersUnits.T_UNIQUE_DESIGNATION_1);
1766
1767            if(modifierValue != null)
1768            {
1769                    tiTemp = new TextInfo(modifierValue, 0, 0, _modifierFont);
1770                    labelBounds = tiTemp.getTextBounds();
1771                    labelWidth = labelBounds.width();
1772        
1773                    if (!byLabelHeight)
1774                    {
1775                        x = bounds.left - labelWidth - bufferXL;
1776                        y = bounds.top + bounds.height();
1777                    }
1778                    else
1779                    {
1780                        x = bounds.left - labelWidth - bufferXL;
1781        
1782                        y = (bounds.height());
1783                        y = (int) ((y * 0.5) + (labelHeight * 0.5));
1784        
1785                        y = y + ((labelHeight + bufferText) - descent);
1786                        y = bounds.top + y;
1787                    }
1788        
1789                    tiTemp.setLocation(x, y);
1790                    tiArray.add(tiTemp);
1791            }
1792        }
1793
1794        if (modifiers.indexOfKey(ModifiersUnits.M_HIGHER_FORMATION) >= 0 || modifiers.indexOfKey(ModifiersUnits.CC_COUNTRY_CODE) >= 0)
1795        {
1796            modifierValue = "";
1797
1798            if (modifiers.indexOfKey(ModifiersUnits.M_HIGHER_FORMATION) >= 0 && SymbolUtilities.canUnitHaveModifier(symbolID, ModifiersUnits.M_HIGHER_FORMATION))
1799            {
1800                modifierValue += modifiers.get(ModifiersUnits.M_HIGHER_FORMATION);
1801            }
1802            if (modifiers.indexOfKey(ModifiersUnits.CC_COUNTRY_CODE) >= 0)
1803            {
1804                if (modifierValue.length() > 0)
1805                {
1806                    modifierValue += " ";
1807                }
1808                modifierValue += modifiers.get(ModifiersUnits.CC_COUNTRY_CODE);
1809            }
1810
1811            if(modifierValue.equals("")==false)
1812            {
1813                tiTemp = new TextInfo(modifierValue, 0, 0, _modifierFont);
1814                labelBounds = tiTemp.getTextBounds();
1815                labelWidth = labelBounds.width();
1816
1817                x = bounds.left + bounds.width() + bufferXR;
1818                if (!byLabelHeight)
1819                {
1820                    y = bounds.top + bounds.height();
1821                }
1822                else
1823                {
1824                    y = (bounds.height());
1825                    y = (int) ((y * 0.5) + (labelHeight * 0.5));
1826
1827                    y = y + ((labelHeight + bufferText - descent));
1828                    y = bounds.top + y;
1829                }
1830
1831                tiTemp.setLocation(x, y);
1832                tiArray.add(tiTemp);
1833
1834                //Concession for cpof name label
1835                if ((x + labelWidth + 3) > cpofNameX)
1836                {
1837                    cpofNameX = x + labelWidth + 3;
1838                }
1839            }
1840        }
1841
1842        if (modifiers.indexOfKey(ModifiersUnits.Z_SPEED) >= 0 && SymbolUtilities.canUnitHaveModifier(symbolID, ModifiersUnits.Z_SPEED))
1843        {
1844            modifierValue = modifiers.get(ModifiersUnits.Z_SPEED);
1845
1846            if(modifierValue != null)
1847            {
1848                    tiTemp = new TextInfo(modifierValue, 0, 0, _modifierFont);
1849                    labelBounds = tiTemp.getTextBounds();
1850                    labelWidth = labelBounds.width();
1851        
1852                    x = bounds.left - labelWidth - bufferXL;
1853                    if (!byLabelHeight)
1854                    {
1855                        y = Math.round(bounds.top + bounds.height() + labelHeight + bufferText);
1856                    }
1857                    else
1858                    {
1859                        y = (bounds.height());
1860                        y = (int) ((y * 0.5) + (labelHeight * 0.5));
1861        
1862                        y = y + ((labelHeight + bufferText) * 2) - (descent * 2);
1863                        y = Math.round(bounds.top + y);
1864                    }
1865        
1866                    tiTemp.setLocation(x, y);
1867                    tiArray.add(tiTemp);
1868            }
1869        }
1870
1871        if (modifiers.indexOfKey(ModifiersUnits.J_EVALUATION_RATING) >= 0
1872                || modifiers.indexOfKey(ModifiersUnits.K_COMBAT_EFFECTIVENESS) >= 0//
1873                || modifiers.indexOfKey(ModifiersUnits.L_SIGNATURE_EQUIP) >= 0//
1874                || modifiers.indexOfKey(ModifiersUnits.N_HOSTILE) >= 0//
1875                || modifiers.indexOfKey(ModifiersUnits.P_IFF_SIF) >= 0)//
1876        {
1877            modifierValue = null;
1878
1879            String jm = null,
1880                    km = null,
1881                    lm = null,
1882                    nm = null,
1883                    pm = null;
1884
1885            if (modifiers.indexOfKey(ModifiersUnits.J_EVALUATION_RATING) >= 0)
1886            {
1887                jm = modifiers.get(ModifiersUnits.J_EVALUATION_RATING);
1888            }
1889            if (modifiers.indexOfKey(ModifiersUnits.K_COMBAT_EFFECTIVENESS) >= 0 && SymbolUtilities.canUnitHaveModifier(symbolID, ModifiersUnits.K_COMBAT_EFFECTIVENESS))
1890            {
1891                km = modifiers.get(ModifiersUnits.K_COMBAT_EFFECTIVENESS);
1892            }
1893            if (modifiers.indexOfKey(ModifiersUnits.L_SIGNATURE_EQUIP) >= 0 && SymbolUtilities.canUnitHaveModifier(symbolID, ModifiersUnits.L_SIGNATURE_EQUIP))
1894            {
1895                lm = modifiers.get(ModifiersUnits.L_SIGNATURE_EQUIP);
1896            }
1897            if (modifiers.indexOfKey(ModifiersUnits.N_HOSTILE) >= 0 && SymbolUtilities.canUnitHaveModifier(symbolID, ModifiersUnits.N_HOSTILE))
1898            {
1899                nm = modifiers.get(ModifiersUnits.N_HOSTILE);
1900            }
1901            if (modifiers.indexOfKey(ModifiersUnits.P_IFF_SIF) >= 0 && SymbolUtilities.canUnitHaveModifier(symbolID, ModifiersUnits.P_IFF_SIF))
1902            {
1903                pm = modifiers.get(ModifiersUnits.P_IFF_SIF);
1904            }
1905
1906            modifierValue = "";
1907            if (jm != null && jm.equals("") == false)
1908            {
1909                modifierValue = modifierValue + jm;
1910            }
1911            if (km != null && km.equals("") == false)
1912            {
1913                modifierValue = modifierValue + " " + km;
1914            }
1915            if (lm != null && lm.equals("") == false)
1916            {
1917                modifierValue = modifierValue + " " + lm;
1918            }
1919            if (nm != null && nm.equals("") == false)
1920            {
1921                modifierValue = modifierValue + " " + nm;
1922            }
1923            if (pm != null && pm.equals("") == false)
1924            {
1925                modifierValue = modifierValue + " " + pm;
1926            }
1927
1928            if (modifierValue.length() > 2 && modifierValue.charAt(0) == ' ')
1929            {
1930                modifierValue = modifierValue.substring(1);
1931            }
1932
1933            modifierValue = modifierValue.trim();
1934
1935            if(modifierValue.equals("")==false)
1936            {
1937                tiTemp = new TextInfo(modifierValue, 0, 0, _modifierFont);
1938                labelBounds = tiTemp.getTextBounds();
1939                labelWidth = labelBounds.width();
1940
1941                x = bounds.left + bounds.width() + bufferXR;
1942                if (!byLabelHeight)
1943                {
1944                    y = Math.round(bounds.top + bounds.height() + labelHeight + bufferText);
1945                }
1946                else
1947                {
1948                    y = (bounds.height());
1949                    y = (int) ((y * 0.5) + (labelHeight * 0.5));
1950
1951                    y = y + ((labelHeight + bufferText) * 2) - (descent * 2);
1952                    y = Math.round(bounds.top + y);
1953                }
1954
1955                tiTemp.setLocation(x, y);
1956                tiArray.add(tiTemp);
1957
1958                //Concession for cpof name label
1959                if ((x + labelWidth + 3) > cpofNameX)
1960                {
1961                    cpofNameX = x + labelWidth + 3;
1962                }
1963            }
1964
1965        }
1966
1967        if (modifiers.indexOfKey(ModifiersUnits.W_DTG_1) >= 0)
1968        {
1969            modifierValue = modifiers.get(ModifiersUnits.W_DTG_1);
1970
1971            if(modifierValue != null)
1972            {
1973                    tiTemp = new TextInfo(modifierValue, 0, 0, _modifierFont);
1974                    labelBounds = tiTemp.getTextBounds();
1975                    labelWidth = labelBounds.width();
1976        
1977                    if (!byLabelHeight)
1978                    {
1979                        x = bounds.left - labelWidth - bufferXL;
1980                        y = bounds.top - bufferY - descent;
1981                    }
1982                    else
1983                    {
1984                        x = bounds.left - labelWidth - bufferXL;
1985        
1986                        y = (bounds.height());
1987                        y = (int) ((y * 0.5) + (labelHeight * 0.5));
1988        
1989                        y = y - ((labelHeight + bufferText) * 2);
1990                        y = bounds.top + y;
1991                    }
1992        
1993                    tiTemp.setLocation(x, y);
1994                    tiArray.add(tiTemp);
1995            }
1996        }
1997
1998        if (modifiers.indexOfKey(ModifiersUnits.F_REINFORCED_REDUCED) >= 0 || modifiers.indexOfKey(ModifiersUnits.E_FRAME_SHAPE_MODIFIER) >= 0)
1999        {
2000            modifierValue = null;
2001            String E = null,
2002                    F = null;
2003
2004            if (modifiers.indexOfKey(ModifiersUnits.E_FRAME_SHAPE_MODIFIER) >= 0)
2005            {
2006                E = modifiers.get(ModifiersUnits.E_FRAME_SHAPE_MODIFIER);
2007                modifiers.delete(ModifiersUnits.E_FRAME_SHAPE_MODIFIER);
2008            }
2009            if (modifiers.indexOfKey(ModifiersUnits.F_REINFORCED_REDUCED) >= 0 && SymbolUtilities.canUnitHaveModifier(symbolID, ModifiersUnits.F_REINFORCED_REDUCED))
2010            {
2011                F = modifiers.get(ModifiersUnits.F_REINFORCED_REDUCED);
2012            }
2013
2014            if (E != null && E.equals("") == false)
2015            {
2016                modifierValue = E;
2017            }
2018
2019            if (F != null && F.equals("") == false)
2020            {
2021                if (F.toUpperCase(Locale.US) == ("R"))
2022                {
2023                    F = "(+)";
2024                }
2025                else if (F.toUpperCase(Locale.US) == ("D"))
2026                {
2027                    F = "(-)";
2028                }
2029                else if (F.toUpperCase(Locale.US) == ("RD"))
2030                {
2031                    F = "(" + (char) (177) + ")";
2032                }
2033            }
2034
2035            if (F != null && F.equals("") == false)
2036            {
2037                if (modifierValue != null && modifierValue.equals("") == false)
2038                {
2039                    modifierValue = modifierValue + " " + F;
2040                }
2041                else
2042                {
2043                    modifierValue = F;
2044                }
2045            }
2046
2047            if(modifierValue != null)
2048            {
2049                    tiTemp = new TextInfo(modifierValue, 0, 0, _modifierFont);
2050                    labelBounds = tiTemp.getTextBounds();
2051                    labelWidth = labelBounds.width();
2052        
2053                    if (!byLabelHeight)
2054                    {
2055                        x = bounds.left + bounds.width() + bufferXR;
2056                        y = bounds.top - bufferY - descent;
2057                    }
2058                    else
2059                    {
2060                        x = bounds.left + bounds.width() + bufferXR;
2061        
2062                        y = (bounds.height());
2063                        y = (int) ((y * 0.5) + (labelHeight * 0.5));
2064        
2065                        y = y - ((labelHeight + bufferText) * 2);
2066                        y = bounds.top + y;
2067                    }
2068        
2069                    tiTemp.setLocation(x, y);
2070                    tiArray.add(tiTemp);
2071        
2072                    //Concession for cpof name label
2073                    if ((x + labelWidth + 3) > cpofNameX)
2074                    {
2075                        cpofNameX = x + labelWidth + 3;
2076                    }
2077            }
2078        }
2079
2080        if (modifiers.indexOfKey(ModifiersUnits.AA_SPECIAL_C2_HQ) >= 0 && SymbolUtilities.canUnitHaveModifier(symbolID, ModifiersUnits.AA_SPECIAL_C2_HQ))
2081        {
2082            modifierValue = modifiers.get(ModifiersUnits.AA_SPECIAL_C2_HQ);
2083
2084            if(modifierValue != null)
2085            {
2086                    tiTemp = new TextInfo(modifierValue, 0, 0, _modifierFont);
2087                    labelBounds = tiTemp.getTextBounds();
2088                    labelWidth = labelBounds.width();
2089        
2090                    x = (int) ((symbolBounds.left + (symbolBounds.width() * 0.5f)) - (labelWidth * 0.5f));
2091        
2092                    y = (symbolBounds.height());//checkpoint, get box above the point
2093                    y = (int) ((y * 0.5) + ((labelHeight - descent) * 0.5));
2094                    y = symbolBounds.top + y;
2095        
2096                    tiTemp.setLocation(x, y);
2097                    tiArray.add(tiTemp);
2098            }
2099        }
2100        
2101        if (modifiers.indexOfKey(ModifiersUnits.SCC_SONAR_CLASSIFICATION_CONFIDENCE) >= 0 && SymbolUtilities.canUnitHaveModifier(symbolID, ModifiersUnits.SCC_SONAR_CLASSIFICATION_CONFIDENCE))
2102        {
2103                int scc = 0;
2104            modifierValue = modifiers.get(ModifiersUnits.SCC_SONAR_CLASSIFICATION_CONFIDENCE);
2105            
2106            if(modifierValue != null && SymbolUtilities.isNumber(modifierValue) && SymbolUtilities.hasModifier(symbolID, ModifiersUnits.SCC_SONAR_CLASSIFICATION_CONFIDENCE))
2107            {
2108                    tiTemp = new TextInfo(modifierValue, 0, 0, _modifierFont);
2109                    labelBounds = tiTemp.getTextBounds();
2110                    labelWidth = labelBounds.width();
2111        
2112                    x = (int) ((symbolBounds.left + (symbolBounds.width() * 0.5f)) - (labelWidth * 0.5f));
2113        
2114                    double yPosition = getYPositionForSCC(symbolID);
2115                    y = (bounds.height() );//checkpoint, get box above the point
2116                y = (int)(((y * yPosition) + ((labelHeight-descent) * 0.5)));
2117                y = bounds.top + y;
2118        
2119                    tiTemp.setLocation(x, y);
2120                    tiArray.add(tiTemp);
2121            }
2122        }
2123
2124        if (modifiers.indexOfKey(ModifiersUnits.CN_CPOF_NAME_LABEL) >= 0)
2125        {
2126            modifierValue = modifiers.get(ModifiersUnits.CN_CPOF_NAME_LABEL);
2127
2128            if(modifierValue != null)
2129            {
2130                    tiTemp = new TextInfo(modifierValue, 0, 0, _modifierFont);
2131                    labelBounds = tiTemp.getTextBounds();
2132                    labelWidth = labelBounds.width();
2133        
2134                    x = cpofNameX;
2135        
2136                    y = (bounds.height());//checkpoint, get box above the point
2137                    y = (int) ((y * 0.5) + (labelHeight * 0.5));
2138                    y = bounds.top + y;
2139        
2140                    tiTemp.setLocation(x, y);
2141                    tiArray.add(tiTemp);
2142            }
2143        }
2144
2145        // </editor-fold>
2146        // <editor-fold defaultstate="collapsed" desc="Shift Points and Draw">
2147        Rect modifierBounds = null;
2148        if (tiArray != null && tiArray.size() > 0)
2149        {
2150
2151            //build modifier bounds/////////////////////////////////////////
2152            modifierBounds = tiArray.get(0).getTextOutlineBounds();
2153            int size = tiArray.size();
2154            TextInfo tempShape = null;
2155            for (int i = 1; i < size; i++)
2156            {
2157                tempShape = tiArray.get(i);
2158                modifierBounds.union(tempShape.getTextOutlineBounds());
2159            }
2160
2161        }
2162
2163        if (modifierBounds != null)
2164        {
2165
2166            imageBounds.union(modifierBounds);
2167
2168            //shift points if needed////////////////////////////////////////
2169            if (imageBounds.left < 0 || imageBounds.top < 0)
2170            {
2171                int shiftX = Math.round(Math.abs(imageBounds.left)),
2172                        shiftY = Math.round(Math.abs(imageBounds.top));
2173
2174                //shift mobility points
2175                int size = tiArray.size();
2176                TextInfo tempShape = null;
2177                for (int i = 0; i < size; i++)
2178                {
2179                    tempShape = tiArray.get(i);
2180                    tempShape.shift(shiftX, shiftY);
2181                }
2182                RectUtilities.shift(modifierBounds, shiftX, shiftY);
2183                //modifierBounds.shift(shiftX,shiftY);
2184
2185                //shift image points
2186                centerPoint.offset(shiftX, shiftY);
2187                RectUtilities.shift(symbolBounds, shiftX, shiftY);
2188                RectUtilities.shift(imageBounds, shiftX, shiftY);
2189                RectUtilities.shift(imageBoundsOld, shiftX, shiftY);
2190                /*centerPoint.shift(shiftX, shiftY);
2191                 symbolBounds.shift(shiftX, shiftY);
2192                 imageBounds.shift(shiftX, shiftY);
2193                 imageBoundsOld.shift(shiftX, shiftY);//*/
2194            }
2195
2196            Bitmap bmp = Bitmap.createBitmap(imageBounds.width(), imageBounds.height(), Config.ARGB_8888);
2197            Canvas ctx = new Canvas(bmp);
2198
2199            //render////////////////////////////////////////////////////////
2200            //draw original icon with potential modifiers.
2201            ctx.drawBitmap(ii.getImage(), imageBoundsOld.left, imageBoundsOld.top, null);
2202            //ctx.drawImage(ii.getImage(),imageBoundsOld.left,imageBoundsOld.top);
2203            
2204            
2205            if (attributes.indexOfKey(MilStdAttributes.TextColor) >= 0)
2206            {
2207                textColor = SymbolUtilities.getColorFromHexString(attributes.get(MilStdAttributes.TextColor));
2208                if(alpha > -1)
2209                    textColor.setAlpha(alpha);
2210            }
2211            if (attributes.indexOfKey(MilStdAttributes.TextBackgroundColor) >= 0)
2212            {
2213                textBackgroundColor = SymbolUtilities.getColorFromHexString(attributes.get(MilStdAttributes.TextBackgroundColor));
2214                if(alpha > -1)
2215                    textBackgroundColor.setAlpha(alpha);
2216            }
2217
2218            renderText(ctx, tiArray, textColor, textBackgroundColor);
2219
2220            newii = new ImageInfo(bmp, centerPoint, symbolBounds);
2221
2222        }
2223        // </editor-fold>
2224
2225        // <editor-fold defaultstate="collapsed" desc="Cleanup">
2226        tiArray = null;
2227        tiTemp = null;
2228        //tempShape = null;
2229        imageBoundsOld = null;
2230        //ctx = null;
2231        //buffer = null;
2232        // </editor-fold>
2233
2234        return newii;
2235    }
2236
2237    public static ImageInfo ProcessTGSPWithSpecialModifierLayout(ImageInfo ii, String symbolID, SparseArray<String> modifiers, SparseArray<String> attributes, Color lineColor)
2238    {
2239        int bufferXL = 6;
2240        int bufferXR = 4;
2241        int bufferY = 2;
2242        int bufferText = 2;
2243        int centerOffset = 1; //getCenterX/Y function seems to go over by a pixel
2244        int x = 0;
2245        int y = 0;
2246        int x2 = 0;
2247        int y2 = 0;
2248        int symStd = RS.getSymbologyStandard();
2249        int outlineOffset = RS.getTextOutlineWidth();
2250        int labelHeight = 0;
2251        int labelWidth = 0;
2252        int alpha = -1;
2253        ImageInfo newii = null;
2254        Color textColor = lineColor;
2255        Color textBackgroundColor = null;
2256
2257        ArrayList<TextInfo> arrMods = new ArrayList<TextInfo>();
2258        boolean duplicate = false;
2259
2260        Rect bounds = new Rect(ii.getSymbolBounds());
2261        Rect symbolBounds = new Rect(ii.getSymbolBounds());
2262        Point centerPoint = new Point(ii.getCenterPoint());
2263        Rect imageBounds = new Rect(ii.getImageBounds());
2264
2265        if (attributes.indexOfKey(MilStdAttributes.SymbologyStandard) >= 0)
2266        {
2267            symStd = Integer.parseInt(attributes.get(MilStdAttributes.SymbologyStandard));
2268        }
2269        if (attributes.indexOfKey(MilStdAttributes.Alpha) >= 0)
2270        {
2271            alpha = Integer.parseInt(attributes.get(MilStdAttributes.Alpha));
2272            textColor.setAlpha(alpha);
2273        }
2274
2275        centerPoint = new Point(Math.round(ii.getCenterPoint().x), Math.round(ii.getCenterPoint().y));
2276
2277        boolean byLabelHeight = false;
2278        labelHeight = (int) (_modifierFontHeight + 0.5f);
2279
2280        int maxHeight = (symbolBounds.height());
2281        if ((labelHeight * 3) > maxHeight)
2282        {
2283            byLabelHeight = true;
2284        }
2285
2286        int descent = (int) (_modifierFontDescent + 0.5f);
2287        int yForY = -1;
2288
2289        Rect labelBounds1 = null;//text.getPixelBounds(null, 0, 0);
2290        Rect labelBounds2 = null;
2291        String strText = "";
2292        String strText1 = "";
2293        String strText2 = "";
2294        TextInfo text1 = null;
2295        TextInfo text2 = null;
2296
2297        String basicID = SymbolUtilities.getBasicSymbolID(symbolID);
2298
2299        if (outlineOffset > 2)
2300        {
2301            outlineOffset = ((outlineOffset - 1) / 2);
2302        }
2303        else
2304        {
2305            outlineOffset = 0;
2306        }
2307
2308        // <editor-fold defaultstate="collapsed" desc="Process Integral Text">
2309        if (basicID.equals("G*G*GPRD--****X"))//DLRP (D)
2310        {
2311
2312            strText1 = "D";
2313
2314            text1 = new TextInfo(strText1, 0, 0, _modifierFont);
2315
2316            labelBounds1 = text1.getTextBounds();
2317            if (symStd == RendererSettings.Symbology_2525B)
2318            {
2319                y = symbolBounds.top + symbolBounds.height();
2320                x = symbolBounds.left - labelBounds1.width() - bufferXL;
2321                text1.setLocation(Math.round(x), Math.round(y));
2322            }
2323            else//2525C built in
2324            {
2325                text1 = null;
2326                //y = symbolBounds.top + symbolBounds.getHeight() - bufferY;
2327                //x = symbolBounds.left + symbolBounds.width()/2 - labelBounds1.getWidth()/2;
2328            }
2329
2330            //ErrorLogger.LogMessage("D: " + String.valueOf(x)+ ", " + String.valueOf(y));
2331        }
2332        else if (basicID.equals("G*G*APU---****X")) //pull-up point (PUP)
2333        {
2334            strText1 = "PUP";
2335            text1 = new TextInfo(strText1, 0, 0, _modifierFont);
2336
2337            labelBounds1 = text1.getTextBounds();
2338            y = RectUtilities.getCenterY(symbolBounds) + ((labelBounds1.height() - descent) / 2);
2339            x = symbolBounds.left + symbolBounds.width() + bufferXR;
2340
2341            text1.setLocation(Math.round(x), Math.round(y));
2342        }
2343        else if (basicID.equals("G*M*NZ----****X")) //Nuclear Detonation Ground Zero (N)
2344        {
2345//                strText1 = "N";
2346//                text1 = new TextLayout(strText1, labelFont, frc);
2347//                labelBounds1 = text1.getPixelBounds(null, 0, 0);
2348//                y = symbolBounds.top + (symbolBounds.getHeight() * 0.8) - centerOffset;
2349//                x = symbolBounds.getCenterX() - centerOffset - (labelBounds1.getWidth()/2);
2350        }
2351        else if (basicID.equals("G*M*NF----****X"))//Fallout Producing (N)
2352        {
2353//                strText1 = "N";
2354//                text1 = new TextLayout(strText1, labelFont, frc);
2355//                descent = text1.getDescent();
2356//                labelBounds1 = text1.getPixelBounds(null, 0, 0);
2357//                y = symbolBounds.top + (symbolBounds.getHeight() * 0.8) - centerOffset;
2358//                x = symbolBounds.getCenterX() - centerOffset - (labelBounds1.getWidth()/2);
2359        }
2360        else if (basicID.equals("G*M*NEB---****X"))//Release Events Biological (BIO, B)
2361        {
2362            //strText1 = "B";
2363            //text1 = new TextLayout(strText1, labelFont, frc);
2364            int offset = 1;
2365            strText2 = "BIO";
2366            text2 = new TextInfo(strText2, 0, 0, _modifierFont);
2367
2368            labelBounds2 = text2.getTextBounds();
2369            //y = symbolBounds.top + (symbolBounds.getHeight() * 0.9);
2370            //x = symbolBounds.getCenterX() - centerOffset - (labelBounds1.getWidth()/2);
2371
2372            y2 = (int) (RectUtilities.getCenterY(symbolBounds) + ((labelBounds2.height() - descent) * 0.5f));
2373
2374            x2 = symbolBounds.left - labelBounds2.width() - bufferXL;
2375
2376            text2.setLocation(Math.round(x2), Math.round(y2 - offset));
2377            //ErrorLogger.LogMessage("BIO: " + String.valueOf(x2)+ ", " + String.valueOf(y2));
2378        }
2379        else if (basicID.equals("G*M*NEC---****X"))//Release Events Chemical (CML, C)
2380        {
2381            //strText1 = "C";
2382            //text1 = new TextLayout(strText1, labelFont, frc);
2383            int offset = 1;
2384            strText2 = "CML";
2385            text2 = new TextInfo(strText2, 0, 0, _modifierFont);
2386
2387            labelBounds2 = text2.getTextBounds();
2388            //y = symbolBounds.top + (symbolBounds.getHeight() * 0.9);
2389            //x = symbolBounds.getCenterX() - centerOffset - (labelBounds1.getWidth()/2);
2390
2391            y2 = RectUtilities.getCenterY(symbolBounds) + ((labelBounds2.height() - descent) / 2);
2392
2393            x2 = symbolBounds.left - labelBounds2.width() - bufferXL;
2394
2395            text2.setLocation(Math.round(x2), Math.round(y2 - offset));
2396        }
2397        if (text1 != null)
2398        {
2399            arrMods.add(text1);
2400        }
2401        if (text2 != null)
2402        {
2403            arrMods.add(text2);
2404        }
2405
2406        // </editor-fold>
2407        // <editor-fold defaultstate="collapsed" desc="Process Special Modifiers">
2408        TextInfo ti = null;
2409        if (basicID.equals("G*M*NZ----****X") ||//ground zero
2410                basicID.equals("G*M*NEB---****X") ||//biological
2411                basicID.equals("G*M*NEC---****X"))//chemical
2412        {
2413            if ((labelHeight * 3) > bounds.height())
2414            {
2415                byLabelHeight = true;
2416            }
2417        }
2418
2419        if (basicID.equals("G*G*GPPC--****X")
2420                || basicID.equals("G*G*GPPD--****X"))
2421        {
2422            if (modifiers.indexOfKey(ModifiersTG.T_UNIQUE_DESIGNATION_1) >= 0)
2423            {
2424                strText = modifiers.get(ModifiersTG.T_UNIQUE_DESIGNATION_1);
2425                if(strText != null)
2426                {
2427                        ti = new TextInfo(strText, 0, 0, _modifierFont);
2428                        labelWidth = Math.round(ti.getTextBounds().width());
2429                        //One modifier symbols and modifier goes in center
2430                        x = bounds.left + (int) (bounds.width() * 0.5f);
2431                        x = x - (int) (labelWidth * 0.5f);
2432                        y = bounds.top + (int) (bounds.height() * 0.4f);
2433                        y = y + (int) (labelHeight * 0.5f);
2434        
2435                        ti.setLocation(Math.round(x), Math.round(y));
2436                        arrMods.add(ti);
2437                }
2438            }
2439        }
2440        else if (basicID.equals("G*G*GPH---****X"))
2441        {
2442            if (modifiers.indexOfKey(ModifiersTG.H_ADDITIONAL_INFO_1) >= 0)
2443            {
2444                strText = modifiers.get(ModifiersTG.H_ADDITIONAL_INFO_1);
2445                if(strText != null)
2446                {
2447                        ti = new TextInfo(strText, 0, 0, _modifierFont);
2448                        labelWidth = Math.round(ti.getTextBounds().width());
2449                        //One modifier symbols and modifier goes in center
2450                        x = bounds.left + (int) (bounds.width() * 0.5f);
2451                        x = x - (int) (labelWidth * 0.5f);
2452                        y = bounds.top + (int) (bounds.height() * 0.5f);
2453                        y = y + (int) (labelHeight * 0.5f);
2454        
2455                        ti.setLocation(Math.round(x), Math.round(y));
2456                        arrMods.add(ti);
2457                }
2458            }
2459        }
2460        else if (basicID.equals("G*G*GPRI--****X"))
2461        {
2462            if (modifiers.indexOfKey(ModifiersTG.T_UNIQUE_DESIGNATION_1) >= 0)
2463            {
2464                strText = modifiers.get(ModifiersTG.T_UNIQUE_DESIGNATION_1);
2465                if(strText != null)
2466                {
2467                        ti = new TextInfo(strText, 0, 0, _modifierFont);
2468                        labelWidth = Math.round(ti.getTextBounds().width());
2469                        //One modifier symbols, top third & center
2470                        x = bounds.left + (int) (bounds.width() * 0.5f);
2471                        x = x - (int) (labelWidth * 0.5f);
2472                        y = bounds.top + (int) (bounds.height() * 0.25f);
2473                        y = y + (int) (labelHeight * 0.5f);
2474        
2475                        ti.setLocation(Math.round(x), Math.round(y));
2476                        arrMods.add(ti);
2477                }
2478            }
2479        }
2480        else if (basicID.equals("G*G*GPPW--****X")
2481                || basicID.equals("G*F*PCF---****X"))
2482        {
2483            if (modifiers.indexOfKey(ModifiersTG.T_UNIQUE_DESIGNATION_1) >= 0)
2484            {
2485                strText = modifiers.get(ModifiersTG.T_UNIQUE_DESIGNATION_1);
2486                if(strText != null)
2487                {
2488                        ti = new TextInfo(strText, 0, 0, _modifierFont);
2489        
2490                        //One modifier symbols and modifier goes right of center
2491                        x = bounds.left + (int) (bounds.width() * 0.75f);
2492                        y = bounds.top + (int) (bounds.height() * 0.5f);
2493                        y = y + (int) ((labelHeight - descent) * 0.5f);
2494        
2495                        ti.setLocation(Math.round(x), Math.round(y));
2496                        arrMods.add(ti);
2497                }
2498            }
2499        }
2500        else if (basicID.equals("G*G*APP---****X")
2501                || basicID.equals("G*G*APC---****X"))
2502        {
2503            if (modifiers.indexOfKey(ModifiersTG.T_UNIQUE_DESIGNATION_1) >= 0)
2504            {
2505                strText = modifiers.get(ModifiersTG.T_UNIQUE_DESIGNATION_1);
2506                if(strText != null)
2507                {
2508                        ti = new TextInfo(strText, 0, 0, _modifierFont);
2509                        labelWidth = ti.getTextBounds().width();
2510                        //One modifier symbols and modifier goes just below of center
2511                        x = bounds.left + (int) (bounds.width() * 0.5);
2512                        x = x - (int) (labelWidth * 0.5);
2513                        y = bounds.top + (int) (bounds.height() * 0.5f);
2514                        y = y + (int) (((bounds.height() * 0.5f) - labelHeight) / 2) + labelHeight - descent;
2515        
2516                        ti.setLocation(Math.round(x), Math.round(y));
2517                        arrMods.add(ti);
2518                }
2519            }
2520        }
2521        else if (basicID.equals("G*G*DPT---****X") || //T (target reference point)
2522                basicID.equals("G*F*PTS---****X") || //t,h,h1 (Point/Single Target)
2523                basicID.equals("G*F*PTN---****X")) //T (nuclear target)
2524        { //Targets with special modifier positions
2525            if (modifiers.indexOfKey(ModifiersTG.H_ADDITIONAL_INFO_1) >= 0
2526                    && basicID.equals("G*F*PTS---****X"))//H
2527            {
2528                strText = modifiers.get(ModifiersTG.H_ADDITIONAL_INFO_1);
2529                if(strText != null)
2530                {
2531                        ti = new TextInfo(strText, 0, 0, _modifierFont);
2532        
2533                        x = RectUtilities.getCenterX(bounds) + (int) (bounds.width() * 0.15f);
2534                        y = bounds.top + (int) (bounds.height() * 0.75f);
2535                        y = y + (int) (labelHeight * 0.5f);
2536        
2537                        ti.setLocation(Math.round(x), Math.round(y));
2538                        arrMods.add(ti);
2539                }
2540            }
2541            if (modifiers.indexOfKey(ModifiersTG.H1_ADDITIONAL_INFO_2) >= 0
2542                    && basicID.equals("G*F*PTS---****X"))//H1
2543            {
2544                strText = modifiers.get(ModifiersTG.H1_ADDITIONAL_INFO_2);
2545                if(strText != null)
2546                {
2547                        ti = new TextInfo(strText, 0, 0, _modifierFont);
2548                        labelWidth = Math.round(ti.getTextBounds().width());
2549                        x = RectUtilities.getCenterX(bounds) - (int) (bounds.width() * 0.15f);
2550                        x = x - (labelWidth);
2551                        y = bounds.top + (int) (bounds.height() * 0.75f);
2552                        y = y + (int) (labelHeight * 0.5f);
2553        
2554                        ti.setLocation(Math.round(x), Math.round(y));
2555                        arrMods.add(ti);
2556                }
2557            }
2558            if (modifiers.indexOfKey(ModifiersTG.T_UNIQUE_DESIGNATION_1) >= 0)
2559            {
2560                strText = modifiers.get(ModifiersTG.T_UNIQUE_DESIGNATION_1);
2561                if(strText != null)
2562                {
2563                        ti = new TextInfo(strText, 0, 0, _modifierFont);
2564        
2565                        x = RectUtilities.getCenterX(bounds) + (int) (bounds.width() * 0.15f);
2566//                  x = x - (labelBounds.width * 0.5);
2567                        y = bounds.top + (int) (bounds.height() * 0.25f);
2568                        y = y + (int) (labelHeight * 0.5f);
2569        
2570                        ti.setLocation(Math.round(x), Math.round(y));
2571                        arrMods.add(ti);
2572                }
2573            }
2574
2575        }
2576        else if (basicID.equals("G*M*NZ----****X") ||//ground zero
2577                basicID.equals("G*M*NEB---****X") ||//biological
2578                basicID.equals("G*M*NEC---****X"))//chemical
2579        {//NBC
2580            if (modifiers.indexOfKey(ModifiersTG.N_HOSTILE) >= 0)
2581            {
2582                strText = modifiers.get(ModifiersTG.N_HOSTILE);
2583                if(strText != null)
2584                {
2585                        ti = new TextInfo(strText, 0, 0, _modifierFont);
2586        
2587                        x = bounds.left + bounds.width() + bufferXR;
2588        
2589                        if (!byLabelHeight)
2590                        {
2591                            y = bounds.top + bounds.height();
2592                        }
2593                        else
2594                        {
2595                            y = bounds.top + (int) ((bounds.height() * 0.5f) + ((labelHeight - descent) * 0.5) + (labelHeight - descent + bufferText));
2596                        }
2597        
2598                        ti.setLocation(Math.round(x), Math.round(y));
2599                        arrMods.add(ti);
2600                }
2601
2602            }
2603            if (modifiers.indexOfKey(ModifiersTG.H_ADDITIONAL_INFO_1) >= 0)
2604            {
2605                strText = modifiers.get(ModifiersTG.H_ADDITIONAL_INFO_1);
2606                if(strText != null)
2607                {
2608                        ti = new TextInfo(strText, 0, 0, _modifierFont);
2609        
2610                        x = bounds.left + bounds.width() + bufferXR;
2611                        if (!byLabelHeight)
2612                        {
2613                            y = bounds.top + labelHeight - descent;
2614                        }
2615                        else
2616                        {
2617                            //y = bounds.y + ((bounds.height * 0.5) + (labelHeight * 0.5) - (labelHeight + bufferText));
2618                            y = bounds.top + (int) ((bounds.height() * 0.5f) - ((labelHeight - descent) * 0.5) + (-descent - bufferText));
2619                        }
2620        
2621                        ti.setLocation(Math.round(x), Math.round(y));
2622                        arrMods.add(ti);
2623                }
2624            }
2625            if (modifiers.indexOfKey(ModifiersTG.W_DTG_1) >= 0)
2626            {
2627                strText = modifiers.get(ModifiersTG.W_DTG_1);
2628                if(strText != null)
2629                {
2630                        ti = new TextInfo(strText, 0, 0, _modifierFont);
2631                        labelWidth = Math.round(ti.getTextBounds().width());
2632        
2633                        x = bounds.left - labelWidth - bufferXL;
2634                        if (!byLabelHeight)
2635                        {
2636                            y = bounds.top + labelHeight - descent;
2637                        }
2638                        else
2639                        {
2640                            //y = bounds.y + ((bounds.height * 0.5) + (labelHeight * 0.5) - (labelHeight + bufferText));
2641                            y = bounds.top + (int) ((bounds.height() * 0.5) - ((labelHeight - descent) * 0.5) + (-descent - bufferText));
2642                        }
2643        
2644                        ti.setLocation(Math.round(x), Math.round(y));
2645                        arrMods.add(ti);
2646                }
2647            }
2648            if (basicID.equals("G*M*NZ----****X") == true && modifiers.indexOfKey(ModifiersTG.V_EQUIP_TYPE) >= 0)
2649            {
2650                strText = modifiers.get(ModifiersTG.V_EQUIP_TYPE);
2651                if(strText != null)
2652                {
2653                        ti = new TextInfo(strText, 0, 0, _modifierFont);
2654        
2655                        //subset of nbc, just nuclear
2656                        labelWidth = Math.round(ti.getTextBounds().width());
2657                        x = bounds.left - labelWidth - bufferXL;
2658                        y = bounds.top + (int) ((bounds.height() * 0.5) + ((labelHeight - descent) * 0.5));//((bounds.height / 2) - (labelHeight/2));
2659        
2660                        ti.setLocation(Math.round(x), Math.round(y));
2661                        arrMods.add(ti);
2662                }
2663            }
2664            if (modifiers.indexOfKey(ModifiersTG.T_UNIQUE_DESIGNATION_1) >= 0)
2665            {
2666                strText = modifiers.get(ModifiersTG.T_UNIQUE_DESIGNATION_1);
2667                if(strText != null)
2668                {
2669                        ti = new TextInfo(strText, 0, 0, _modifierFont);
2670                        labelWidth = Math.round(ti.getTextBounds().width());
2671                        x = bounds.left - labelWidth - bufferXL;
2672                        if (!byLabelHeight)
2673                        {
2674                            y = bounds.top + bounds.height();
2675                        }
2676                        else
2677                        {
2678                            //y = bounds.y + ((bounds.height * 0.5) + ((labelHeight-descent) * 0.5) + (labelHeight + bufferText));
2679                            y = bounds.top + (int) ((bounds.height() * 0.5) + ((labelHeight - descent) * 0.5) + (labelHeight - descent + bufferText));
2680                        }
2681                        ti.setLocation(Math.round(x), Math.round(y));
2682                        arrMods.add(ti);
2683                }
2684            }
2685            if (modifiers.indexOfKey(ModifiersTG.Y_LOCATION) >= 0)
2686            {
2687                strText = modifiers.get(ModifiersTG.Y_LOCATION);
2688                if(strText != null)
2689                {
2690                        ti = new TextInfo(strText, 0, 0, _modifierFont);
2691                        labelWidth = Math.round(ti.getTextBounds().width());
2692                        //just NBC
2693                        //x = bounds.getX() + (bounds.getWidth() * 0.5);
2694                        //x = x - (labelWidth * 0.5);
2695                        x = bounds.left + (int) (bounds.width() * 0.5f);
2696                        x = x - (int) (labelWidth * 0.5f);
2697        
2698                        if (!byLabelHeight)
2699                        {
2700                            y = bounds.top + bounds.height() + labelHeight - descent + bufferY;
2701                        }
2702                        else
2703                        {
2704                            y = bounds.top + (int) ((bounds.height() * 0.5) + ((labelHeight - descent) * 0.5) + ((labelHeight + bufferText) * 2) - descent);
2705        
2706                        }
2707                        yForY = y + descent; //so we know where to start the DOM arrow.
2708                        ti.setLocation(Math.round(x), Math.round(y));
2709                        arrMods.add(ti);
2710                }
2711
2712            }
2713            if (modifiers.indexOfKey(ModifiersTG.C_QUANTITY) >= 0)
2714            {
2715                strText = modifiers.get(ModifiersTG.C_QUANTITY);
2716                if(strText != null)
2717                {
2718                        ti = new TextInfo(strText, 0, 0, _modifierFont);
2719                        labelWidth = Math.round(ti.getTextBounds().width());
2720                        //subset of NBC, just nuclear
2721                        x = bounds.left + (int) (bounds.width() * 0.5);
2722                        x = x - (int) (labelWidth * 0.5);
2723                        y = bounds.top - descent;
2724                        ti.setLocation(Math.round(x), Math.round(y));
2725                        arrMods.add(ti);
2726                }
2727
2728            }
2729        }
2730        else if (basicID.equals("G*M*OFS---****X"))
2731        {
2732            if (modifiers.indexOfKey(ModifiersTG.H_ADDITIONAL_INFO_1) >= 0)
2733            {
2734                strText = modifiers.get(ModifiersTG.H_ADDITIONAL_INFO_1);
2735                if(strText != null)
2736                {
2737                        ti = new TextInfo(strText, 0, 0, _modifierFont);
2738                        labelWidth = Math.round(ti.getTextBounds().width());
2739                        x = bounds.left + (int) (bounds.width() * 0.5);
2740                        x = x - (int) (labelWidth * 0.5);
2741                        y = bounds.top - descent;// + (bounds.height * 0.5);
2742                        //y = y + (labelHeight * 0.5);
2743        
2744                        ti.setLocation(Math.round(x), Math.round(y));
2745                        arrMods.add(ti);
2746                }
2747
2748            }
2749            if (modifiers.indexOfKey(ModifiersTG.W_DTG_1) >= 0)
2750            {
2751                strText = modifiers.get(ModifiersTG.W_DTG_1);
2752                if(strText != null)
2753                {
2754                        ti = new TextInfo(strText, 0, 0, _modifierFont);
2755                        labelWidth = Math.round(ti.getTextBounds().width());
2756                        x = bounds.left + (int) (bounds.width() * 0.5);
2757                        x = x - (int) (labelWidth * 0.5);
2758                        y = bounds.top + (bounds.height());
2759                        y = y + (labelHeight);
2760        
2761                        ti.setLocation(Math.round(x), Math.round(y));
2762                        arrMods.add(ti);
2763                }
2764            }
2765            if (modifiers.indexOfKey(ModifiersTG.N_HOSTILE) >= 0)
2766            {
2767                strText = modifiers.get(ModifiersTG.N_HOSTILE);
2768                if(strText != null)
2769                {
2770                        ti = new TextInfo(strText, 0, 0, _modifierFont);
2771                        TextInfo ti2 = new TextInfo(strText, 0, 0, _modifierFont);
2772                        labelWidth = Math.round(ti.getTextBounds().width());
2773                        x = bounds.left + (bounds.width()) + bufferXR;//right
2774                        //x = x + labelWidth;//- (labelBounds.width * 0.75);
2775        
2776                        duplicate = true;
2777        
2778                        x2 = bounds.left;//left
2779                        x2 = x2 - labelWidth - bufferXL;// - (labelBounds.width * 0.25);
2780        
2781                        y = bounds.top + (int) (bounds.height() * 0.5);//center
2782                        y = y + (int) ((labelHeight - descent) * 0.5);
2783        
2784                        y2 = y;
2785        
2786                        ti.setLocation(Math.round(x), Math.round(y));
2787                        ti2.setLocation(Math.round(x2), Math.round(y2));
2788                        arrMods.add(ti);
2789                        arrMods.add(ti2);
2790                }
2791            }
2792
2793        }
2794        else if(basicID.charAt(0) == 'W')
2795        {
2796            String modX = null;
2797            if(modifiers.indexOfKey(ModifiersTG.X_ALTITUDE_DEPTH) > -1)
2798                modX = (modifiers.get(ModifiersTG.X_ALTITUDE_DEPTH));
2799
2800            if(basicID.equals("WAS-WSF-LVP----"))//Freezing Level
2801            {
2802                strText = "0" + (char)(176) + ":";
2803                if(modX != null)
2804                    strText += modX;
2805                else
2806                    strText += "?";
2807
2808                ti = new TextInfo(strText, 0, 0, _modifierFont);
2809                labelWidth = Math.round(ti.getTextBounds().width());
2810                //One modifier symbols and modifier goes in center
2811                x = bounds.left + (int) (bounds.width() * 0.5f);
2812                x = x - (int) (labelWidth * 0.5f);
2813                y = bounds.top + (int) (bounds.height() * 0.5f);
2814                y = y + (int) ((labelHeight - _modifierFontDescent) * 0.5f);
2815
2816                ti.setLocation(Math.round(x), Math.round(y));
2817                arrMods.add(ti);
2818            }
2819            else if(basicID.equals("WAS-WST-LVP----"))//tropopause Level
2820            {
2821                strText = "X?";
2822                if(modX != null)
2823                    strText = modX;
2824
2825                ti = new TextInfo(strText, 0, 0, _modifierFont);
2826                labelWidth = Math.round(ti.getTextBounds().width());
2827                //One modifier symbols and modifier goes in center
2828                x = bounds.left + (int) (bounds.width() * 0.5f);
2829                x = x - (int) (labelWidth * 0.5f);
2830                y = bounds.top + (int) (bounds.height() * 0.5f);
2831                y = y + (int) ((labelHeight - _modifierFontDescent) * 0.5f);
2832
2833                ti.setLocation(Math.round(x), Math.round(y));
2834                arrMods.add(ti);
2835            }
2836            else if(basicID.equals("WAS-PLT---P----"))//tropopause Low
2837            {
2838                strText = "X?";
2839                if(modX != null)
2840                    strText = modX;
2841
2842                ti = new TextInfo(strText, 0, 0, _modifierFont);
2843                labelWidth = Math.round(ti.getTextBounds().width());
2844                //One modifier symbols and modifier goes in center
2845                x = bounds.left + (int) (bounds.width() * 0.5f);
2846                x = x - (int) (labelWidth * 0.5f);
2847                y = bounds.top + (int) (bounds.height() * 0.5f);
2848                y = y - descent;
2849
2850                ti.setLocation(Math.round(x), Math.round(y));
2851                arrMods.add(ti);
2852            }
2853            else if(basicID.equals("WAS-PHT---P----"))//tropopause High
2854            {
2855                strText = "X?";
2856                if(modX != null)
2857                    strText = modX;
2858
2859                ti = new TextInfo(strText, 0, 0, _modifierFont);
2860                labelWidth = Math.round(ti.getTextBounds().width());
2861                //One modifier symbols and modifier goes in center
2862                x = bounds.left + (int) (bounds.width() * 0.5f);
2863                x = x - (int) (labelWidth * 0.5f);
2864                y = bounds.top + (int) (bounds.height() * 0.5f);
2865                //y = y + (int) ((labelHeight * 0.5f) + (labelHeight/2));
2866                y = y + (int) (((labelHeight * 0.5f) - (labelHeight/2)) + labelHeight - descent);
2867
2868                ti.setLocation(Math.round(x), Math.round(y));
2869                arrMods.add(ti);
2870            }
2871        }
2872        // </editor-fold>
2873
2874        // <editor-fold defaultstate="collapsed" desc="DOM Arrow">
2875        Point[] domPoints = null;
2876        Rect domBounds = null;
2877        if (modifiers.indexOfKey(ModifiersTG.Q_DIRECTION_OF_MOVEMENT) >= 0
2878                && (basicID.equals("G*M*NZ----****X") ||//ground zero
2879                basicID.equals("G*M*NEB---****X") ||//biological
2880                basicID.equals("G*M*NEC---****X")))//chemical)
2881        {
2882            strText = modifiers.get(ModifiersTG.Q_DIRECTION_OF_MOVEMENT);
2883            if(strText != null && SymbolUtilities.isNumber(strText))
2884            {
2885                    float q = Float.parseFloat(strText);
2886                    Rect tempBounds = new Rect(bounds);
2887                    tempBounds.union(RectUtilities.getCenterX(bounds), yForY);
2888        
2889                    domPoints = createDOMArrowPoints(symbolID, tempBounds, ii.getCenterPoint(), q, false);
2890        
2891                    domBounds = RectUtilities.makeRect(domPoints[0].x, domPoints[0].y, 1, 1);
2892        
2893                    Point temp = null;
2894                    for (int i = 1; i < 6; i++)
2895                    {
2896                        temp = domPoints[i];
2897                        if (temp != null)
2898                        {
2899                            domBounds.union(temp.x, temp.y);
2900                        }
2901                    }
2902                    imageBounds.union(domBounds);
2903            }
2904        }
2905        // </editor-fold>
2906
2907        // <editor-fold defaultstate="collapsed" desc="Shift Points and Draw">
2908        Rect modifierBounds = null;
2909        if (arrMods != null && arrMods.size() > 0)
2910        {
2911
2912            //build modifier bounds/////////////////////////////////////////
2913            modifierBounds = arrMods.get(0).getTextOutlineBounds();
2914            int size = arrMods.size();
2915            TextInfo tempShape = null;
2916            for (int i = 1; i < size; i++)
2917            {
2918                tempShape = arrMods.get(i);
2919                modifierBounds.union(tempShape.getTextOutlineBounds());
2920            }
2921
2922        }
2923
2924        if (modifierBounds != null || domBounds != null)
2925        {
2926
2927            if (modifierBounds != null)
2928            {
2929                imageBounds.union(modifierBounds);
2930            }
2931            if (domBounds != null)
2932            {
2933                imageBounds.union(domBounds);
2934            }
2935
2936            //shift points if needed////////////////////////////////////////
2937            if (imageBounds.left < 0 || imageBounds.top < 0)
2938            {
2939                int shiftX = Math.abs(imageBounds.left);
2940                int shiftY = Math.abs(imageBounds.top);
2941
2942                //shift mobility points
2943                int size = arrMods.size();
2944                TextInfo tempShape = null;
2945                for (int i = 0; i < size; i++)
2946                {
2947                    tempShape = arrMods.get(i);
2948                    tempShape.shift(shiftX, shiftY);
2949                }
2950                modifierBounds.offset(shiftX, shiftY);
2951
2952                if (domBounds != null)
2953                {
2954                    for (int i = 0; i < 6; i++)
2955                    {
2956                        Point temp = domPoints[i];
2957                        if (temp != null)
2958                        {
2959                            temp.offset(shiftX, shiftY);
2960                        }
2961                    }
2962                    domBounds.offset(shiftX, shiftY);
2963                }
2964
2965                //shift image points
2966                centerPoint.offset(shiftX, shiftY);
2967                symbolBounds.offset(shiftX, shiftY);
2968                imageBounds.offset(shiftX, shiftY);
2969            }
2970
2971            //Render modifiers//////////////////////////////////////////////////
2972            Bitmap bmp = Bitmap.createBitmap(imageBounds.width(), imageBounds.height(), Config.ARGB_8888);
2973            Canvas ctx = new Canvas(bmp);
2974
2975            //render////////////////////////////////////////////////////////
2976            //draw original icon with potential modifiers.
2977            ctx.drawBitmap(ii.getImage(), symbolBounds.left, symbolBounds.top, null);
2978            //ctx.drawImage(ii.getImage(),imageBoundsOld.left,imageBoundsOld.top);
2979
2980            if (attributes.indexOfKey(MilStdAttributes.TextColor) >= 0)
2981            {
2982                textColor = SymbolUtilities.getColorFromHexString(attributes.get(MilStdAttributes.TextColor));
2983                if(alpha > -1)
2984                    textColor.setAlpha(alpha);
2985            }
2986            if (attributes.indexOfKey(MilStdAttributes.TextBackgroundColor) >= 0)
2987            {
2988                textBackgroundColor = SymbolUtilities.getColorFromHexString(attributes.get(MilStdAttributes.TextBackgroundColor));
2989                if(alpha > -1)
2990                    textBackgroundColor.setAlpha(alpha);
2991            }
2992
2993
2994            
2995            renderText(ctx, arrMods, textColor, textBackgroundColor);
2996
2997            newii = new ImageInfo(bmp, centerPoint, symbolBounds);
2998
2999            //draw DOM arrow
3000            if (domBounds != null)
3001            {
3002                drawDOMArrow(ctx, domPoints, alpha, lineColor);
3003            }
3004
3005            newii = new ImageInfo(bmp, centerPoint, symbolBounds);
3006
3007            // <editor-fold defaultstate="collapsed" desc="Cleanup">
3008            ctx = null;
3009            // </editor-fold>
3010
3011            return newii;
3012
3013        }
3014        else
3015        {
3016            return null;
3017        }
3018        // </editor-fold>
3019
3020    }
3021
3022    public static ImageInfo ProcessTGSPModifiers(ImageInfo ii, String symbolID, SparseArray<String> modifiers, SparseArray<String> attributes, Color lineColor)
3023    {
3024
3025        // <editor-fold defaultstate="collapsed" desc="Variables">
3026        int bufferXL = 6;
3027        int bufferXR = 4;
3028        int bufferY = 2;
3029        int bufferText = 2;
3030        int centerOffset = 1; //getCenterX/Y function seems to go over by a pixel
3031        int x = 0;
3032        int y = 0;
3033        int x2 = 0;
3034        int y2 = 0;
3035        int symStd = RS.getSymbologyStandard();
3036        int outlineOffset = RS.getTextOutlineWidth();
3037        int labelHeight = 0;
3038        int labelWidth = 0;
3039        int alpha = -1;
3040        ImageInfo newii = null;
3041        
3042        Color textColor = lineColor;
3043        Color textBackgroundColor = null;
3044
3045        ArrayList<TextInfo> arrMods = new ArrayList<TextInfo>();
3046        boolean duplicate = false;
3047
3048        if (attributes.indexOfKey(MilStdAttributes.SymbologyStandard) >= 0)
3049        {
3050            symStd = Integer.parseInt(attributes.get(MilStdAttributes.SymbologyStandard));
3051        }
3052        if (attributes.indexOfKey(MilStdAttributes.Alpha) >= 0)
3053        {
3054            alpha = Integer.parseInt(attributes.get(MilStdAttributes.Alpha));
3055        }
3056
3057        Rect bounds = new Rect(ii.getSymbolBounds());
3058        Rect symbolBounds = new Rect(ii.getSymbolBounds());
3059        Point centerPoint = new Point(ii.getCenterPoint());
3060        Rect imageBounds = new Rect(ii.getImageBounds());
3061
3062        centerPoint = new Point(Math.round(ii.getCenterPoint().x), Math.round(ii.getCenterPoint().y));
3063
3064        boolean byLabelHeight = false;
3065
3066        labelHeight = Math.round(_modifierFontHeight + 0.5f);
3067        int maxHeight = (symbolBounds.height());
3068        if ((labelHeight * 3) > maxHeight)
3069        {
3070            byLabelHeight = true;
3071        }
3072
3073        int descent = (int) (_modifierFontDescent + 0.5f);
3074        int yForY = -1;
3075
3076        Rect labelBounds1 = null;//text.getPixelBounds(null, 0, 0);
3077        Rect labelBounds2 = null;
3078        String strText = "";
3079        String strText1 = "";
3080        String strText2 = "";
3081        TextInfo text1 = null;
3082        TextInfo text2 = null;
3083
3084        String basicID = SymbolUtilities.getBasicSymbolID(symbolID);
3085
3086        if (outlineOffset > 2)
3087        {
3088            outlineOffset = ((outlineOffset - 1) / 2);
3089        }
3090        else
3091        {
3092            outlineOffset = 0;
3093        }
3094
3095        /*bufferXL += outlineOffset;
3096         bufferXR += outlineOffset;
3097         bufferY += outlineOffset;
3098         bufferText += outlineOffset;*/
3099        // </editor-fold>
3100        // <editor-fold defaultstate="collapsed" desc="Process Modifiers">
3101        TextInfo ti = null;
3102
3103        {
3104            if (modifiers.indexOfKey(ModifiersTG.N_HOSTILE) >= 0)
3105            {
3106                strText = modifiers.get(ModifiersTG.N_HOSTILE);
3107                if(strText != null)
3108                {
3109                        ti = new TextInfo(strText, 0, 0, _modifierFont);
3110        
3111                        x = bounds.left + bounds.width() + bufferXR;
3112        
3113                        if (!byLabelHeight)
3114                        {
3115                            y = ((bounds.height() / 3) * 2);//checkpoint, get box above the point
3116                            y = bounds.top + y;
3117                        }
3118                        else
3119                        {
3120                            //y = ((labelHeight + bufferText) * 3);
3121                            //y = bounds.y + y - descent;
3122                            y = bounds.top + bounds.height();
3123                        }
3124        
3125                        ti.setLocation(x, y);
3126                        arrMods.add(ti);
3127                }
3128
3129            }
3130            if (modifiers.indexOfKey(ModifiersTG.H_ADDITIONAL_INFO_1) >= 0)
3131            {
3132                strText = modifiers.get(ModifiersTG.H_ADDITIONAL_INFO_1);
3133                if(strText != null)
3134                {
3135                        ti = new TextInfo(strText, 0, 0, _modifierFont);
3136                        labelWidth = Math.round(ti.getTextBounds().width());
3137        
3138                        x = bounds.left + (int) (bounds.width() * 0.5f);
3139                        x = x - (int) (labelWidth * 0.5f);
3140                        y = bounds.top - descent;
3141        
3142                        ti.setLocation(x, y);
3143                        arrMods.add(ti);
3144                }
3145            }
3146            if (modifiers.indexOfKey(ModifiersTG.H1_ADDITIONAL_INFO_2) >= 0)
3147            {
3148                strText = modifiers.get(ModifiersTG.H1_ADDITIONAL_INFO_2);
3149                if(strText != null)
3150                {
3151                        ti = new TextInfo(strText, 0, 0, _modifierFont);
3152                        labelWidth = Math.round(ti.getTextBounds().width());
3153        
3154                        x = bounds.left + (int) (bounds.width() * 0.5);
3155                        x = x - (int) (labelWidth * 0.5);
3156                        y = bounds.top + labelHeight + (int) (bounds.height() * 0.2);
3157        
3158                        ti.setLocation(x, y);
3159                        arrMods.add(ti);
3160                }
3161            }
3162            if (modifiers.indexOfKey(ModifiersTG.W_DTG_1) >= 0)
3163            {
3164                strText = modifiers.get(ModifiersTG.W_DTG_1);
3165                if(strText != null)
3166                {
3167                        ti = new TextInfo(strText, 0, 0, _modifierFont);
3168                        labelWidth = Math.round(ti.getTextBounds().width());
3169        
3170                        x = bounds.left - labelWidth - bufferXL;
3171                        y = bounds.top + labelHeight - descent;
3172        
3173                        ti.setLocation(x, y);
3174                        arrMods.add(ti);
3175                }
3176            }
3177            if (modifiers.indexOfKey(ModifiersTG.W1_DTG_2) >= 0)
3178            {
3179                strText = modifiers.get(ModifiersTG.W1_DTG_2);
3180                if(strText != null)
3181                {
3182                        ti = new TextInfo(strText, 0, 0, _modifierFont);
3183                        labelWidth = Math.round(ti.getTextBounds().width());
3184        
3185                        x = bounds.left - labelWidth - bufferXL;
3186        
3187                        y = ((labelHeight - descent + bufferText) * 2);
3188                        y = bounds.top + y;
3189        
3190                        ti.setLocation(x, y);
3191                        arrMods.add(ti);
3192                }
3193            }
3194            if (modifiers.indexOfKey(ModifiersTG.T_UNIQUE_DESIGNATION_1) >= 0)
3195            {
3196                strText = modifiers.get(ModifiersTG.T_UNIQUE_DESIGNATION_1);
3197                if(strText != null)
3198                {
3199                        ti = new TextInfo(strText, 0, 0, _modifierFont);
3200        
3201                        x = bounds.left + bounds.width() + bufferXR;
3202                        y = bounds.top + labelHeight - descent;
3203        
3204                        ti.setLocation(x, y);
3205                        arrMods.add(ti);
3206                }
3207            }
3208            if ((modifiers.indexOfKey(ModifiersTG.T1_UNIQUE_DESIGNATION_2) >= 0) &&//T1
3209                    (basicID.equals("G*O*ES----****X") || //emergency distress call
3210                    basicID.equals("G*S*PP----****X") || //medevac pick-up point
3211                    basicID.equals("G*S*PX----****X")))//ambulance exchange point
3212            {
3213                strText = modifiers.get(ModifiersTG.T1_UNIQUE_DESIGNATION_2);
3214                if(strText != null)
3215                {
3216                        ti = new TextInfo(strText, 0, 0, _modifierFont);
3217                        labelWidth = Math.round(ti.getTextBounds().width());
3218        
3219                        //points
3220                        x = bounds.left + (int) (bounds.width() * 0.5);
3221                        x = x - (int) (labelWidth * 0.5);
3222                        //y = bounds.y + (bounds.height * 0.5);
3223        
3224                        y = (int) ((bounds.height() * 0.60));//633333333
3225                        y = bounds.top + y;
3226        
3227                        ti.setLocation(x, y);
3228                        arrMods.add(ti);
3229                }
3230            }
3231
3232        }
3233
3234        // </editor-fold>
3235        // <editor-fold defaultstate="collapsed" desc="Shift Points and Draw">
3236        Rect modifierBounds = null;
3237        if (arrMods != null && arrMods.size() > 0)
3238        {
3239
3240            //build modifier bounds/////////////////////////////////////////
3241            modifierBounds = arrMods.get(0).getTextOutlineBounds();
3242            int size = arrMods.size();
3243            TextInfo tempShape = null;
3244            for (int i = 1; i < size; i++)
3245            {
3246                tempShape = arrMods.get(i);
3247                modifierBounds.union(tempShape.getTextOutlineBounds());
3248            }
3249
3250        }
3251
3252        if (modifierBounds != null)
3253        {
3254
3255            imageBounds.union(modifierBounds);
3256
3257            //shift points if needed////////////////////////////////////////
3258            if (imageBounds.left < 0 || imageBounds.top < 0)
3259            {
3260                int shiftX = Math.abs(imageBounds.left);
3261                int shiftY = Math.abs(imageBounds.top);
3262
3263                //shift mobility points
3264                int size = arrMods.size();
3265                TextInfo tempShape = null;
3266                for (int i = 0; i < size; i++)
3267                {
3268                    tempShape = arrMods.get(i);
3269                    tempShape.shift(shiftX, shiftY);
3270                }
3271                modifierBounds.offset(shiftX, shiftY);
3272
3273                //shift image points
3274                centerPoint.offset(shiftX, shiftY);
3275                symbolBounds.offset(shiftX, shiftY);
3276                imageBounds.offset(shiftX, shiftY);
3277            }
3278
3279            //Render modifiers//////////////////////////////////////////////////
3280            Bitmap bmp = Bitmap.createBitmap(imageBounds.width(), imageBounds.height(), Config.ARGB_8888);
3281            Canvas ctx = new Canvas(bmp);
3282
3283            //draw original icon with potential modifiers.
3284            ctx.drawBitmap(ii.getImage(), symbolBounds.left, symbolBounds.top, null);
3285            //ctx.drawImage(ii.getImage(),imageBoundsOld.left,imageBoundsOld.top);
3286
3287            if (attributes.indexOfKey(MilStdAttributes.TextColor) >= 0)
3288            {
3289                textColor = SymbolUtilities.getColorFromHexString(attributes.get(MilStdAttributes.TextColor));
3290                if(alpha > -1)
3291                    textColor.setAlpha(alpha);
3292            }
3293            if (attributes.indexOfKey(MilStdAttributes.TextBackgroundColor) >= 0)
3294            {
3295                textBackgroundColor = SymbolUtilities.getColorFromHexString(attributes.get(MilStdAttributes.TextBackgroundColor));
3296                if(alpha > -1)
3297                    textBackgroundColor.setAlpha(alpha);
3298            }
3299
3300
3301            renderText(ctx, arrMods, textColor, textBackgroundColor);
3302
3303            newii = new ImageInfo(bmp, centerPoint, symbolBounds);
3304
3305            // <editor-fold defaultstate="collapsed" desc="Cleanup">
3306            ctx = null;
3307
3308            // </editor-fold>
3309        }
3310        // </editor-fold>
3311        return newii;
3312
3313    }
3314
3315    private static void renderText(Canvas ctx, ArrayList<TextInfo> tiArray, Color color, Color backgroundColor)
3316    {
3317        ModifierRenderer.renderText(ctx, (TextInfo[]) tiArray.toArray(new TextInfo[0]), color, backgroundColor);
3318    }
3319
3320    /**
3321     * 
3322     * @param ctx
3323     * @param tiArray
3324     * @param color
3325     * @param backgroundColor 
3326     */
3327    public static void renderText(Canvas ctx, TextInfo[] tiArray, Color color, Color backgroundColor)
3328    {
3329        /*for (TextInfo textInfo : tiArray) 
3330         {
3331         ctx.drawText(textInfo.getText(), textInfo.getLocation().x, textInfo.getLocation().y, _modifierFont);   
3332         }*/
3333
3334        int size = tiArray.length;
3335
3336        int tbm = RS.getTextBackgroundMethod();
3337        int outlineWidth = RS.getTextOutlineWidth();
3338
3339        if (color == null)
3340        {
3341            color = Color.BLACK;
3342        }
3343
3344        Color outlineColor = null;
3345        
3346        if(backgroundColor != null)
3347            outlineColor = backgroundColor;
3348        else
3349            outlineColor = RendererUtilities.getIdealOutlineColor(color);
3350
3351        try {
3352
3353            if (tbm == RendererSettings.TextBackgroundMethod_OUTLINE_QUICK)
3354            {
3355                //draw text outline
3356                synchronized (_ModifierFontMutex) {
3357                    _modifierFont.setStyle(Style.FILL);
3358                    _modifierFont.setStrokeWidth(RS.getTextOutlineWidth());
3359                    _modifierFont.setColor(outlineColor.toInt());
3360                    if (outlineWidth > 0) {
3361                        for (int i = 0; i < size; i++) {
3362                            TextInfo textInfo = tiArray[i];
3363                            if (outlineWidth > 0) {
3364                                for (int j = 1; j <= outlineWidth; j++) {
3365                                    if (j % 2 == 1) {
3366                                        ctx.drawText(textInfo.getText(), textInfo.getLocation().x - j, textInfo.getLocation().y, _modifierFont);
3367                                        ctx.drawText(textInfo.getText(), textInfo.getLocation().x + j, textInfo.getLocation().y, _modifierFont);
3368                                        ctx.drawText(textInfo.getText(), textInfo.getLocation().x - j, textInfo.getLocation().y + j, _modifierFont);
3369                                        ctx.drawText(textInfo.getText(), textInfo.getLocation().x - j, textInfo.getLocation().y - j, _modifierFont);
3370                                    } else {
3371                                        ctx.drawText(textInfo.getText(), textInfo.getLocation().x - j, textInfo.getLocation().y - j, _modifierFont);
3372                                        ctx.drawText(textInfo.getText(), textInfo.getLocation().x + j, textInfo.getLocation().y - j, _modifierFont);
3373                                        ctx.drawText(textInfo.getText(), textInfo.getLocation().x - j, textInfo.getLocation().y + j, _modifierFont);
3374                                        ctx.drawText(textInfo.getText(), textInfo.getLocation().x + j, textInfo.getLocation().y + j, _modifierFont);
3375                                    }
3376
3377                                }
3378
3379                            }
3380
3381                        }
3382                    }
3383                    //draw text
3384                    _modifierFont.setColor(color.toInt());
3385
3386                    for (int j = 0; j < size; j++) {
3387                        TextInfo textInfo = tiArray[j];
3388                        ctx.drawText(textInfo.getText(), textInfo.getLocation().x, textInfo.getLocation().y, _modifierFont);
3389                /*Paint outline = new Paint();
3390                 outline.setStyle(Style.STROKE);
3391                 outline.setColor(Color.red.toInt());
3392                 outline.setAlpha(155);
3393                 outline.setStrokeWidth(1f);
3394                 ctx.drawRect(textInfo.getTextBounds(), outline);
3395                 outline.setColor(Color.blue.toInt());
3396                 ctx.drawRect(textInfo.getTextOutlineBounds(), outline);//*/
3397                    }
3398                }
3399            } else if (tbm == RendererSettings.TextBackgroundMethod_OUTLINE) {
3400                synchronized (_ModifierFontMutex) {
3401                    //draw text outline
3402                    //draw text outline
3403                    _modifierFont.setStyle(Style.STROKE);
3404                    _modifierFont.setStrokeWidth(RS.getTextOutlineWidth());
3405                    _modifierFont.setColor(outlineColor.toInt());
3406                    int i = 0;
3407
3408                    if (outlineWidth > 0) {
3409                        for (i = 0; i < size; i++) {
3410                            TextInfo textInfo = tiArray[i];
3411                            ctx.drawText(textInfo.getText(), textInfo.getLocation().x, textInfo.getLocation().y, _modifierFont);
3412                            //ErrorLogger.LogMessage("Draw outline " + textInfo.getText() + ", " + String.valueOf(i + 1) + " of " + String.valueOf(size) + "\n ", Level.WARNING, false);
3413                        }
3414                    }
3415
3416                    //draw text
3417                    _modifierFont.setColor(color.toInt());
3418                    _modifierFont.setStyle(Style.FILL);
3419
3420                    for (int j = 0; j < size; j++) {
3421                        TextInfo textInfo = tiArray[j];
3422                        ctx.drawText(textInfo.getText(), textInfo.getLocation().x, textInfo.getLocation().y, _modifierFont);
3423                    }
3424                }
3425
3426            } else if (tbm == RendererSettings.TextBackgroundMethod_COLORFILL) {
3427                synchronized (_ModifierFontMutex) {
3428                    Paint rectFill = new Paint();
3429                    rectFill.setStyle(Paint.Style.FILL);
3430                    rectFill.setColor(outlineColor.toARGB());
3431
3432
3433                    //draw rectangle
3434                    for (int k = 0; k < size; k++) {
3435                        TextInfo textInfo = tiArray[k];
3436                        ctx.drawRect(textInfo.getTextOutlineBounds(), rectFill);
3437                    }
3438                    //draw text
3439                    _modifierFont.setColor(color.toInt());
3440                    _modifierFont.setStyle(Style.FILL);
3441                    for (int j = 0; j < size; j++) {
3442                        TextInfo textInfo = tiArray[j];
3443                        ctx.drawText(textInfo.getText(), textInfo.getLocation().x, textInfo.getLocation().y, _modifierFont);
3444                    }
3445                }
3446            } else if (tbm == RendererSettings.TextBackgroundMethod_NONE)
3447            {
3448                synchronized (_ModifierFontMutex) {
3449                    _modifierFont.setColor(color.toInt());
3450                    _modifierFont.setStyle(Style.FILL);
3451                    for (int j = 0; j < size; j++) {
3452                        TextInfo textInfo = tiArray[j];
3453                        ctx.drawText(textInfo.getText(), textInfo.getLocation().x, textInfo.getLocation().y, _modifierFont);
3454                    }
3455                }
3456            }
3457        }
3458        catch(Exception exc)
3459        {
3460            ErrorLogger.LogException("ModifierRenderer","RenderText",exc);
3461        }
3462    }
3463
3464    public static boolean hasDisplayModifiers(String symbolID, SparseArray<String> modifiers)
3465    {
3466        boolean hasModifiers = false;
3467        char scheme = symbolID.charAt(0);
3468        char status = symbolID.charAt(3);
3469        char affiliation = symbolID.charAt(1);
3470        if (scheme != 'W')
3471        {
3472            if (scheme != 'G' && (SymbolUtilities.isEMSNaturalEvent(symbolID) == false))
3473            {
3474                switch (status)
3475                {
3476                    case 'C':
3477                    case 'D':
3478                    case 'X':
3479                    case 'F':
3480                        hasModifiers = true;
3481
3482                    default:
3483                        break;
3484                }
3485
3486                if ((symbolID.substring(10, 12).equals("--") == false && symbolID.substring(10, 12).equals("**") == false) || modifiers.indexOfKey(ModifiersUnits.Q_DIRECTION_OF_MOVEMENT) >= 0)
3487                {
3488                    hasModifiers = true;
3489                }
3490
3491                if(SymbolUtilities.isHQ(symbolID))
3492                    hasModifiers = true;
3493            }
3494            else
3495            {
3496                if (SymbolUtilities.isNBC(symbolID) == true && modifiers.indexOfKey(ModifiersTG.Q_DIRECTION_OF_MOVEMENT) >= 0)
3497                {
3498                    hasModifiers = true;
3499                }
3500            }
3501
3502        }
3503
3504        return hasModifiers;
3505    }
3506
3507    public static boolean hasTextModifiers(String symbolID, SparseArray<String> modifiers, SparseArray<String> attributes)
3508    {
3509
3510        int symStd = RS.getSymbologyStandard();
3511        if (attributes.indexOfKey(MilStdAttributes.SymbologyStandard) >= 0)
3512        {
3513            symStd = Integer.parseInt(attributes.get(MilStdAttributes.SymbologyStandard));
3514        }
3515        char scheme = symbolID.charAt(0);
3516        if(scheme == 'W')
3517        {
3518            if(symbolID.equals("WAS-WSF-LVP----") || //freezing level
3519                    symbolID.equals("WAS-PHT---P----") || //tropopause high
3520                    symbolID.equals("WAS-PLT---P----") || //tropopause low
3521                    symbolID.equals("WAS-WST-LVP----")) ////tropopause level
3522                return true;
3523            else
3524                return false;
3525        }
3526        if (scheme == 'G')
3527        {
3528            String basic = SymbolUtilities.getBasicSymbolIDStrict(symbolID);
3529            SymbolDef sd = SymbolDefTable.getInstance().getSymbolDef(basic, symStd);
3530            String expr = "\\.";
3531            String mods[] = sd.getModifiers().split(expr);
3532
3533            for(int lcv = 0; lcv < mods.length; lcv++)
3534            {
3535                if(modifiers.indexOfKey(ModifiersTG.getModifierKey(mods[lcv])) >= 0)
3536                    return true;
3537            }
3538            return false;
3539        }
3540        else if (SymbolUtilities.isEMSNaturalEvent(symbolID) == false)
3541        {
3542
3543            if (SymbolUtilities.getUnitAffiliationModifier(symbolID, symStd) != null)
3544            {
3545                return true;
3546            }
3547
3548            if (SymbolUtilities.hasValidCountryCode(symbolID))
3549            {
3550                return true;
3551            }
3552
3553            if (SymbolUtilities.isEMSNaturalEvent(symbolID))
3554            {
3555                return false;
3556            }
3557
3558            if (modifiers.indexOfKey(ModifiersUnits.Q_DIRECTION_OF_MOVEMENT) >= 0)
3559            {
3560                if (modifiers.size() > 1)
3561                {
3562                    return true;
3563                }
3564            }
3565            else if (modifiers.size() > 0)
3566            {
3567                return true;
3568            }
3569        }
3570        return false;
3571    }
3572
3573}