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.equals("25130100")) 105 Log.e("action point",id);//*/ 106 107 //read 2nd line to get SVG 108 svg = br.readLine(); 109 110 lookup.put(id, new SVGInfo(id, bbox, svg)); 111 112 //read next line for next loop 113 line = br.readLine(); 114 } 115 _initCalled = true; 116 } 117 catch(IOException ioe) 118 { 119 System.out.println(ioe.getMessage()); 120 } 121 catch(Exception e) 122 { 123 System.out.println(e.getMessage()); 124 } 125 } 126 127 /** 128 * 129 * @param id 130 * @param version 131 * @return 132 */ 133 public SVGInfo getSVGLInfo(String id, int version) 134 { 135 if(version >= SymbolID.Version_2525E) 136 { 137 if (_SVGLookupE.containsKey(id)) 138 return _SVGLookupE.get(id); 139 } 140 else 141 { 142 if (_SVGLookupD.containsKey(id)) 143 return _SVGLookupD.get(id); 144 } 145 146 return null; 147 } 148 149 public SVGInfo getSVGOctagon() 150 { 151 return _SVGLookupD.getOrDefault("octagon", null); 152 } 153 154 public static String getFrameID(String symbolID) 155 { 156 //SIDC positions 3_456_7 157 // String frameID = symbolID.charAt(2) + "_" + symbolID.substring(3, 6) + "_" + symbolID.charAt(6); 158 159 String frameID = null; 160 String ss; 161 int affiliation = SymbolID.getAffiliation(symbolID); 162 int status = SymbolID.getStatus(symbolID); 163 //Some affiliations are always dashed and only have one SVG for status with a value of 0 164 if(affiliation == SymbolID.StandardIdentity_Affiliation_Pending || 165 affiliation == SymbolID.StandardIdentity_Affiliation_AssumedFriend || 166 affiliation == SymbolID.StandardIdentity_Affiliation_Suspect_Joker) 167 { 168 // "When the frame is assumed friend, suspect, or pending, the status shall not be displayed." 169 status = 0; 170 } 171 if(status > 1) // Anything above 1 for status means present for the frame 172 status = 0; 173 174 int context = SymbolID.getContext(symbolID); 175 //they didn't make duplicate frame so I have to change the number for 176 //the lookup to work. 177 178 if(SymbolID.getVersion(symbolID) < SymbolID.Version_2525E)//2525Dch1 or less 179 { 180 switch(SymbolID.getSymbolSet(symbolID)) 181 { 182 case 01: //Air 183 case 02: //Air Missile 184 case 51: //Air SIGINT 185 ss = "01"; 186 break; 187 case 05: //Space 188 case 06: //Space Missile 189 case 50: //Space SIGINT 190 ss = "05"; 191 break; 192 case 10: //Land Unit 193 case 11://Land Civilian Unit/Org 194 ss = "10"; 195 break; 196 case 15://Land Equipment 197 case 52://Land SigInt 198 case 53://Sea Surface SIGINT 199 ss = "30"; 200 break; 201 case 30://Sea Surface 202 ss = "30"; 203 if(SymbolID.getEntityCode(symbolID)==150000) 204 return "octagon";//this symbol has no frame and a size of 1L x 1L. 205 break; 206 case 20: //Land Installation 207 ss = "20"; 208 break; 209 case SymbolID.SymbolSet_DismountedIndividuals: //Dismounted Individuals 210 ss = "27"; 211 break; 212 case 35: //Sea Subsurface 213 case 36: //Mine Warfare 214 case 54: //Sea Subsurface SigInt 215 ss = "35"; 216 break; 217 case 40: //Activities/Events 218 ss = "40"; 219 break; 220 case 60: //Cyberspace 221 ss = "60"; //No cyberspace SVG frame at the moment so setting to activities 222 break; 223 default: 224 ss = "00"; 225 226 if(context == SymbolID.StandardIdentity_Context_Exercise && affiliation > SymbolID.StandardIdentity_Affiliation_Unknown) 227 { 228 //really there are no unknown exercise symbols outside of pending and unknown 229 //default to unknown 230 affiliation = SymbolID.StandardIdentity_Affiliation_Unknown; 231 } 232 } 233 frameID = context + "_" + affiliation + ss + "_" + status; 234 } 235 else//2525E or above 236 { 237 char frameShape = SymbolID.getFrameShape(symbolID); 238 if(frameShape==SymbolID.FrameShape_Unknown) 239 { 240 241 /*if(SymbolID.getSymbolSet(symbolID) != SymbolID.SymbolSet_SignalsIntelligence) 242 {//get frame shape associated with symbol set 243 frameShape=SymbolID.getDefaultFrameShape(symbolID); 244 }//*/ 245 frameShape=SymbolID.getDefaultFrameShape(symbolID); 246 if(context == SymbolID.StandardIdentity_Context_Exercise && 247 SymbolID.getSymbolSet(symbolID) == SymbolID.SymbolSet_Unknown && 248 affiliation > SymbolID.StandardIdentity_Affiliation_Unknown) 249 { 250 //really there are no unknown exercise symbols outside pending and unknown affiliations 251 //default to unknown 252 affiliation = SymbolID.StandardIdentity_Affiliation_Unknown; 253 } 254 } 255 if(SymbolID.getSymbolSet(symbolID)==SymbolID.SymbolSet_SeaSurface && 256 SymbolID.getEntityCode(symbolID)==150000 && //Own Ship 257 (frameShape == SymbolID.FrameShape_LandEquipment_SeaSurface || frameShape == SymbolID.FrameShape_Unknown)) 258 { 259 return "octagon"; 260 } 261 frameID = context + "_" + affiliation + frameShape + "_" + status; 262 } 263 return frameID; 264 } 265 266 public static String getMainIconID(String symbolID) 267 { 268 //SIDC positions 5-6 + 11-16 269 String mainIconID = symbolID.substring(4, 6) + symbolID.substring(10, 16); 270 int ss = SymbolID.getSymbolSet(symbolID); 271 272 if(ss == SymbolID.SymbolSet_MineWarfare) 273 { 274 if(RendererSettings.getInstance().getSeaMineRenderMethod() == RendererSettings.SeaMineRenderMethod_ALT || 275 mainIconID.equals("36110600") || mainIconID.equals("36110700")) 276 { 277 mainIconID += "_a"; 278 } 279 } 280 else if(ss == SymbolID.SymbolSet_LandUnit) 281 { 282 switch(SymbolID.getEntityCode(symbolID)) 283 { 284 case 111000: 285 case 111001: 286 case 111002: 287 case 111003: 288 case 111004: 289 case 111005: 290 case 120100: 291 case 120400: 292 case 120401: 293 case 120402: 294 case 120501: 295 case 120502: 296 case 120601: 297 case 120801: 298 case 121100: 299 case 121101: 300 case 121102: 301 case 121103: 302 case 121104: 303 case 121105: 304 case 121106: 305 case 121300: 306 case 121301: 307 case 121302: 308 case 121303: 309 case 121802: 310 case 130100: 311 case 130101: 312 case 130102: 313 case 130103: 314 case 130200: 315 case 130302: 316 case 140102: 317 case 140103: 318 case 140104: 319 case 140105: 320 case 140702: 321 case 140703: 322 case 141702: 323 case 150504: 324 case 150800: 325 case 160200: 326 case 161200: 327 case 161300: 328 case 161400: 329 case 161700: 330 case 161800: 331 case 161900: 332 case 162000: 333 case 162100: 334 case 162200: 335 case 163400: 336 case 163700: 337 case 163800: 338 case 163900: 339 case 164000: 340 case 164100: 341 case 164200: 342 case 164300: 343 case 164400: 344 case 164500: 345 case 164600: 346 case 165000://NATO Only 347 //do thing to append correct number 348 mainIconID += getPostFixForIcon(symbolID); 349 break; 350 default: 351 break; 352 } 353 354 } 355 else if(ss == SymbolID.SymbolSet_LandEquipment) 356 { 357 switch (SymbolID.getEntityCode(symbolID)) 358 { 359 case 120111: 360 //do thing to append correct number 361 mainIconID += getPostFixForIcon(symbolID); 362 break; 363 default: 364 break; 365 } 366 } 367 else if(ss == SymbolID.SymbolSet_LandInstallation) 368 { 369 switch (SymbolID.getEntityCode(symbolID)) 370 { 371 case 110300: 372 case 111200: 373 case 120103: 374 case 120105: 375 case 120106: 376 case 120107: 377 case 120701: 378 case 120702: 379 //do thing to append correct number 380 mainIconID += getPostFixForIcon(symbolID); 381 break; 382 default: 383 break; 384 } 385 } 386 else if(ss == SymbolID.SymbolSet_Activities) 387 { 388 switch (SymbolID.getEntityCode(symbolID)) 389 { 390 case 110303: 391 case 130201: 392 case 131202: 393 case 131208: 394 //do thing to append correct number 395 mainIconID += getPostFixForIcon(symbolID); 396 break; 397 default: 398 break; 399 } 400 } 401 else if(ss == SymbolID.SymbolSet_Unknown) 402 mainIconID = "00000000";//unknown with question mark 403 else if (ss != SymbolID.SymbolSet_Air && 404 ss != SymbolID.SymbolSet_AirMissile && 405 ss != SymbolID.SymbolSet_Space && 406 ss != SymbolID.SymbolSet_SpaceMissile && 407 ss != SymbolID.SymbolSet_LandCivilianUnit_Organization && 408 ss != SymbolID.SymbolSet_DismountedIndividuals && 409 ss != SymbolID.SymbolSet_ControlMeasure && 410 ss != SymbolID.SymbolSet_SeaSurface && 411 ss != SymbolID.SymbolSet_SeaSubsurface && 412 ss != SymbolID.SymbolSet_Atmospheric && 413 ss != SymbolID.SymbolSet_Oceanographic && 414 ss != SymbolID.SymbolSet_MeteorologicalSpace && 415 ss != SymbolID.SymbolSet_SignalsIntelligence_Space && 416 ss != SymbolID.SymbolSet_SignalsIntelligence_Air && 417 ss != SymbolID.SymbolSet_SignalsIntelligence_Land && 418 ss != SymbolID.SymbolSet_SignalsIntelligence_SeaSurface && 419 ss != SymbolID.SymbolSet_SignalsIntelligence_SeaSubsurface && 420 ss != SymbolID.SymbolSet_CyberSpace) 421 { 422 mainIconID = "98100000";//invalid symbol, inverted question mark 423 } 424 425 return mainIconID; 426 } 427 428 429 private static String getPostFixForIcon(String symbolID) 430 { 431 int aff = SymbolID.getAffiliation(symbolID); 432 String pf = ""; 433 if(aff == SymbolID.StandardIdentity_Affiliation_Friend || 434 aff == SymbolID.StandardIdentity_Affiliation_AssumedFriend) 435 pf += "_1"; 436 else if(aff == SymbolID.StandardIdentity_Affiliation_Neutral) 437 pf += "_2"; 438 else if(aff == SymbolID.StandardIdentity_Affiliation_Hostile_Faker || 439 aff == SymbolID.StandardIdentity_Affiliation_Suspect_Joker) 440 pf += "_3"; 441 else if(aff == SymbolID.StandardIdentity_Affiliation_Unknown || 442 aff == SymbolID.StandardIdentity_Affiliation_Pending) 443 pf += "_0"; 444 445 return pf; 446 } 447 448 public static String getMod1ID(String symbolID) 449 { 450 String mod1ID = null; 451 452 453 if((SymbolID.getVersion(symbolID)>=SymbolID.Version_2525E) && symbolID.charAt(20) !='0') 454 {//2525E with Modifier 1 Indicator set 455 mod1ID = symbolID.substring(20,21) + symbolID.substring(16, 18) + "_1"; 456 } 457 else //2525D or no Modifier 1 Indicator set 458 { 459 //SIDC positions 5-6 + 17-18 + "1" 460 461 if(SymbolID.getEntity(symbolID)>=11) 462 mod1ID = symbolID.substring(4, 6) + symbolID.substring(16, 18) + "1"; 463 else 464 mod1ID = symbolID.substring(4, 6) + "001"; 465 466 if(SymbolID.getSymbolSet(symbolID) == SymbolID.SymbolSet_LandUnit) 467 { 468 switch(SymbolID.getModifier1(symbolID)) 469 { 470 case 98: 471 mod1ID += getPostFixForIcon(symbolID); 472 break; 473 default: 474 break; 475 } 476 } 477 } 478 return mod1ID; 479 } 480 481 public static String getMod2ID(String symbolID) 482 { 483 String mod2ID = null; 484 if((SymbolID.getVersion(symbolID)>=SymbolID.Version_2525E) && symbolID.charAt(21) != '0') 485 {//2525E with Modifier 1 Indicator set 486 mod2ID = symbolID.substring(21,22) + symbolID.substring(18, 20) + "_2"; 487 } 488 else //2525D or no Modifier 1 Indicator set 489 { 490 //SIDC positions 5-6 + 19-20 + "2" 491 if(SymbolID.getEntity(symbolID)>=11) 492 mod2ID = symbolID.substring(4, 6) + symbolID.substring(18, 20) + "2"; 493 else 494 mod2ID = symbolID.substring(4, 6) + "002"; 495 496 if(SymbolID.getSymbolSet(symbolID) == SymbolID.SymbolSet_LandUnit) 497 { 498 switch(SymbolID.getModifier2(symbolID)) 499 { 500 case 60: 501 case 62: 502 case 84: 503 case 89: 504 mod2ID += getPostFixForIcon(symbolID); 505 break; 506 default: 507 break; 508 } 509 } 510 } 511 return mod2ID; 512 } 513 514 public static String getEchelonAmplifier(String symbolID) 515 { 516 String amp = null; 517 int ver = SymbolID.getVersion(symbolID); 518 if (ver < SymbolID.Version_2525E) 519 { 520 amp = symbolID.charAt(3) + symbolID.substring(8,10); 521 } 522 else // >= 2525E 523 { 524 //This will eventually be different with the introduction of the frame shape modifier 525 amp = symbolID.charAt(3) + symbolID.substring(8,10); 526 } 527 return amp; 528 } 529 530 public static String getHQTFFD(String symbolID) { 531 String hqtffd = null; 532 int ver = SymbolID.getVersion(symbolID); 533 if (ver < SymbolID.Version_2525E) 534 { 535 hqtffd = symbolID.substring(3, 6) + symbolID.charAt(7); 536 } 537 else // >= 2525E 538 { 539 //This will eventually be different with the introduction of the frame shape modifier 540 hqtffd = symbolID.substring(3, 6) + symbolID.charAt(7); 541 } 542 return hqtffd; 543 } 544 545 public static String getOCA(String symbolID, boolean useSlash) 546 { 547 if(useSlash) 548 { 549 int status = SymbolID.getStatus(symbolID); 550 if(status == SymbolID.Status_Present_Damaged || status == SymbolID.Status_Present_Destroyed) 551 return String.valueOf(status); 552 else 553 return null; 554 } 555 else//get the bar 556 { 557 String oca = null; 558 int ver = SymbolID.getVersion(symbolID); 559 if(ver < SymbolID.Version_2525E) 560 { 561 oca = symbolID.substring(2,7) + "2"; 562 } 563 else // >= 2525E 564 { 565 //This will eventually be different with the introduction of the frame shape modifier 566 oca = symbolID.substring(2,7) + "2"; 567 } 568 return oca; 569 } 570 } 571 public static List<String> getAllKeys() 572 { 573 List<String> kl = new ArrayList(); 574 Set<String> keys = _SVGLookupD.keySet(); 575 for(String key: keys) { 576 //System.out.println(key); 577 kl.add(key); 578 } 579 return kl; 580 } 581 582 /** 583 * 584 * @param node 585 * <a href="https://stackoverflow.com/questions/4412848/xml-node-to-string-in-java"> 586 * https://stackoverflow.com/questions/4412848/xml-node-to-string-in-java</a> 587 */ 588 /*private static String nodeToString(Node node) 589 { 590 StringWriter sw = new StringWriter(); 591 try 592 { 593 Transformer t = TransformerFactory.newInstance().newTransformer(); 594 t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); 595 t.setOutputProperty(OutputKeys.INDENT, "yes"); 596 t.transform(new DOMSource(node), new StreamResult(sw)); 597 } 598 catch(TransformerException te) 599 { 600 System.out.println(te.getMessage()); 601 } 602 return sw.toString(); 603 }//*/ 604 605 /* 606 * For use only by MilStdIconRenderer.addCustomSymbol() 607 * @param svgInfo with the basic symbol id, bounds of the SVG, SVG group 608 * @param version like SymbolID.Version_2525E 609 * @return 610 */ 611 public boolean addCustomSymbol(SVGInfo svgInfo, int version) 612 { 613 boolean success = false; 614 try 615 { 616 String basicID = svgInfo.getID(); 617 if (version < SymbolID.Version_2525E) 618 { 619 if(SVGLookup._SVGLookupD.containsKey(svgInfo.getID()) == false) 620 { 621 SVGLookup._SVGLookupD.put(svgInfo.getID(),svgInfo); 622 } 623 } 624 else if (version == SymbolID.Version_2525E) 625 { 626 if(SVGLookup._SVGLookupE.containsKey(svgInfo.getID()) == false) 627 { 628 SVGLookup._SVGLookupE.put(svgInfo.getID(),svgInfo); 629 } 630 } 631 } 632 catch(Exception e) 633 { 634 ErrorLogger.LogException("SVGLookup","addCUstomSymbol",e); 635 } 636 return success; 637 } 638} 639 640