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