001package armyc2.c5isr.renderer.utilities; 002 003import android.content.Context; 004import android.graphics.RectF; 005 006import java.io.BufferedReader; 007import java.io.IOException; 008import java.io.InputStream; 009import java.io.InputStreamReader; 010import java.util.ArrayList; 011import java.util.HashMap; 012import java.util.List; 013import java.util.Map; 014import java.util.Set; 015 016 017import armyc2.c5isr.renderer.R; 018 019public class SVGLookup { 020 private static SVGLookup _instance = null; 021 private static Boolean _initCalled = false; 022 private static Map<String, SVGInfo> _SVGLookupD = null; 023 private static Map<String, SVGInfo> _SVGLookupE = null; 024 private String TAG = "SVGLookup"; 025 026 027 /* 028 * Holds SymbolDefs for all symbols. (basicSymbolID, Description, MinPoint, MaxPoints, etc...) Call 029 * getInstance(). 030 * 031 */ 032 private SVGLookup() { 033 // init(null); 034 // _initCalled=true; 035 } 036 037 public static synchronized SVGLookup getInstance() { 038 if (_instance == null) { 039 _instance = new SVGLookup(); 040 } 041 042 return _instance; 043 } 044 045 public final synchronized void init(Context context) 046 { 047 if (_initCalled == false) 048 { 049 _SVGLookupD = new HashMap<>(); 050 _SVGLookupE = new HashMap<>(); 051 052 try 053 { 054 InputStream isD = context.getResources().openRawResource(R.raw.svgd); 055 loadData(isD, SymbolID.Version_2525Dch1); 056 isD.close(); 057 058 InputStream isE = context.getResources().openRawResource(R.raw.svge); 059 loadData(isE, SymbolID.Version_2525E); 060 isE.close(); 061 062 _initCalled = true; 063 } 064 catch(Exception e) 065 { 066 System.out.println(e.getMessage()); 067 } 068 } 069 070 } 071 072 private void loadData(InputStream is, int version) 073 { 074 Map<String, SVGInfo> lookup; 075 if(version >= SymbolID.Version_2525E) 076 lookup = _SVGLookupE; 077 else 078 lookup = _SVGLookupD; 079 080 String[] temp = null; 081 String id = null; 082 RectF bbox = null; 083 String svg = null; 084 String delimiter = "~"; 085 086 try 087 { 088 BufferedReader br = new BufferedReader(new InputStreamReader(is)); 089 090 String line = br.readLine(); 091 092 while (line != null) 093 { 094 //parse first line 095 temp = line.split(delimiter); 096 id = temp[0]; 097 float left, top, width, height; 098 left = Float.parseFloat(temp[1]); 099 top = Float.parseFloat(temp[2]); 100 width = Float.parseFloat(temp[3]); 101 height = Float.parseFloat(temp[4]); 102 bbox = RectUtilities.makeRectF(left, top, width, height); 103 104 if(id.startsWith("461206"))//Hydrography Bottom Features 105 { 106 //grow bbox as android uses a different serif italic font than browsers and windows 107 bbox = RectUtilities.makeRectF((int)(left + (left * -0.04)), (int)(top + (top * -0.1)), (int)(width * 1.2), (int)(height * 1.1)); 108 } 109 /*if(id.equals("25130100")) 110 Log.e("action point",id);//*/ 111 112 //read 2nd line to get SVG 113 svg = br.readLine(); 114 115 lookup.put(id, new SVGInfo(id, bbox, svg)); 116 117 //read next line for next loop 118 line = br.readLine(); 119 } 120 _initCalled = true; 121 } 122 catch(IOException ioe) 123 { 124 System.out.println(ioe.getMessage()); 125 } 126 catch(Exception e) 127 { 128 System.out.println(e.getMessage()); 129 } 130 } 131 132 /** 133 * 134 * @param id 135 * @param version 136 * @return 137 */ 138 public SVGInfo getSVGLInfo(String id, int version) 139 { 140 if(version >= SymbolID.Version_2525E) 141 { 142 if (_SVGLookupE.containsKey(id)) 143 return _SVGLookupE.get(id); 144 } 145 else 146 { 147 if (_SVGLookupD.containsKey(id)) 148 return _SVGLookupD.get(id); 149 } 150 151 return null; 152 } 153 154 155 public static String getFrameID(String symbolID) 156 { 157 //SIDC positions 3_456_7 158 // String frameID = symbolID.charAt(2) + "_" + symbolID.substring(3, 6) + "_" + symbolID.charAt(6); 159 160 String frameID = null; 161 String ss; 162 int affiliation = SymbolID.getAffiliation(symbolID); 163 int status = SymbolID.getStatus(symbolID); 164 //Some affiliations are always dashed and only have one SVG for status with a value of 0 165 if(affiliation == SymbolID.StandardIdentity_Affiliation_Pending || 166 affiliation == SymbolID.StandardIdentity_Affiliation_AssumedFriend || 167 affiliation == SymbolID.StandardIdentity_Affiliation_Suspect_Joker) 168 { 169 // "When the frame is assumed friend, suspect, or pending, the status shall not be displayed." 170 status = 0; 171 } 172 if(status > 1) // Anything above 1 for status means present for the frame 173 status = 0; 174 175 int context = SymbolID.getContext(symbolID); 176 //they didn't make duplicate frame so I have to change the number for 177 //the lookup to work. 178 179 if(SymbolID.getVersion(symbolID) < SymbolID.Version_2525E)//2525Dch1 or less 180 { 181 switch(SymbolID.getSymbolSet(symbolID)) 182 { 183 case 01: //Air 184 case 02: //Air Missile 185 case 51: //Air SIGINT 186 ss = "01"; 187 break; 188 case 05: //Space 189 case 06: //Space Missile 190 case 50: //Space SIGINT 191 ss = "05"; 192 break; 193 case 10: //Land Unit 194 case 11://Land Civilian Unit/Org 195 ss = "10"; 196 break; 197 case 15://Land Equipment 198 case 52://Land SigInt 199 case 53://Sea Surface SIGINT 200 ss = "30"; 201 break; 202 case 30://Sea Surface 203 ss = "30"; 204 if(SymbolID.getEntityCode(symbolID)==150000) 205 return "octagon";//this symbol has no frame and a size of 1L x 1L. 206 break; 207 case 20: //Land Installation 208 ss = "20"; 209 break; 210 case SymbolID.SymbolSet_DismountedIndividuals: //Dismounted Individuals 211 ss = "27"; 212 break; 213 case 35: //Sea Subsurface 214 case 36: //Mine Warfare 215 case 54: //Sea Subsurface SigInt 216 ss = "35"; 217 break; 218 case 40: //Activities/Events 219 ss = "40"; 220 break; 221 case 60: //Cyberspace 222 ss = "60"; //No cyberspace SVG frame at the moment so setting to activities 223 break; 224 default: 225 ss = "00"; 226 227 if(context == SymbolID.StandardIdentity_Context_Exercise && affiliation > SymbolID.StandardIdentity_Affiliation_Unknown) 228 { 229 //really there are no unknown exercise symbols outside of pending and unknown 230 //default to unknown 231 affiliation = SymbolID.StandardIdentity_Affiliation_Unknown; 232 } 233 } 234 if(context == SymbolID.StandardIdentity_Context_Restricted_Target_Reality || context == SymbolID.StandardIdentity_Context_No_Strike_Entity_Reality) 235 context = SymbolID.StandardIdentity_Context_Reality; 236 frameID = context + "_" + affiliation + ss + "_" + status; 237 } 238 else//2525E or above 239 { 240 char frameShape = SymbolID.getFrameShape(symbolID); 241 if(frameShape==SymbolID.FrameShape_Unknown) 242 { 243 244 /*if(SymbolID.getSymbolSet(symbolID) != SymbolID.SymbolSet_SignalsIntelligence) 245 {//get frame shape associated with symbol set 246 frameShape=SymbolID.getDefaultFrameShape(symbolID); 247 }//*/ 248 frameShape=SymbolID.getDefaultFrameShape(symbolID); 249 if(context == SymbolID.StandardIdentity_Context_Exercise && 250 SymbolID.getSymbolSet(symbolID) == SymbolID.SymbolSet_Unknown && 251 affiliation > SymbolID.StandardIdentity_Affiliation_Unknown) 252 { 253 //really there are no unknown exercise symbols outside pending and unknown affiliations 254 //default to unknown 255 affiliation = SymbolID.StandardIdentity_Affiliation_Unknown; 256 } 257 } 258 if(SymbolID.getSymbolSet(symbolID)==SymbolID.SymbolSet_SeaSurface && 259 SymbolID.getEntityCode(symbolID)==150000 && //Own Ship 260 (frameShape == SymbolID.FrameShape_LandEquipment_SeaSurface || frameShape == SymbolID.FrameShape_Unknown)) 261 { 262 return "octagon"; 263 } 264 if(context == SymbolID.StandardIdentity_Context_Restricted_Target_Reality || context == SymbolID.StandardIdentity_Context_No_Strike_Entity_Reality) 265 context = SymbolID.StandardIdentity_Context_Reality; 266 frameID = context + "_" + affiliation + frameShape + "_" + status; 267 } 268 return frameID; 269 } 270 271 public static String getMainIconID(String symbolID) 272 { 273 //SIDC positions 5-6 + 11-16 274 String mainIconID = symbolID.substring(4, 6) + symbolID.substring(10, 16); 275 int ss = SymbolID.getSymbolSet(symbolID); 276 277 if(ss == SymbolID.SymbolSet_MineWarfare) 278 { 279 if(RendererSettings.getInstance().getSeaMineRenderMethod() == RendererSettings.SeaMineRenderMethod_ALT || 280 mainIconID.equals("36110600") || mainIconID.equals("36110700")) 281 { 282 mainIconID += "_a"; 283 } 284 } 285 else if(ss == SymbolID.SymbolSet_LandUnit) 286 { 287 switch(SymbolID.getEntityCode(symbolID)) 288 { 289 case 111000: 290 case 111001: 291 case 111002: 292 case 111003: 293 case 111004: 294 case 111005: 295 case 111500: 296 case 120100: 297 case 120400: 298 case 120401: 299 case 120402: 300 case 120501: 301 case 120502: 302 case 120601: 303 case 120801: 304 case 121100: 305 case 121101: 306 case 121102: 307 case 121103: 308 case 121104: 309 case 121105: 310 case 121106: 311 case 121107: 312 case 121300: 313 case 121301: 314 case 121302: 315 case 121303: 316 case 121304: 317 case 121802: 318 case 122100: 319 case 130100: 320 case 130101: 321 case 130102: 322 case 130103: 323 case 130200: 324 case 130302: 325 case 130303: 326 case 140102: 327 case 140103: 328 case 140104: 329 case 140105: 330 case 140702: 331 case 140703: 332 case 141702: 333 case 150504: 334 case 150800: 335 case 160200: 336 case 161200: 337 case 161300: 338 case 161400: 339 case 161700: 340 case 161800: 341 case 161900: 342 case 162000: 343 case 162100: 344 case 162200: 345 case 163400: 346 case 163700: 347 case 163800: 348 case 163900: 349 case 164000: 350 case 164100: 351 case 164200: 352 case 164300: 353 case 164400: 354 case 164500: 355 case 164600: 356 case 165000://NATO Only 357 //do thing to append correct number 358 mainIconID += getPostFixForIcon(symbolID); 359 break; 360 default: 361 break; 362 } 363 364 } 365 else if(ss == SymbolID.SymbolSet_LandEquipment) 366 { 367 switch (SymbolID.getEntityCode(symbolID)) 368 { 369 case 120111: 370 //do thing to append correct number 371 mainIconID += getPostFixForIcon(symbolID); 372 break; 373 default: 374 break; 375 } 376 } 377 else if(ss == SymbolID.SymbolSet_LandInstallation) 378 { 379 switch (SymbolID.getEntityCode(symbolID)) 380 { 381 case 110300: 382 case 111200: 383 case 120103: 384 case 120105: 385 case 120106: 386 case 120107: 387 case 120701: 388 case 120702: 389 //do thing to append correct number 390 mainIconID += getPostFixForIcon(symbolID); 391 break; 392 default: 393 break; 394 } 395 } 396 else if(ss == SymbolID.SymbolSet_Activities) 397 { 398 switch (SymbolID.getEntityCode(symbolID)) 399 { 400 case 110303: 401 case 130201: 402 case 131202: 403 case 131208: 404 //do thing to append correct number 405 mainIconID += getPostFixForIcon(symbolID); 406 break; 407 default: 408 break; 409 } 410 } 411 else if(ss == SymbolID.SymbolSet_Unknown) 412 mainIconID = "00000000";//unknown with question mark 413 else if (ss != SymbolID.SymbolSet_Air && 414 ss != SymbolID.SymbolSet_AirMissile && 415 ss != SymbolID.SymbolSet_Space && 416 ss != SymbolID.SymbolSet_SpaceMissile && 417 ss != SymbolID.SymbolSet_LandCivilianUnit_Organization && 418 ss != SymbolID.SymbolSet_DismountedIndividuals && 419 ss != SymbolID.SymbolSet_ControlMeasure && 420 ss != SymbolID.SymbolSet_SeaSurface && 421 ss != SymbolID.SymbolSet_SeaSubsurface && 422 ss != SymbolID.SymbolSet_Atmospheric && 423 ss != SymbolID.SymbolSet_Oceanographic && 424 ss != SymbolID.SymbolSet_MeteorologicalSpace && 425 ss != SymbolID.SymbolSet_SignalsIntelligence_Space && 426 ss != SymbolID.SymbolSet_SignalsIntelligence_Air && 427 ss != SymbolID.SymbolSet_SignalsIntelligence_Land && 428 ss != SymbolID.SymbolSet_SignalsIntelligence_SeaSurface && 429 ss != SymbolID.SymbolSet_SignalsIntelligence_SeaSubsurface && 430 ss != SymbolID.SymbolSet_CyberSpace) 431 { 432 mainIconID = "98100000";//invalid symbol, inverted question mark 433 } 434 435 return mainIconID; 436 } 437 438 439 private static String getPostFixForIcon(String symbolID) 440 { 441 int aff = SymbolID.getAffiliation(symbolID); 442 String pf = ""; 443 if(aff == SymbolID.StandardIdentity_Affiliation_Friend || 444 aff == SymbolID.StandardIdentity_Affiliation_AssumedFriend) 445 pf += "_1"; 446 else if(aff == SymbolID.StandardIdentity_Affiliation_Neutral) 447 pf += "_2"; 448 else if(aff == SymbolID.StandardIdentity_Affiliation_Hostile_Faker || 449 aff == SymbolID.StandardIdentity_Affiliation_Suspect_Joker) 450 pf += "_3"; 451 else if(aff == SymbolID.StandardIdentity_Affiliation_Unknown || 452 aff == SymbolID.StandardIdentity_Affiliation_Pending) 453 pf += "_0"; 454 455 return pf; 456 } 457 458 public static String getMod1ID(String symbolID) 459 { 460 String mod1ID = null; 461 462 463 if((SymbolID.getVersion(symbolID)>=SymbolID.Version_2525E) && symbolID.charAt(20) !='0') 464 {//2525E with Modifier 1 Indicator set 465 mod1ID = symbolID.substring(20,21) + symbolID.substring(16, 18) + "_1"; 466 if(mod1ID.equals("175_1")) 467 { 468 //TODO: as this is a common modifier, it can fit more than land units and will probably need its own function and more SVGs 469 mod1ID += getPostFixForIcon(symbolID); 470 } 471 } 472 else //2525D or no Modifier 1 Indicator set 473 { 474 //SIDC positions 5-6 + 17-18 + "1" 475 476 if(SymbolID.getEntity(symbolID)>=11) 477 mod1ID = symbolID.substring(4, 6) + symbolID.substring(16, 18) + "1"; 478 else 479 mod1ID = symbolID.substring(4, 6) + "001"; 480 481 if(SymbolID.getSymbolSet(symbolID) == SymbolID.SymbolSet_LandUnit) 482 { 483 switch(SymbolID.getModifier1(symbolID)) 484 { 485 case 98: 486 mod1ID += getPostFixForIcon(symbolID); 487 break; 488 default: 489 break; 490 } 491 } 492 } 493 return mod1ID; 494 } 495 496 public static String getMod2ID(String symbolID) 497 { 498 String mod2ID = null; 499 if((SymbolID.getVersion(symbolID)>=SymbolID.Version_2525E) && symbolID.charAt(21) != '0') 500 {//2525E with Modifier 1 Indicator set 501 mod2ID = symbolID.substring(21,22) + symbolID.substring(18, 20) + "_2"; 502 if(mod2ID.equals("131_2") || mod2ID.equals("134_2")) 503 { 504 //TODO: as this is a common modifier, it can fit more than land units and will probably need its own function and more SVGs 505 mod2ID += getPostFixForIcon(symbolID); 506 } 507 } 508 else //2525D or no Modifier 1 Indicator set 509 { 510 //SIDC positions 5-6 + 19-20 + "2" 511 if(SymbolID.getEntity(symbolID)>=11) 512 mod2ID = symbolID.substring(4, 6) + symbolID.substring(18, 20) + "2"; 513 else 514 mod2ID = symbolID.substring(4, 6) + "002"; 515 516 if(SymbolID.getSymbolSet(symbolID) == SymbolID.SymbolSet_LandUnit) 517 { 518 switch(SymbolID.getModifier2(symbolID)) 519 { 520 case 60: 521 case 62: 522 case 84: 523 case 89: 524 mod2ID += getPostFixForIcon(symbolID); 525 break; 526 default: 527 break; 528 } 529 } 530 } 531 return mod2ID; 532 } 533 534 public static String getEchelonAmplifier(String symbolID) 535 { 536 String amp = null; 537 int ver = SymbolID.getVersion(symbolID); 538 if (ver < SymbolID.Version_2525E) 539 { 540 amp = symbolID.charAt(3) + symbolID.substring(8,10); 541 } 542 else // >= 2525E 543 { 544 //This will eventually be different with the introduction of the frame shape modifier 545 amp = symbolID.charAt(3) + symbolID.substring(8,10); 546 } 547 return amp; 548 } 549 550 public static String getHQTFFD(String symbolID) { 551 String hqtffd = null; 552 int ver = SymbolID.getVersion(symbolID); 553 if (ver < SymbolID.Version_2525E) 554 { 555 hqtffd = symbolID.substring(3, 6) + symbolID.charAt(7); 556 } 557 else // >= 2525E 558 { 559 //This will eventually be different with the introduction of the frame shape modifier 560 hqtffd = symbolID.substring(3, 6) + symbolID.charAt(7); 561 } 562 return hqtffd; 563 } 564 565 public static String getOCA(String symbolID, boolean useSlash) 566 { 567 if(useSlash) 568 { 569 int status = SymbolID.getStatus(symbolID); 570 if(status == SymbolID.Status_Present_Damaged || status == SymbolID.Status_Present_Destroyed) 571 return String.valueOf(status); 572 else 573 return null; 574 } 575 else//get the bar 576 { 577 String oca = null; 578 int ver = SymbolID.getVersion(symbolID); 579 if(ver < SymbolID.Version_2525E) 580 { 581 oca = symbolID.substring(2,7) + "2"; 582 } 583 else // >= 2525E 584 { 585 //This will eventually be different with the introduction of the frame shape modifier 586 oca = symbolID.substring(2,7) + "2"; 587 } 588 return oca; 589 } 590 } 591 public static List<String> getAllKeys() 592 { 593 List<String> kl = new ArrayList(); 594 Set<String> keys = _SVGLookupD.keySet(); 595 for(String key: keys) { 596 //System.out.println(key); 597 kl.add(key); 598 } 599 return kl; 600 } 601 602 603 /* 604 * For use only by MilStdIconRenderer.addCustomSymbol() 605 * @param svgInfo with the basic symbol id, bounds of the SVG, SVG group 606 * @param version like SymbolID.Version_2525E 607 * @return 608 */ 609 public boolean addCustomSymbol(SVGInfo svgInfo, int version) 610 { 611 boolean success = false; 612 try 613 { 614 String basicID = svgInfo.getID(); 615 if (version < SymbolID.Version_2525E) 616 { 617 if(SVGLookup._SVGLookupD.containsKey(svgInfo.getID()) == false) 618 { 619 SVGLookup._SVGLookupD.put(svgInfo.getID(),svgInfo); 620 } 621 } 622 else if (version >= SymbolID.Version_2525E) 623 { 624 if(SVGLookup._SVGLookupE.containsKey(svgInfo.getID()) == false) 625 { 626 SVGLookup._SVGLookupE.put(svgInfo.getID(),svgInfo); 627 } 628 } 629 } 630 catch(Exception e) 631 { 632 ErrorLogger.LogException("SVGLookup","addCUstomSymbol",e); 633 } 634 return success; 635 } 636} 637 638