001package armyc2.c5isr.renderer; 002 003import android.graphics.Bitmap; 004import android.graphics.Bitmap.Config; 005import android.graphics.Canvas; 006import android.graphics.Paint; 007import android.graphics.Paint.FontMetrics; 008import android.graphics.Point; 009import android.graphics.PointF; 010import android.graphics.Rect; 011import android.graphics.RectF; 012import android.util.Log; 013import android.util.LruCache; 014 015import com.caverock.androidsvg.SVG; 016 017import java.util.HashMap; 018import java.util.Map; 019 020import armyc2.c5isr.renderer.utilities.Color; 021import armyc2.c5isr.renderer.utilities.DrawRules; 022import armyc2.c5isr.renderer.utilities.ErrorLogger; 023import armyc2.c5isr.renderer.utilities.ImageInfo; 024import armyc2.c5isr.renderer.utilities.MSInfo; 025import armyc2.c5isr.renderer.utilities.MSLookup; 026import armyc2.c5isr.renderer.utilities.MilStdAttributes; 027import armyc2.c5isr.renderer.utilities.Modifiers; 028import armyc2.c5isr.renderer.utilities.RectUtilities; 029import armyc2.c5isr.renderer.utilities.RendererSettings; 030import armyc2.c5isr.renderer.utilities.RendererUtilities; 031import armyc2.c5isr.renderer.utilities.SVGInfo; 032import armyc2.c5isr.renderer.utilities.SVGLookup; 033import armyc2.c5isr.renderer.utilities.SettingsChangedEvent; 034import armyc2.c5isr.renderer.utilities.SettingsChangedEventListener; 035import armyc2.c5isr.renderer.utilities.SymbolDimensionInfo; 036import armyc2.c5isr.renderer.utilities.SymbolID; 037import armyc2.c5isr.renderer.utilities.SymbolUtilities; 038 039public class SinglePointRenderer implements SettingsChangedEventListener 040{ 041 042 private final String TAG = "SinglePointRenderer"; 043 private static SinglePointRenderer _instance = null; 044 045 private final Object _SinglePointCacheMutex = new Object(); 046 private final Object _UnitCacheMutex = new Object(); 047 048 private final Object _modifierFontMutex = new Object(); 049 private Paint _modifierFont = new Paint(); 050 private Paint _modifierOutlineFont = new Paint(); 051 private float _modifierDescent = 2; 052 private float _modifierFontHeight = 10; 053 private int _deviceDPI = 72; 054 055 //private LruCache<String, ImageInfo> _unitCache = new LruCache<String, ImageInfo>(15); 056 //private LruCache<String, ImageInfo> _tgCache = new LruCache<String, ImageInfo>(7); 057 private LruCache<String, ImageInfo> _unitCache = new LruCache<String, ImageInfo>(1024); 058 private LruCache<String, ImageInfo> _tgCache = new LruCache<String, ImageInfo>(1024); 059 private final int maxMemory = (int) (Runtime.getRuntime().maxMemory());// / 1024); 060 private int cacheSize = 5;//RendererSettings.getInstance().getCacheSize() / 2; 061 private int maxCachedEntrySize = cacheSize / 5; 062 private boolean cacheEnabled = RendererSettings.getInstance().getCacheEnabled(); 063 064 private SinglePointRenderer() 065 { 066 RendererSettings.getInstance().addEventListener(this); 067 068 //get modifier font values. 069 onSettingsChanged(new SettingsChangedEvent(SettingsChangedEvent.EventType_FontChanged)); 070 //set cache 071 onSettingsChanged(new SettingsChangedEvent(SettingsChangedEvent.EventType_CacheSizeChanged)); 072 073 } 074 075 public static synchronized SinglePointRenderer getInstance() 076 { 077 if (_instance == null) 078 { 079 _instance = new SinglePointRenderer(); 080 } 081 082 return _instance; 083 } 084 085 /** 086 * 087 * @param symbolID 088 * @param modifiers 089 * @return 090 */ 091 public ImageInfo RenderUnit(String symbolID, Map<String,String> modifiers, Map<String,String> attributes) 092 { 093 Color lineColor = SymbolUtilities.getLineColorOfAffiliation(symbolID); 094 Color fillColor = SymbolUtilities.getFillColorOfAffiliation(symbolID); 095 Color iconColor = null; 096 097 int alpha = -1; 098 099 100 //SVG values 101 String frameID = null; 102 String iconID = null; 103 String mod1ID = null; 104 String mod2ID = null; 105 SVGInfo siFrame = null; 106 SVGInfo siIcon = null; 107 SVGInfo siMod1 = null; 108 SVGInfo siMod2 = null; 109 SVG mySVG = null; 110 int top = 0; 111 int left = 0; 112 int width = 0; 113 int height = 0; 114 String svgStart = null; 115 String strSVG = null; 116 String strSVGFrame = null; 117 118 119 Rect symbolBounds = null; 120 Rect fullBounds = null; 121 Bitmap fullBMP = null; 122 123 boolean hasDisplayModifiers = false; 124 boolean hasTextModifiers = false; 125 126 int pixelSize = -1; 127 boolean keepUnitRatio = true; 128 boolean icon = false; 129 boolean noFrame = false; 130 131 int ver = SymbolID.getVersion(symbolID); 132 133 // <editor-fold defaultstate="collapsed" desc="Parse Attributes"> 134 try 135 { 136 137 if (attributes.containsKey(MilStdAttributes.PixelSize)) 138 { 139 pixelSize = Integer.parseInt(attributes.get(MilStdAttributes.PixelSize)); 140 } 141 else 142 { 143 pixelSize = RendererSettings.getInstance().getDefaultPixelSize(); 144 } 145 146 if (attributes.containsKey(MilStdAttributes.KeepUnitRatio)) 147 { 148 keepUnitRatio = Boolean.parseBoolean(attributes.get(MilStdAttributes.KeepUnitRatio)); 149 } 150 151 if (attributes.containsKey(MilStdAttributes.DrawAsIcon)) 152 { 153 icon = Boolean.parseBoolean(attributes.get(MilStdAttributes.DrawAsIcon)); 154 } 155 156 if (icon)//icon won't show modifiers or display icons 157 { 158 //TODO: symbolID modifications as necessary 159 keepUnitRatio = false; 160 hasDisplayModifiers = false; 161 hasTextModifiers = false; 162 //symbolID = symbolID.substring(0, 10) + "-----"; 163 } 164 else 165 { 166 hasDisplayModifiers = ModifierRenderer.hasDisplayModifiers(symbolID, modifiers); 167 hasTextModifiers = ModifierRenderer.hasTextModifiers(symbolID, modifiers); 168 } 169 170 if (attributes.containsKey(MilStdAttributes.LineColor)) 171 { 172 lineColor = new Color(attributes.get(MilStdAttributes.LineColor)); 173 } 174 if (attributes.containsKey(MilStdAttributes.FillColor)) 175 { 176 fillColor = new Color(attributes.get(MilStdAttributes.FillColor)); 177 } 178 if (attributes.containsKey(MilStdAttributes.IconColor)) 179 { 180 iconColor = new Color(attributes.get(MilStdAttributes.IconColor)); 181 }//*/ 182 if (attributes.containsKey(MilStdAttributes.Alpha)) 183 { 184 alpha = Integer.parseInt(attributes.get(MilStdAttributes.Alpha)); 185 } 186 187 } 188 catch (Exception excModifiers) 189 { 190 ErrorLogger.LogException("MilStdIconRenderer", "RenderUnit", excModifiers); 191 } 192 // </editor-fold> 193 194 try 195 { 196 197 ImageInfo ii = null; 198 String key = makeCacheKey(symbolID, lineColor.toInt(), fillColor.toInt(), String.valueOf(iconColor),pixelSize, keepUnitRatio, false); 199 200 //see if it's in the cache 201 if(_unitCache != null) { 202 ii = _unitCache.get(key); 203 //safety check in case bitmaps are getting recycled while still in the LRU cache 204 if (ii != null && ii.getImage() != null && ii.getImage().isRecycled()) { 205 synchronized (_UnitCacheMutex) { 206 _unitCache.remove(key); 207 ii = null; 208 } 209 } 210 } 211 //if not, generate symbol 212 if (ii == null)//*/ 213 { 214 int version = SymbolID.getVersion(symbolID); 215 //Get SVG pieces of symbol 216 frameID = SVGLookup.getFrameID(symbolID); 217 iconID = SVGLookup.getMainIconID(symbolID); 218 mod1ID = SVGLookup.getMod1ID(symbolID); 219 mod2ID = SVGLookup.getMod2ID(symbolID); 220 siFrame = SVGLookup.getInstance().getSVGLInfo(frameID, version); 221 siIcon = SVGLookup.getInstance().getSVGLInfo(iconID, version); 222 223 if(siFrame == null) 224 { 225 frameID = SVGLookup.getFrameID(SymbolUtilities.reconcileSymbolID(symbolID)); 226 siFrame = SVGLookup.getInstance().getSVGLInfo(frameID, version); 227 if(siFrame == null)//still no match, get unknown frame 228 { 229 frameID = SVGLookup.getFrameID(SymbolID.setSymbolSet(symbolID,SymbolID.SymbolSet_Unknown)); 230 siFrame = SVGLookup.getInstance().getSVGLInfo(frameID, version); 231 } 232 } 233 234 if(siIcon == null) 235 { 236 if(iconID.substring(2,8).equals("000000")==false && MSLookup.getInstance().getMSLInfo(symbolID) == null) 237 siIcon = SVGLookup.getInstance().getSVGLInfo("98100000", version);//inverted question mark 238 else if(SymbolID.getSymbolSet(symbolID) == SymbolID.SymbolSet_Unknown) 239 siIcon = SVGLookup.getInstance().getSVGLInfo("00000000", version);//question mark 240 } 241 242 if(RendererSettings.getInstance().getScaleMainIcon()) 243 siIcon = RendererUtilities.scaleIcon(symbolID,siIcon); 244 245 siMod1 = SVGLookup.getInstance().getSVGLInfo(mod1ID, version); 246 siMod2 = SVGLookup.getInstance().getSVGLInfo(mod2ID, version); 247 top = Math.round(siFrame.getBbox().top); 248 left = Math.round(siFrame.getBbox().left); 249 width = Math.round(siFrame.getBbox().width()); 250 height = Math.round(siFrame.getBbox().height()); 251 if(siFrame.getBbox().bottom > 400) 252 svgStart = "<svg xmlns:svg=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewBox=\"0 0 612 792\">"; 253 else 254 svgStart = "<svg xmlns:svg=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewBox=\"0 0 400 400\">"; 255 256 //update line and fill color of frame SVG 257 if(lineColor != null || fillColor != null) 258 strSVGFrame = RendererUtilities.setSVGFrameColors(symbolID,siFrame.getSVG(),lineColor,fillColor); 259 else 260 strSVGFrame = siFrame.getSVG(); 261 262 if(frameID.equals("octagon"))//for the 1 unit symbol that doesn't have a frame: 30 + 15000 263 { 264 noFrame = true; 265 strSVGFrame = strSVGFrame.replaceFirst("<g id=\"octagon\">", "<g id=\"octagon\" display=\"none\">"); 266 } 267 268 269 //get SVG dimensions and target dimensions 270 symbolBounds = RectUtilities.makeRect(left,top,width,height); 271 Rect rect = new Rect(symbolBounds); 272 float ratio = -1; 273 274 if (pixelSize > 0 && keepUnitRatio == true) 275 { 276 float heightRatio = SymbolUtilities.getUnitRatioHeight(symbolID); 277 float widthRatio = SymbolUtilities.getUnitRatioWidth(symbolID); 278 279 if(noFrame == true)//using octagon with display="none" as frame for a 1x1 shape 280 { 281 heightRatio = 1.0f; 282 widthRatio = 1.0f; 283 } 284 285 if (heightRatio > widthRatio) 286 { 287 pixelSize = (int) ((pixelSize / 1.5f) * heightRatio); 288 } 289 else 290 { 291 pixelSize = (int) ((pixelSize / 1.5f) * widthRatio); 292 } 293 } 294 if (pixelSize > 0) 295 { 296 float p = pixelSize; 297 float h = rect.height(); 298 float w = rect.width(); 299 300 ratio = Math.min((p / h), (p / w)); 301 302 symbolBounds = RectUtilities.makeRect(0f, 0f, w * ratio, h * ratio); 303 } 304 305 //center of octagon is the center of all unit symbols 306 Point centerOctagon = new Point(306, 396); 307 centerOctagon.offset(-left,-top);//offset for the symbol bounds x,y 308 //scale center point by same ratio as the symbol 309 centerOctagon = new Point((int)(centerOctagon.x * ratio), (int)(centerOctagon.y * ratio)); 310 311 //set centerpoint of the image 312 Point centerPoint = centerOctagon; 313 Point centerCache = new Point(centerOctagon.x, centerOctagon.y); 314 315 //y offset to get centerpoint so we set back to zero when done. 316 symbolBounds.top = 0; 317 318 //Create destination BMP 319 Bitmap bmp = Bitmap.createBitmap(symbolBounds.width(), symbolBounds.height(), Config.ARGB_8888); 320 Canvas canvas = new Canvas(bmp); 321 322 //draw unit from SVG 323 StringBuilder sb = new StringBuilder(); 324 sb.append(svgStart); 325 326 if(strSVGFrame != null) 327 sb.append(strSVGFrame); 328 329 String color = ""; 330 String strokeFill = ""; 331 if(iconColor != null) 332 { 333 //make sure string is properly formatted. 334 color = RendererUtilities.colorToHexString(iconColor,false); 335 if(color != null && color != "#000000" && color != "") 336 strokeFill = " stroke=\"" + color + "\" fill=\"" + color + "\" "; 337 else 338 color = null; 339 } 340 String unit = "<g" + strokeFill + ">"; 341 if (siIcon != null) 342 unit += (siIcon.getSVG()); 343 if (siMod1 != null) 344 unit += (siMod1.getSVG()); 345 if (siMod2 != null) 346 unit += (siMod2.getSVG()); 347 if(iconColor != null && color != null && color != "") 348 unit = unit.replaceAll("#000000",color); 349 sb.append(unit + "</g>"); 350 351 sb.append("</svg>"); 352 353 strSVG = sb.toString(); 354 355 mySVG = SVG.getFromString(strSVG); 356 mySVG.setDocumentViewBox(left,top,width,height); 357 mySVG.renderToCanvas(canvas); 358 359 360 //adjust centerpoint for HQStaff if present 361 if (SymbolUtilities.isHQ(symbolID)) 362 { 363 PointF point1 = new PointF(); 364 PointF point2 = new PointF(); 365 int affiliation = SymbolID.getAffiliation(symbolID); 366 int ss = SymbolID.getStandardIdentity(symbolID); 367 if (affiliation == SymbolID.StandardIdentity_Affiliation_Friend 368 || affiliation == SymbolID.StandardIdentity_Affiliation_AssumedFriend 369 || affiliation == SymbolID.StandardIdentity_Affiliation_Neutral 370 || ss == 15 || ss == 16)//exercise joker or faker 371 { 372 point1.x = (symbolBounds.left); 373 point1.y = symbolBounds.top + (symbolBounds.height()); 374 point2.x = point1.x; 375 point2.y = point1.y + symbolBounds.height(); 376 } 377 else 378 { 379 point1.x = (symbolBounds.left + 1); 380 point1.y = symbolBounds.top + (symbolBounds.height() / 2); 381 point2.x = point1.x; 382 point2.y = point1.y + symbolBounds.height(); 383 } 384 centerPoint = new Point((int) point2.x, (int) point2.y); 385 } 386 387 ii = new ImageInfo(bmp, centerPoint, symbolBounds); 388 389 if(cacheEnabled && icon == false && bmp.getAllocationByteCount() <= maxCachedEntrySize) 390 { 391 synchronized (_UnitCacheMutex) 392 { 393 if(_unitCache != null && _unitCache.get(key) == null) 394 _unitCache.put(key, new ImageInfo(bmp, new Point(centerCache), new Rect(symbolBounds))); 395 } 396 } 397 398 /*if(icon == false && pixelSize <= 100) 399 { 400 _unitCache.put(key, new ImageInfo(bmp, new Point(centerCache), new Rect(symbolBounds))); 401 }//*/ 402 } 403 404 ImageInfo iiNew = null; 405 SymbolDimensionInfo sdiTemp = null; 406 //////////////////////////////////////////////////////////////////// 407 //process display modifiers 408 if (hasDisplayModifiers) 409 { 410 sdiTemp = ModifierRenderer.processUnitDisplayModifiers( ii, symbolID, modifiers, hasTextModifiers, attributes); 411 iiNew = (sdiTemp instanceof ImageInfo ? (ImageInfo)sdiTemp : null); 412 sdiTemp = null; 413 } 414 415 if (iiNew != null) 416 { 417 ii = iiNew; 418 } 419 iiNew = null; 420 421 //process text modifiers 422 if (hasTextModifiers) 423 { 424 int ss = SymbolID.getSymbolSet(symbolID); 425 switch(ss) 426 { 427 case SymbolID.SymbolSet_LandUnit: 428 case SymbolID.SymbolSet_LandCivilianUnit_Organization: 429 if(ver >= SymbolID.Version_2525E) 430 sdiTemp = ModifierRenderer.processLandUnitTextModifiersE(ii, symbolID, modifiers, attributes); 431 else 432 sdiTemp = ModifierRenderer.processLandUnitTextModifiers(ii, symbolID, modifiers, attributes); 433 break; 434 case SymbolID.SymbolSet_LandEquipment: 435 case SymbolID.SymbolSet_SignalsIntelligence_Land: 436 if(ver >= SymbolID.Version_2525E) 437 sdiTemp = ModifierRenderer.processLandEquipmentTextModifiersE(ii, symbolID, modifiers, attributes); 438 else 439 sdiTemp = ModifierRenderer.processLandEquipmentTextModifiers(ii, symbolID, modifiers, attributes); 440 break; 441 case SymbolID.SymbolSet_LandInstallation: 442 if(ver >= SymbolID.Version_2525E) 443 sdiTemp = ModifierRenderer.processLandInstallationTextModifiersE(ii, symbolID, modifiers, attributes); 444 else 445 sdiTemp = ModifierRenderer.processLandInstallationTextModifiers(ii, symbolID, modifiers, attributes); 446 break; 447 case SymbolID.SymbolSet_DismountedIndividuals: 448 sdiTemp = ModifierRenderer.processDismountedIndividualsTextModifiers(ii, symbolID, modifiers, attributes); 449 break; 450 case SymbolID.SymbolSet_Space: 451 case SymbolID.SymbolSet_SpaceMissile: 452 case SymbolID.SymbolSet_Air: 453 case SymbolID.SymbolSet_AirMissile: 454 case SymbolID.SymbolSet_SignalsIntelligence_Air: 455 if(ver >= SymbolID.Version_2525E) 456 sdiTemp = ModifierRenderer.processAirSpaceUnitTextModifiersE(ii, symbolID, modifiers, attributes); 457 else 458 sdiTemp = ModifierRenderer.processAirSpaceUnitTextModifiers(ii, symbolID, modifiers, attributes); 459 break; 460 case SymbolID.SymbolSet_SignalsIntelligence_Space: 461 if(ver < SymbolID.Version_2525E) 462 sdiTemp = ModifierRenderer.processAirSpaceUnitTextModifiers(ii, symbolID, modifiers, attributes); 463 else//SIGINT in 2525E+ uses modifer places based on frame shape 464 { 465 char frameShape = SymbolID.getFrameShape(symbolID); 466 if(frameShape == SymbolID.FrameShape_Space || frameShape == SymbolID.FrameShape_Air) 467 sdiTemp = ModifierRenderer.processAirSpaceUnitTextModifiersE(ii, symbolID, modifiers, attributes); 468 else if(frameShape == SymbolID.FrameShape_LandEquipment_SeaSurface)//sea surface, but can't tell which so default land equip 469 sdiTemp = ModifierRenderer.processLandEquipmentTextModifiersE(ii, symbolID, modifiers, attributes); 470 else if(frameShape == SymbolID.FrameShape_SeaSubsurface) 471 sdiTemp = ModifierRenderer.processSeaSubSurfaceTextModifiersE(ii, symbolID, modifiers, attributes); 472 else//default land equipment 473 sdiTemp = ModifierRenderer.processLandEquipmentTextModifiersE(ii, symbolID, modifiers, attributes); 474 } 475 break; 476 case SymbolID.SymbolSet_SeaSurface: 477 case SymbolID.SymbolSet_SignalsIntelligence_SeaSurface: 478 if(ver >= SymbolID.Version_2525E) 479 sdiTemp = ModifierRenderer.processSeaSurfaceTextModifiersE(ii, symbolID, modifiers, attributes); 480 else 481 sdiTemp = ModifierRenderer.processSeaSurfaceTextModifiers(ii, symbolID, modifiers, attributes); 482 break; 483 case SymbolID.SymbolSet_SeaSubsurface: 484 case SymbolID.SymbolSet_SignalsIntelligence_SeaSubsurface: 485 if(ver >= SymbolID.Version_2525E) 486 sdiTemp = ModifierRenderer.processSeaSubSurfaceTextModifiersE(ii, symbolID, modifiers, attributes); 487 else 488 sdiTemp = ModifierRenderer.processSeaSubSurfaceTextModifiers(ii, symbolID, modifiers, attributes); 489 break; 490 case SymbolID.SymbolSet_Activities: 491 if(ver >= SymbolID.Version_2525E) 492 sdiTemp = ModifierRenderer.processActivitiesTextModifiersE(ii, symbolID, modifiers, attributes); 493 else 494 sdiTemp = ModifierRenderer.processActivitiesTextModifiers(ii, symbolID, modifiers, attributes); 495 break; 496 case SymbolID.SymbolSet_CyberSpace: 497 sdiTemp = ModifierRenderer.processCyberSpaceTextModifiers(ii, symbolID, modifiers, attributes); 498 break; 499 case SymbolID.SymbolSet_MineWarfare: 500 break;//no modifiers 501 case SymbolID.SymbolSet_Unknown: 502 default: //in theory, will never get here 503 sdiTemp = ModifierRenderer.processUnknownTextModifiers(ii, symbolID, modifiers, attributes); 504 } 505 506 } 507 508 iiNew = (sdiTemp instanceof ImageInfo ? (ImageInfo)sdiTemp : null); 509 if (iiNew != null) 510 { 511 ii = iiNew; 512 } 513 iiNew = null; 514 515 //cleanup/////////////////////////////////////////////////////////// 516 //bmp.recycle(); 517 symbolBounds = null; 518 fullBMP = null; 519 fullBounds = null; 520 mySVG = null; 521 //////////////////////////////////////////////////////////////////// 522 523 if (icon == true) 524 { 525 return ii.getSquareImageInfo(); 526 } 527 else 528 { 529 return ii; 530 } 531 532 } 533 catch (Exception exc) 534 { 535 ErrorLogger.LogException("MilStdIconRenderer", "RenderUnit", exc); 536 } 537 return null; 538 } 539 540 /** 541 * 542 * @param symbolID 543 * @param modifiers 544 * @return 545 */ 546 @SuppressWarnings("unused") 547 public ImageInfo RenderSP(String symbolID, Map<String,String> modifiers, Map<String,String> attributes) 548 { 549 ImageInfo temp = null; 550 String basicSymbolID = null; 551 552 Color lineColor = SymbolUtilities.getDefaultLineColor(symbolID); 553 Color fillColor = null;//SymbolUtilities.getFillColorOfAffiliation(symbolID); 554 555 int alpha = -1; 556 557 558 //SVG rendering variables 559 MSInfo msi = null; 560 String iconID = null; 561 SVGInfo siIcon = null; 562 String mod1ID = null; 563 SVGInfo siMod1 = null; 564 int top = 0; 565 int left = 0; 566 int width = 0; 567 int height = 0; 568 String svgStart = null; 569 String strSVG = null; 570 SVG mySVG = null; 571 572 float ratio = 0; 573 574 Rect symbolBounds = null; 575 RectF fullBounds = null; 576 Bitmap fullBMP = null; 577 578 boolean drawAsIcon = false; 579 int pixelSize = -1; 580 boolean keepUnitRatio = true; 581 boolean hasDisplayModifiers = false; 582 boolean hasTextModifiers = false; 583 boolean drawCustomOutline = false; 584 585 msi = MSLookup.getInstance().getMSLInfo(symbolID); 586 int ss = SymbolID.getSymbolSet(symbolID); 587 int ec = SymbolID.getEntityCode(symbolID); 588 int mod1 = 0; 589 int drawRule = 0; 590 if(msi!=null){drawRule = msi.getDrawRule();} 591 boolean hasAPFill = false; 592 if(RendererSettings.getInstance().getActionPointDefaultFill()) { 593 if (SymbolUtilities.isActionPoint(symbolID) || //action points 594 drawRule == DrawRules.POINT10 || //Sonobuoy 595 ec == 180100 || ec == 180200 || ec == 180400) //ACP, CCP, PUP 596 { 597 if (SymbolID.getSymbolSet(symbolID) == SymbolID.SymbolSet_ControlMeasure) { 598 lineColor = Color.BLACK; 599 hasAPFill = true; 600 } 601 } 602 } 603 604 try 605 { 606 if (modifiers == null) 607 { 608 modifiers = new HashMap<>(); 609 } 610 611 612 //get symbol info 613 614 msi = MSLookup.getInstance().getMSLInfo(symbolID); 615 616 if (msi == null)//if lookup fails, fix code/use unknown symbol code. 617 { 618 //TODO: change symbolID to Action Point with bad symbolID in the T or H field 619 } 620 621 /* Fills built into SVG 622 if (SymbolUtilities.hasDefaultFill(symbolID)) 623 { 624 fillColor = SymbolUtilities.getFillColorOfAffiliation(symbolID); 625 } 626 if (SymbolUtilities.isTGSPWithFill(symbolID)) 627 { 628 fillID = SymbolUtilities.getTGFillSymbolCode(symbolID); 629 if (fillID != null) 630 { 631 charFillIndex = SinglePointLookup.getInstance().getCharCodeFromSymbol(fillID, symStd); 632 } 633 } 634 else if (SymbolUtilities.isWeatherSPWithFill(symbolID)) 635 { 636 charFillIndex = charFrameIndex + 1; 637 fillColor = SymbolUtilities.getFillColorOfWeather(symbolID); 638 639 }//*/ 640 641 if (attributes != null) 642 { 643 if (attributes.containsKey(MilStdAttributes.KeepUnitRatio)) 644 { 645 keepUnitRatio = Boolean.parseBoolean(attributes.get(MilStdAttributes.KeepUnitRatio)); 646 } 647 648 if (attributes.containsKey(MilStdAttributes.LineColor)) 649 { 650 lineColor = RendererUtilities.getColorFromHexString(attributes.get(MilStdAttributes.LineColor)); 651 } 652 653 if (attributes.containsKey(MilStdAttributes.FillColor)) 654 { 655 fillColor = RendererUtilities.getColorFromHexString(attributes.get(MilStdAttributes.FillColor)); 656 } 657 658 if (attributes.containsKey(MilStdAttributes.Alpha)) 659 { 660 alpha = Integer.parseInt(attributes.get(MilStdAttributes.Alpha)); 661 } 662 663 if (attributes.containsKey(MilStdAttributes.DrawAsIcon)) 664 { 665 drawAsIcon = Boolean.parseBoolean(attributes.get(MilStdAttributes.DrawAsIcon)); 666 } 667 668 if (attributes.containsKey(MilStdAttributes.PixelSize)) 669 { 670 pixelSize = Integer.parseInt(attributes.get(MilStdAttributes.PixelSize)); 671 } 672 else 673 { 674 pixelSize = RendererSettings.getInstance().getDefaultPixelSize(); 675 } 676 if(keepUnitRatio == true && msi.getSymbolSet() == SymbolID.SymbolSet_ControlMeasure && msi.getGeometry().equalsIgnoreCase("point")) 677 { 678 if(msi.getDrawRule() == DrawRules.POINT1)//Action Points 679 pixelSize = (int)Math.ceil((pixelSize/1.5f) * 1.5f); 680 else 681 pixelSize = (int)Math.ceil((pixelSize/1.5f) * 1.2f); 682 } 683 684 if(attributes.containsKey(MilStdAttributes.OutlineSymbol)) 685 drawCustomOutline = Boolean.parseBoolean(attributes.get(MilStdAttributes.OutlineSymbol)); 686 else 687 drawCustomOutline = RendererSettings.getInstance().getOutlineSPControlMeasures(); 688 689 if(SymbolUtilities.isMultiPoint(symbolID)) 690 drawCustomOutline=false;//icon previews for multipoints do not need outlines since they shouldn't be on the map 691 } 692 693 if (drawAsIcon)//icon won't show modifiers or display icons 694 { 695 keepUnitRatio = false; 696 hasDisplayModifiers = false; 697 hasTextModifiers = false; 698 drawCustomOutline = false; 699 } 700 else 701 { 702 hasDisplayModifiers = ModifierRenderer.hasDisplayModifiers(symbolID, modifiers); 703 hasTextModifiers = ModifierRenderer.hasTextModifiers(symbolID, modifiers); 704 } 705 706 //Check if we need to set 'N' to "ENY" 707 int aff = SymbolID.getAffiliation(symbolID); 708 //int ss = msi.getSymbolSet(); 709 if (ss == SymbolID.SymbolSet_ControlMeasure && 710 (aff == SymbolID.StandardIdentity_Affiliation_Hostile_Faker || 711 aff == SymbolID.StandardIdentity_Affiliation_Suspect_Joker ) && 712 modifiers.containsKey(Modifiers.N_HOSTILE) && 713 drawAsIcon == false) 714 { 715 modifiers.put(Modifiers.N_HOSTILE, "ENY"); 716 } 717 718 } 719 catch (Exception excModifiers) 720 { 721 ErrorLogger.LogException("MilStdIconRenderer", "RenderSP", excModifiers); 722 } 723 724 try 725 { 726 ImageInfo ii = null; 727 int intFill = -1; 728 if (fillColor != null) 729 { 730 intFill = fillColor.toInt(); 731 } 732 733 734 if(msi.getSymbolSet() != SymbolID.SymbolSet_ControlMeasure) 735 lineColor = Color.BLACK;//color isn't black but should be fine for weather since colors can't be user defined. 736 737 738 739 if (SymbolID.getSymbolSet(symbolID)==SymbolID.SymbolSet_ControlMeasure && SymbolID.getEntityCode(symbolID) == 270701)//static depiction 740 { 741 //add mine fill to image 742 mod1 = SymbolID.getModifier1(symbolID); 743 if (!(mod1 >= 13 && mod1 <= 50)) 744 symbolID = SymbolID.setModifier1(symbolID, 13); 745 } 746 747 String key = makeCacheKey(symbolID, lineColor.toInt(), intFill, pixelSize, keepUnitRatio, drawCustomOutline); 748 749 //see if it's in the cache 750 if(_tgCache != null) { 751 ii = _tgCache.get(key); 752 //safety check in case bitmaps are getting recycled while still in the LRU cache 753 if (ii != null && ii.getImage() != null && ii.getImage().isRecycled()) { 754 synchronized (_SinglePointCacheMutex) { 755 _tgCache.remove(key); 756 ii = null; 757 } 758 } 759 } 760 761 //if not, generate symbol. 762 if (ii == null)//*/ 763 { 764 int version = SymbolID.getVersion(symbolID); 765 //check symbol size//////////////////////////////////////////// 766 Rect rect = null; 767 iconID = SVGLookup.getMainIconID(symbolID); 768 siIcon = SVGLookup.getInstance().getSVGLInfo(iconID, version); 769 mod1ID = SVGLookup.getMod1ID(symbolID); 770 siMod1 = SVGLookup.getInstance().getSVGLInfo(mod1ID, version); 771 float borderPadding = 0; 772 if (drawCustomOutline) { 773 borderPadding = RendererUtilities.findWidestStrokeWidth(siIcon.getSVG()); 774 } 775 top = Math.round(siIcon.getBbox().top); 776 left = Math.round(siIcon.getBbox().left); 777 width = Math.round(siIcon.getBbox().width()); 778 height = Math.round(siIcon.getBbox().height()); 779 if(siIcon.getBbox().bottom > 400) 780 svgStart = "<svg xmlns:svg=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewBox=\"0 0 612 792\">"; 781 else 782 svgStart = "<svg xmlns:svg=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewBox=\"0 0 400 400\">"; 783 784 String strSVGIcon = null; 785 786 787 if(hasAPFill) //action points and a few others //Sonobuoy //ACP, CCP, PUP 788 { 789 String apFill; 790 if(fillColor != null) 791 apFill = RendererUtilities.colorToHexString(fillColor,false); 792 else 793 apFill = RendererUtilities.colorToHexString(SymbolUtilities.getFillColorOfAffiliation(symbolID),false); 794 siIcon = new SVGInfo(siIcon.getID(),siIcon.getBbox(), siIcon.getSVG().replaceAll("fill=\"none\"","fill=\"" + apFill + "\"")); 795 } 796 797 //update line and fill color of frame SVG 798 if(msi.getSymbolSet() == SymbolID.SymbolSet_ControlMeasure && (lineColor != null || fillColor != null)) { 799 if (drawCustomOutline) { 800 // create outline with larger stroke-width first (if selected) 801 strSVGIcon = RendererUtilities.setSVGSPCMColors(symbolID, siIcon.getSVG(), RendererUtilities.getIdealOutlineColor(lineColor), fillColor, true); 802 } 803 804 // append normal symbol SVG to be layered on top of outline 805 strSVGIcon += RendererUtilities.setSVGSPCMColors(symbolID, siIcon.getSVG(), lineColor, fillColor, false); 806 } 807 else//weather symbol (don't change color of weather graphics) 808 strSVGIcon = siIcon.getSVG(); 809 810 //If symbol is Static Depiction, add internal mine graphic based on sector modifier 1 811 if(SymbolID.getEntityCode(symbolID) == 270701 && siMod1 != null) 812 { 813 if (drawCustomOutline) { 814 // create outline with larger stroke-width first (if selected) 815 strSVGIcon += RendererUtilities.setSVGSPCMColors(mod1ID, siMod1.getSVG(), RendererUtilities.getIdealOutlineColor(RendererUtilities.getColorFromHexString("#00A651")), RendererUtilities.getColorFromHexString("#00A651"), true); 816 } 817 //strSVGIcon += siMod1.getSVG(); 818 strSVGIcon += RendererUtilities.setSVGSPCMColors(mod1ID, siMod1.getSVG(), lineColor, fillColor, false); 819 } 820 821 if (pixelSize > 0) 822 { 823 symbolBounds = RectUtilities.makeRect(left,top,width,height); 824 rect = new Rect(symbolBounds); 825 826 //adjust size 827 float p = pixelSize; 828 float h = rect.height(); 829 float w = rect.width(); 830 831 ratio = Math.min((p / h), (p / w)); 832 833 symbolBounds = RectUtilities.makeRect(0f, 0f, w * ratio, h * ratio); 834 835 //make sure border padding isn't excessive. 836 w = symbolBounds.width(); 837 h = symbolBounds.height(); 838 839 if(h/(h+borderPadding) > 0.10) 840 { 841 borderPadding = (float)(h * 0.1); 842 } 843 else if(w/(w+borderPadding) > 0.10) 844 { 845 borderPadding = (float)(w * 0.1); 846 } 847 848 } 849 850 //Draw glyphs to bitmap 851 Bitmap bmp = Bitmap.createBitmap((symbolBounds.width() + Math.round(borderPadding)), (symbolBounds.height() + Math.round(borderPadding)), Config.ARGB_8888); 852 Canvas canvas = new Canvas(bmp); 853 854 symbolBounds = new Rect(0, 0, bmp.getWidth(), bmp.getHeight()); 855 856 //grow size SVG to accommodate the outline we added 857 int offset = 0; 858 if(drawCustomOutline) 859 { 860 //TODO: maybe come up with a calculation vs just the #2, although it seems to work well. 861 RectUtilities.grow(rect, 2); 862 offset = 4; 863 }//*/ 864 865 866 if(msi.getSymbolSet()==SymbolID.SymbolSet_ControlMeasure && msi.getDrawRule()==DrawRules.POINT1)//smooth out action points 867 strSVGIcon = "/n<g stroke-linejoin=\"round\" >/n" + strSVGIcon + "/n</g>"; 868 869 strSVG = svgStart + strSVGIcon + "</svg>"; 870 mySVG = SVG.getFromString(strSVG); 871 //mySVG.setDocumentViewBox(left,top,width,height); 872 mySVG.setDocumentViewBox(rect.left,rect.top,rect.width(),rect.height()); 873 mySVG.renderToCanvas(canvas); 874 875 Point centerPoint = SymbolUtilities.getCMSymbolAnchorPoint(symbolID,new RectF(offset, offset, symbolBounds.right, symbolBounds.bottom)); 876 877 ii = new ImageInfo(bmp, centerPoint, symbolBounds); 878 879 if(cacheEnabled && drawAsIcon == false && bmp.getAllocationByteCount() <= maxCachedEntrySize) 880 { 881 synchronized (_SinglePointCacheMutex) 882 { 883 if(_tgCache.get(key) == null) 884 _tgCache.put(key, ii); 885 } 886 } 887 /*if (drawAsIcon == false && pixelSize <= 100) 888 889 _tgCache.put(key, ii); 890 }//*/ 891 } 892 893 //Process Modifiers 894 ImageInfo iiNew = null; 895 if (drawAsIcon == false && (hasTextModifiers || hasDisplayModifiers)) 896 { 897 SymbolDimensionInfo sdiTemp = null; 898 if (SymbolUtilities.isSPWithSpecialModifierLayout(symbolID))//(SymbolUtilitiesD.isTGSPWithSpecialModifierLayout(symbolID)) 899 { 900 sdiTemp = ModifierRenderer.ProcessTGSPWithSpecialModifierLayout(ii, symbolID, modifiers, attributes, lineColor); 901 } 902 else 903 { 904 sdiTemp = ModifierRenderer.ProcessTGSPModifiers(ii, symbolID, modifiers, attributes, lineColor); 905 } 906 iiNew = (sdiTemp instanceof ImageInfo ? (ImageInfo)sdiTemp : null); 907 } 908 909 if (iiNew != null) 910 { 911 ii = iiNew; 912 } 913 914 //cleanup 915 //bmp.recycle(); 916 symbolBounds = null; 917 fullBMP = null; 918 fullBounds = null; 919 mySVG = null; 920 921 922 if (drawAsIcon) 923 { 924 return ii.getSquareImageInfo(); 925 } 926 else 927 { 928 return ii; 929 } 930 931 } 932 catch (Exception exc) 933 { 934 ErrorLogger.LogException("MilStdIconRenderer", "RenderSP", exc); 935 } 936 return null; 937 } 938 939 940 /** 941 * 942 * @param symbolID 943 * @return 944 */ 945 @SuppressWarnings("unused") 946 public ImageInfo RenderModifier(String symbolID, Map<String,String> attributes) 947 { 948 ImageInfo temp = null; 949 String basicSymbolID = null; 950 951 Color lineColor = null; 952 Color fillColor = null;//SymbolUtilities.getFillColorOfAffiliation(symbolID); 953 954 int alpha = -1; 955 956 957 //SVG rendering variables 958 MSInfo msi = null; 959 String iconID = null; 960 SVGInfo siIcon = null; 961 int top = 0; 962 int left = 0; 963 int width = 0; 964 int height = 0; 965 String svgStart = null; 966 String strSVG = null; 967 SVG mySVG = null; 968 969 float ratio = 0; 970 971 Rect symbolBounds = null; 972 RectF fullBounds = null; 973 Bitmap fullBMP = null; 974 975 boolean drawAsIcon = false; 976 int pixelSize = -1; 977 boolean keepUnitRatio = true; 978 boolean hasDisplayModifiers = false; 979 boolean hasTextModifiers = false; 980 int symbolOutlineWidth = RendererSettings.getInstance().getSinglePointSymbolOutlineWidth(); 981 boolean drawCustomOutline = false; 982 983 try 984 { 985 986 msi = MSLookup.getInstance().getMSLInfo(symbolID); 987 if (attributes != null) 988 { 989 if (attributes.containsKey(MilStdAttributes.KeepUnitRatio)) 990 { 991 keepUnitRatio = Boolean.parseBoolean(attributes.get(MilStdAttributes.KeepUnitRatio)); 992 } 993 994 if (attributes.containsKey(MilStdAttributes.LineColor)) 995 { 996 lineColor = RendererUtilities.getColorFromHexString(attributes.get(MilStdAttributes.LineColor)); 997 } 998 999 if (attributes.containsKey(MilStdAttributes.FillColor)) 1000 { 1001 fillColor = RendererUtilities.getColorFromHexString(attributes.get(MilStdAttributes.FillColor)); 1002 } 1003 1004 if (attributes.containsKey(MilStdAttributes.Alpha)) 1005 { 1006 alpha = Integer.parseInt(attributes.get(MilStdAttributes.Alpha)); 1007 } 1008 1009 if (attributes.containsKey(MilStdAttributes.DrawAsIcon)) 1010 { 1011 drawAsIcon = Boolean.parseBoolean(attributes.get(MilStdAttributes.DrawAsIcon)); 1012 } 1013 1014 if (attributes.containsKey(MilStdAttributes.PixelSize)) 1015 { 1016 pixelSize = Integer.parseInt(attributes.get(MilStdAttributes.PixelSize)); 1017 if(msi.getSymbolSet() == SymbolID.SymbolSet_ControlMeasure) 1018 { 1019 if(SymbolID.getEntityCode(symbolID)==270701)//static depiction 1020 pixelSize = (int)(pixelSize * 0.9);//try to scale to be somewhat in line with units 1021 } 1022 } 1023 1024 if(drawAsIcon==false)//don't outline icons because they're not going on the map 1025 { 1026 if(attributes.containsKey(MilStdAttributes.OutlineSymbol)) 1027 drawCustomOutline = Boolean.parseBoolean(attributes.get(MilStdAttributes.OutlineSymbol)); 1028 else 1029 drawCustomOutline = RendererSettings.getInstance().getOutlineSPControlMeasures(); 1030 } 1031 1032 if(SymbolUtilities.isMultiPoint(symbolID)) 1033 drawCustomOutline=false;//icon previews for multipoints do not need outlines since they shouldn't be on the map 1034 1035 /*if (attributes.containsKey(MilStdAttributes.OutlineWidth)>=0) 1036 symbolOutlineWidth = Integer.parseInt(attributes.get(MilStdAttributes.OutlineWidth));//*/ 1037 } 1038 1039 int outlineOffset = symbolOutlineWidth; 1040 if (drawCustomOutline && outlineOffset > 2) 1041 { 1042 outlineOffset = (outlineOffset - 1) / 2; 1043 } 1044 else 1045 { 1046 outlineOffset = 0; 1047 } 1048 1049 } 1050 catch (Exception excModifiers) 1051 { 1052 ErrorLogger.LogException("MilStdIconRenderer", "RenderSP", excModifiers); 1053 } 1054 1055 try 1056 { 1057 ImageInfo ii = null; 1058 int intFill = -1; 1059 if (fillColor != null) 1060 { 1061 intFill = fillColor.toInt(); 1062 } 1063 1064 1065 if(msi.getSymbolSet() != SymbolID.SymbolSet_ControlMeasure) 1066 lineColor = Color.BLACK;//color isn't black but should be fine for weather since colors can't be user defined. 1067 1068 1069 //if not, generate symbol 1070 if (ii == null)//*/ 1071 { 1072 int version = SymbolID.getVersion(symbolID); 1073 //check symbol size//////////////////////////////////////////// 1074 Rect rect = null; 1075 1076 iconID = SVGLookup.getMod1ID(symbolID); 1077 siIcon = SVGLookup.getInstance().getSVGLInfo(iconID, version); 1078 top = Math.round(siIcon.getBbox().top); 1079 left = Math.round(siIcon.getBbox().left); 1080 width = Math.round(siIcon.getBbox().width()); 1081 height = Math.round(siIcon.getBbox().height()); 1082 if(siIcon.getBbox().bottom > 400) 1083 svgStart = "<svg xmlns:svg=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewBox=\"0 0 612 792\">"; 1084 else 1085 svgStart = "<svg xmlns:svg=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewBox=\"0 0 400 400\">"; 1086 1087 String strSVGIcon = null; 1088 String strSVGOutline = null; 1089 1090 //update line and fill color of frame SVG 1091 if(msi.getSymbolSet() == SymbolID.SymbolSet_ControlMeasure && (lineColor != null || fillColor != null)) 1092 strSVGIcon = RendererUtilities.setSVGFrameColors(symbolID,siIcon.getSVG(),lineColor,fillColor); 1093 else 1094 strSVGIcon = siIcon.getSVG(); 1095 1096 if (pixelSize > 0) 1097 { 1098 symbolBounds = RectUtilities.makeRect(left,top,width,height); 1099 rect = new Rect(symbolBounds); 1100 1101 //adjust size 1102 float p = pixelSize; 1103 float h = rect.height(); 1104 float w = rect.width(); 1105 1106 ratio = Math.min((p / h), (p / w)); 1107 1108 symbolBounds = RectUtilities.makeRect(0f, 0f, w * ratio, h * ratio); 1109 1110 } 1111 1112 1113 //TODO: figure out how to draw an outline and adjust the symbol bounds accordingly 1114 1115 //Draw glyphs to bitmap 1116 Bitmap bmp = Bitmap.createBitmap((symbolBounds.width()), (symbolBounds.height()), Config.ARGB_8888); 1117 Canvas canvas = new Canvas(bmp); 1118 1119 symbolBounds = new Rect(0, 0, bmp.getWidth(), bmp.getHeight()); 1120 1121 strSVG = svgStart + strSVGIcon + "</svg>"; 1122 mySVG = SVG.getFromString(strSVG); 1123 mySVG.setDocumentViewBox(left,top,width,height); 1124 mySVG.renderToCanvas(canvas); 1125 1126 Point centerPoint = SymbolUtilities.getCMSymbolAnchorPoint(symbolID,new RectF(0, 0, symbolBounds.right, symbolBounds.bottom)); 1127 1128 ii = new ImageInfo(bmp, centerPoint, symbolBounds); 1129 1130 1131 /*if (drawAsIcon == false && pixelSize <= 100) 1132 { 1133 _tgCache.put(key, ii); 1134 }//*/ 1135 } 1136 1137 1138 //cleanup 1139 //bmp.recycle(); 1140 symbolBounds = null; 1141 fullBMP = null; 1142 fullBounds = null; 1143 mySVG = null; 1144 1145 1146 if (drawAsIcon) 1147 { 1148 return ii.getSquareImageInfo(); 1149 } 1150 else 1151 { 1152 return ii; 1153 } 1154 1155 } 1156 catch (Exception exc) 1157 { 1158 ErrorLogger.LogException("MilStdIconRenderer", "RenderSP", exc); 1159 } 1160 return null; 1161 } 1162 1163 1164 1165 /** 1166 * 1167 * @param symbolID 1168 * @param lineColor 1169 * @param fillColor 1170 * @param size 1171 * @param keepUnitRatio 1172 * @param drawOutline (only for single-point Control Measures) 1173 * @return 1174 */ 1175 private static String makeCacheKey(String symbolID, int lineColor, int fillColor, int size, boolean keepUnitRatio, boolean drawOutline) 1176 { 1177 return makeCacheKey(symbolID, lineColor, fillColor, "null",size, keepUnitRatio, false); 1178 } 1179 1180 private static String makeCacheKey(String symbolID, int lineColor, int fillColor, String iconColor, int size, boolean keepUnitRatio, boolean drawOutline) 1181 { 1182 //String key = symbolID.substring(0, 20) + String.valueOf(lineColor) + String.valueOf(fillColor) + String.valueOf(size) + String.valueOf(keepUnitRatio); 1183 String key = symbolID.substring(0, 7) + symbolID.substring(10, 20) + SymbolID.getFrameShape(symbolID) + lineColor + fillColor + iconColor + size + keepUnitRatio + drawOutline; 1184 return key; 1185 } 1186 1187 public void logError(String tag, Throwable thrown) 1188 { 1189 if (tag == null || tag.equals("")) 1190 { 1191 tag = "singlePointRenderer"; 1192 } 1193 1194 String message = thrown.getMessage(); 1195 String stack = getStackTrace(thrown); 1196 if (message != null) 1197 { 1198 Log.e(tag, message); 1199 } 1200 if (stack != null) 1201 { 1202 Log.e(tag, stack); 1203 } 1204 } 1205 1206 public String getStackTrace(Throwable thrown) 1207 { 1208 try 1209 { 1210 if (thrown != null) 1211 { 1212 if (thrown.getStackTrace() != null) 1213 { 1214 String eol = System.getProperty("line.separator"); 1215 StringBuilder sb = new StringBuilder(); 1216 sb.append(thrown.toString()); 1217 sb.append(eol); 1218 for (StackTraceElement element : thrown.getStackTrace()) 1219 { 1220 sb.append(" at "); 1221 sb.append(element); 1222 sb.append(eol); 1223 } 1224 return sb.toString(); 1225 } 1226 else 1227 { 1228 return thrown.getMessage() + "- no stack trace"; 1229 } 1230 } 1231 else 1232 { 1233 return "no stack trace"; 1234 } 1235 } 1236 catch (Exception exc) 1237 { 1238 Log.e("getStackTrace", exc.getMessage()); 1239 } 1240 return thrown.getMessage(); 1241 }// 1242 1243 /* 1244 private static String PrintList(ArrayList list) 1245 { 1246 String message = ""; 1247 for(Object item : list) 1248 { 1249 1250 message += item.toString() + "\n"; 1251 } 1252 return message; 1253 }//*/ 1254 /* 1255 private static String PrintObjectMap(Map<String, Object> map) 1256 { 1257 Iterator<Object> itr = map.values().iterator(); 1258 String message = ""; 1259 String temp = null; 1260 while(itr.hasNext()) 1261 { 1262 temp = String.valueOf(itr.next()); 1263 if(temp != null) 1264 message += temp + "\n"; 1265 } 1266 //ErrorLogger.LogMessage(message); 1267 return message; 1268 }//*/ 1269 @Override 1270 public void onSettingsChanged(SettingsChangedEvent sce) 1271 { 1272 1273 if(sce != null && sce.getEventType().equals(SettingsChangedEvent.EventType_FontChanged)) 1274 { 1275 synchronized (_modifierFontMutex) 1276 { 1277 _modifierFont = RendererSettings.getInstance().getModiferFont(); 1278 _modifierOutlineFont = RendererSettings.getInstance().getModiferFont(); 1279 FontMetrics fm = new FontMetrics(); 1280 fm = _modifierFont.getFontMetrics(); 1281 _modifierDescent = fm.descent; 1282 //_modifierFontHeight = fm.top + fm.bottom; 1283 _modifierFontHeight = fm.bottom - fm.top; 1284 1285 _modifierFont.setStrokeWidth(RendererSettings.getInstance().getTextOutlineWidth()); 1286 _modifierOutlineFont.setColor(Color.white.toInt()); 1287 _deviceDPI = RendererSettings.getInstance().getDeviceDPI(); 1288 1289 ModifierRenderer.setModifierFont(_modifierFont, _modifierFontHeight, _modifierDescent); 1290 1291 } 1292 } 1293 1294 if(sce != null && sce.getEventType().equals(SettingsChangedEvent.EventType_CacheSizeChanged)) 1295 { 1296 1297 int cSize = RendererSettings.getInstance().getCacheSize()/2; 1298 //adjust unit cache 1299 if(cSize != cacheSize) { 1300 cacheSize = cSize; 1301 if (cacheSize >= 5) 1302 maxCachedEntrySize = cacheSize / 5; 1303 else 1304 maxCachedEntrySize = 1; 1305 1306 if(cacheEnabled) //if cache enabled, update cache 1307 { 1308 1309 synchronized (_UnitCacheMutex) { 1310 if(_unitCache != null) 1311 _unitCache.evictAll(); 1312 _unitCache = new LruCache<String, ImageInfo>(cSize) { 1313 @Override 1314 protected int sizeOf(String key, ImageInfo ii) { 1315 return ii.getByteCount();// / 1024; 1316 } 1317 }; 1318 } 1319 //adjust tg cache 1320 synchronized (_SinglePointCacheMutex) { 1321 if(_tgCache != null) 1322 _tgCache.evictAll(); 1323 _tgCache = new LruCache<String, ImageInfo>(cSize) { 1324 @Override 1325 protected int sizeOf(String key, ImageInfo ii) { 1326 return ii.getByteCount();// / 1024; 1327 } 1328 }; 1329 } 1330 } 1331 } 1332 } 1333 if(sce != null && sce.getEventType().equals(SettingsChangedEvent.EventType_CacheToggled)) 1334 { 1335 if(cacheEnabled != RendererSettings.getInstance().getCacheEnabled()) 1336 { 1337 cacheEnabled = RendererSettings.getInstance().getCacheEnabled(); 1338 1339 if (cacheEnabled == false) 1340 { 1341 synchronized (_SinglePointCacheMutex) 1342 { 1343 if (_tgCache != null) 1344 _tgCache.evictAll(); 1345 _tgCache = null; 1346 } 1347 synchronized (_UnitCacheMutex) 1348 { 1349 if (_unitCache != null) 1350 _unitCache.evictAll(); 1351 _unitCache = null; 1352 } 1353 } 1354 else 1355 { 1356 int cSize = RendererSettings.getInstance().getCacheSize() / 2; 1357 synchronized (_SinglePointCacheMutex) 1358 { 1359 if(_tgCache != null) 1360 _tgCache.evictAll(); 1361 _tgCache = new LruCache<String, ImageInfo>(cSize) { 1362 @Override 1363 protected int sizeOf(String key, ImageInfo ii) { 1364 return ii.getByteCount();// / 1024; 1365 } 1366 }; 1367 } 1368 synchronized (_UnitCacheMutex) 1369 { 1370 if(_unitCache != null) 1371 _unitCache.evictAll(); 1372 _unitCache = new LruCache<String, ImageInfo>(cSize) { 1373 @Override 1374 protected int sizeOf(String key, ImageInfo ii) { 1375 return ii.getByteCount();// / 1024; 1376 } 1377 }; 1378 } 1379 } 1380 } 1381 } 1382 } 1383}