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 120400: 302 case 120401: 303 case 120402: 304 case 120501: 305 case 120502: 306 case 120601: 307 case 120801: 308 case 121100: 309 case 121101: 310 case 121102: 311 case 121103: 312 case 121104: 313 case 121105: 314 case 121106: 315 case 121107: 316 case 121300: 317 case 121301: 318 case 121302: 319 case 121303: 320 case 121304: 321 case 121802: 322 case 122100: 323 case 130100: 324 case 130101: 325 case 130102: 326 case 130103: 327 case 130200: 328 case 130302: 329 case 130303: 330 case 140102: 331 case 140103: 332 case 140104: 333 case 140105: 334 case 140702: 335 case 140703: 336 case 141702: 337 case 150504: 338 case 150800: 339 case 160200: 340 case 161200: 341 case 161300: 342 case 161400: 343 case 161700: 344 case 161800: 345 case 161900: 346 case 162000: 347 case 162100: 348 case 162200: 349 case 163400: 350 case 163700: 351 case 163800: 352 case 163900: 353 case 164000: 354 case 164100: 355 case 164200: 356 case 164300: 357 case 164400: 358 case 164500: 359 case 164600: 360 case 165000://NATO Only 361 //do thing to append correct number 362 mainIconID += getPostFixForIcon(symbolID); 363 break; 364 default: 365 break; 366 } 367 368 } 369 else if(ss == SymbolID.SymbolSet_LandEquipment) 370 { 371 switch (SymbolID.getEntityCode(symbolID)) 372 { 373 case 120111: 374 //do thing to append correct number 375 mainIconID += getPostFixForIcon(symbolID); 376 break; 377 default: 378 break; 379 } 380 } 381 else if(ss == SymbolID.SymbolSet_LandInstallation) 382 { 383 switch (SymbolID.getEntityCode(symbolID)) 384 { 385 case 110300: 386 case 111200: 387 case 120103: 388 case 120105: 389 case 120106: 390 case 120107: 391 case 120701: 392 case 120702: 393 //do thing to append correct number 394 mainIconID += getPostFixForIcon(symbolID); 395 break; 396 default: 397 break; 398 } 399 } 400 else if(ss == SymbolID.SymbolSet_Activities) 401 { 402 switch (SymbolID.getEntityCode(symbolID)) 403 { 404 case 110303: 405 case 130201: 406 case 131202: 407 case 131208: 408 //do thing to append correct number 409 mainIconID += getPostFixForIcon(symbolID); 410 break; 411 default: 412 break; 413 } 414 } 415 else if(ss == SymbolID.SymbolSet_Unknown) 416 mainIconID = "00000000";//unknown with question mark 417 else if (ss != SymbolID.SymbolSet_Air && 418 ss != SymbolID.SymbolSet_AirMissile && 419 ss != SymbolID.SymbolSet_Space && 420 ss != SymbolID.SymbolSet_SpaceMissile && 421 ss != SymbolID.SymbolSet_LandCivilianUnit_Organization && 422 ss != SymbolID.SymbolSet_DismountedIndividuals && 423 ss != SymbolID.SymbolSet_ControlMeasure && 424 ss != SymbolID.SymbolSet_SeaSurface && 425 ss != SymbolID.SymbolSet_SeaSubsurface && 426 ss != SymbolID.SymbolSet_Atmospheric && 427 ss != SymbolID.SymbolSet_Oceanographic && 428 ss != SymbolID.SymbolSet_MeteorologicalSpace && 429 ss != SymbolID.SymbolSet_SignalsIntelligence_Space && 430 ss != SymbolID.SymbolSet_SignalsIntelligence_Air && 431 ss != SymbolID.SymbolSet_SignalsIntelligence_Land && 432 ss != SymbolID.SymbolSet_SignalsIntelligence_SeaSurface && 433 ss != SymbolID.SymbolSet_SignalsIntelligence_SeaSubsurface && 434 ss != SymbolID.SymbolSet_CyberSpace) 435 { 436 mainIconID = "98100000";//invalid symbol, inverted question mark 437 } 438 439 return mainIconID; 440 } 441 442 443 private static String getPostFixForIcon(String symbolID) 444 { 445 int aff = SymbolID.getAffiliation(symbolID); 446 String pf = ""; 447 if(aff == SymbolID.StandardIdentity_Affiliation_Friend || 448 aff == SymbolID.StandardIdentity_Affiliation_AssumedFriend) 449 pf += "_1"; 450 else if(aff == SymbolID.StandardIdentity_Affiliation_Neutral) 451 pf += "_2"; 452 else if(aff == SymbolID.StandardIdentity_Affiliation_Hostile_Faker || 453 aff == SymbolID.StandardIdentity_Affiliation_Suspect_Joker) 454 pf += "_3"; 455 else if(aff == SymbolID.StandardIdentity_Affiliation_Unknown || 456 aff == SymbolID.StandardIdentity_Affiliation_Pending) 457 pf += "_0"; 458 459 return pf; 460 } 461 462 public static String getMod1ID(String symbolID) 463 { 464 String mod1ID = null; 465 466 467 if((SymbolID.getVersion(symbolID)>=SymbolID.Version_2525E) && symbolID.charAt(20) !='0') 468 {//2525E with Modifier 1 Indicator set 469 mod1ID = symbolID.substring(20,21) + symbolID.substring(16, 18) + "_1"; 470 if(mod1ID.equals("175_1")) 471 { 472 //TODO: as this is a common modifier, it can fit more than land units and will probably need its own function and more SVGs 473 mod1ID += getPostFixForIcon(symbolID); 474 } 475 } 476 else //2525D or no Modifier 1 Indicator set 477 { 478 //SIDC positions 5-6 + 17-18 + "1" 479 mod1ID = symbolID.substring(4, 6) + symbolID.substring(16, 18) + "1"; 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 mod2ID = symbolID.substring(4, 6) + symbolID.substring(18, 20) + "2"; 512 513 if(SymbolID.getSymbolSet(symbolID) == SymbolID.SymbolSet_LandUnit) 514 { 515 switch(SymbolID.getModifier2(symbolID)) 516 { 517 case 60: 518 case 62: 519 case 84: 520 case 89: 521 mod2ID += getPostFixForIcon(symbolID); 522 break; 523 default: 524 break; 525 } 526 } 527 } 528 return mod2ID; 529 } 530 531 public static String getEchelonAmplifier(String symbolID) 532 { 533 String amp = null; 534 int ver = SymbolID.getVersion(symbolID); 535 if (ver < SymbolID.Version_2525E) 536 { 537 amp = symbolID.charAt(3) + symbolID.substring(8,10); 538 } 539 else // >= 2525E 540 { 541 //This will eventually be different with the introduction of the frame shape modifier 542 amp = symbolID.charAt(3) + symbolID.substring(8,10); 543 } 544 return amp; 545 } 546 547 public static String getHQTFFD(String symbolID) { 548 String hqtffd = null; 549 int ver = SymbolID.getVersion(symbolID); 550 if (ver < SymbolID.Version_2525E) 551 { 552 hqtffd = symbolID.substring(3, 6) + symbolID.charAt(7); 553 } 554 else // >= 2525E 555 { 556 //This will eventually be different with the introduction of the frame shape modifier 557 hqtffd = symbolID.substring(3, 6) + symbolID.charAt(7); 558 } 559 return hqtffd; 560 } 561 562 public static String getOCA(String symbolID, boolean useSlash) 563 { 564 if(useSlash) 565 { 566 int status = SymbolID.getStatus(symbolID); 567 if(status == SymbolID.Status_Present_Damaged || status == SymbolID.Status_Present_Destroyed) 568 return String.valueOf(status); 569 else 570 return null; 571 } 572 else//get the bar 573 { 574 String oca = null; 575 int ver = SymbolID.getVersion(symbolID); 576 if(ver < SymbolID.Version_2525E) 577 { 578 oca = symbolID.substring(2,7) + "2"; 579 } 580 else // >= 2525E 581 { 582 //This will eventually be different with the introduction of the frame shape modifier 583 oca = symbolID.substring(2,7) + "2"; 584 } 585 return oca; 586 } 587 } 588 public static List<String> getAllKeys() 589 { 590 List<String> kl = new ArrayList(); 591 Set<String> keys = _SVGLookupD.keySet(); 592 for(String key: keys) { 593 //System.out.println(key); 594 kl.add(key); 595 } 596 return kl; 597 } 598 599 600 /* 601 * For use only by MilStdIconRenderer.addCustomSymbol() 602 * @param svgInfo with the basic symbol id, bounds of the SVG, SVG group 603 * @param version like SymbolID.Version_2525E 604 * @return 605 */ 606 public boolean addCustomSymbol(SVGInfo svgInfo, int version) 607 { 608 boolean success = false; 609 try 610 { 611 String basicID = svgInfo.getID(); 612 if (version < SymbolID.Version_2525E) 613 { 614 if(SVGLookup._SVGLookupD.containsKey(svgInfo.getID()) == false) 615 { 616 SVGLookup._SVGLookupD.put(svgInfo.getID(),svgInfo); 617 } 618 } 619 else if (version >= SymbolID.Version_2525E) 620 { 621 if(SVGLookup._SVGLookupE.containsKey(svgInfo.getID()) == false) 622 { 623 SVGLookup._SVGLookupE.put(svgInfo.getID(),svgInfo); 624 } 625 } 626 } 627 catch(Exception e) 628 { 629 ErrorLogger.LogException("SVGLookup","addCUstomSymbol",e); 630 } 631 return success; 632 } 633} 634 635