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.SVGSymbolInfo; 034import armyc2.c5isr.renderer.utilities.SettingsChangedEvent; 035import armyc2.c5isr.renderer.utilities.SettingsChangedEventListener; 036import armyc2.c5isr.renderer.utilities.SymbolDimensionInfo; 037import armyc2.c5isr.renderer.utilities.SymbolID; 038import armyc2.c5isr.renderer.utilities.SymbolUtilities; 039 040public class SinglePointRenderer implements SettingsChangedEventListener 041{ 042 043 private final String TAG = "SinglePointRenderer"; 044 private static SinglePointRenderer _instance = null; 045 046 private final Object _SinglePointCacheMutex = new Object(); 047 private final Object _UnitCacheMutex = new Object(); 048 049 private final Object _modifierFontMutex = new Object(); 050 private Paint _modifierFont = new Paint(); 051 private Paint _modifierOutlineFont = new Paint(); 052 private float _modifierDescent = 2; 053 private float _modifierFontHeight = 10; 054 private int _deviceDPI = 72; 055 056 //private LruCache<String, ImageInfo> _unitCache = new LruCache<String, ImageInfo>(15); 057 //private LruCache<String, ImageInfo> _tgCache = new LruCache<String, ImageInfo>(7); 058 private LruCache<String, ImageInfo> _unitCache = new LruCache<String, ImageInfo>(1024); 059 private LruCache<String, ImageInfo> _tgCache = new LruCache<String, ImageInfo>(1024); 060 private final int maxMemory = (int) (Runtime.getRuntime().maxMemory());// / 1024); 061 private int cacheSize = 5;//RendererSettings.getInstance().getCacheSize() / 2; 062 private int maxCachedEntrySize = cacheSize / 5; 063 private boolean cacheEnabled = RendererSettings.getInstance().getCacheEnabled(); 064 065 private SinglePointRenderer() 066 { 067 RendererSettings.getInstance().addEventListener(this); 068 069 //get modifier font values. 070 onSettingsChanged(new SettingsChangedEvent(SettingsChangedEvent.EventType_FontChanged)); 071 //set cache 072 onSettingsChanged(new SettingsChangedEvent(SettingsChangedEvent.EventType_CacheSizeChanged)); 073 074 } 075 076 public static synchronized SinglePointRenderer getInstance() 077 { 078 if (_instance == null) 079 { 080 _instance = new SinglePointRenderer(); 081 } 082 083 return _instance; 084 } 085 086 /** 087 * 088 * @param symbolID 089 * @param modifiers 090 * @return 091 */ 092 public ImageInfo RenderUnit(String symbolID, Map<String,String> modifiers, Map<String,String> attributes) 093 { 094 Color lineColor = SymbolUtilities.getLineColorOfAffiliation(symbolID); 095 Color fillColor = SymbolUtilities.getFillColorOfAffiliation(symbolID); 096 Color iconColor = null; 097 098 int alpha = -1; 099 100 101 //SVG values 102 String frameID = null; 103 String iconID = null; 104 String mod1ID = null; 105 String mod2ID = null; 106 SVGInfo siFrame = null; 107 SVGInfo siIcon = null; 108 SVGInfo siMod1 = null; 109 SVGInfo siMod2 = null; 110 SVG mySVG = null; 111 int top = 0; 112 int left = 0; 113 int width = 0; 114 int height = 0; 115 String svgStart = null; 116 String strSVG = null; 117 String strSVGFrame = null; 118 119 120 Rect symbolBounds = null; 121 Rect fullBounds = null; 122 Bitmap fullBMP = null; 123 124 boolean hasDisplayModifiers = false; 125 boolean hasTextModifiers = false; 126 127 int pixelSize = -1; 128 boolean keepUnitRatio = true; 129 boolean icon = false; 130 boolean noFrame = false; 131 132 int ver = SymbolID.getVersion(symbolID); 133 134 // <editor-fold defaultstate="collapsed" desc="Parse Attributes"> 135 try 136 { 137 138 if (attributes.containsKey(MilStdAttributes.PixelSize)) 139 { 140 pixelSize = Integer.parseInt(attributes.get(MilStdAttributes.PixelSize)); 141 } 142 else 143 { 144 pixelSize = RendererSettings.getInstance().getDefaultPixelSize(); 145 } 146 147 if (attributes.containsKey(MilStdAttributes.KeepUnitRatio)) 148 { 149 keepUnitRatio = Boolean.parseBoolean(attributes.get(MilStdAttributes.KeepUnitRatio)); 150 } 151 152 if (attributes.containsKey(MilStdAttributes.DrawAsIcon)) 153 { 154 icon = Boolean.parseBoolean(attributes.get(MilStdAttributes.DrawAsIcon)); 155 } 156 157 if (icon)//icon won't show modifiers or display icons 158 { 159 //TODO: symbolID modifications as necessary 160 keepUnitRatio = false; 161 hasDisplayModifiers = false; 162 hasTextModifiers = false; 163 //symbolID = symbolID.substring(0, 10) + "-----"; 164 } 165 else 166 { 167 hasDisplayModifiers = ModifierRenderer.hasDisplayModifiers(symbolID, modifiers); 168 hasTextModifiers = ModifierRenderer.hasTextModifiers(symbolID, modifiers); 169 } 170 171 if (attributes.containsKey(MilStdAttributes.LineColor)) 172 { 173 lineColor = new Color(attributes.get(MilStdAttributes.LineColor)); 174 } 175 if (attributes.containsKey(MilStdAttributes.FillColor)) 176 { 177 fillColor = new Color(attributes.get(MilStdAttributes.FillColor)); 178 } 179 if (attributes.containsKey(MilStdAttributes.IconColor)) 180 { 181 iconColor = new Color(attributes.get(MilStdAttributes.IconColor)); 182 }//*/ 183 if (attributes.containsKey(MilStdAttributes.Alpha)) 184 { 185 alpha = Integer.parseInt(attributes.get(MilStdAttributes.Alpha)); 186 } 187 188 } 189 catch (Exception excModifiers) 190 { 191 ErrorLogger.LogException("SinglePointRenderer", "RenderUnit", excModifiers); 192 } 193 // </editor-fold> 194 195 try 196 { 197 198 ImageInfo ii = null; 199 String key = makeCacheKey(symbolID, lineColor.toInt(), fillColor.toInt(), String.valueOf(iconColor),pixelSize, keepUnitRatio, false); 200 201 //see if it's in the cache 202 if(_unitCache != null) { 203 ii = _unitCache.get(key); 204 //safety check in case bitmaps are getting recycled while still in the LRU cache 205 if (ii != null && ii.getImage() != null && ii.getImage().isRecycled()) { 206 synchronized (_UnitCacheMutex) { 207 _unitCache.remove(key); 208 ii = null; 209 } 210 } 211 } 212 //if not, generate symbol 213 if (ii == null)//*/ 214 { 215 int version = SymbolID.getVersion(symbolID); 216 //Get SVG pieces of symbol 217 frameID = SVGLookup.getFrameID(symbolID); 218 iconID = SVGLookup.getMainIconID(symbolID); 219 mod1ID = SVGLookup.getMod1ID(symbolID); 220 mod2ID = SVGLookup.getMod2ID(symbolID); 221 siFrame = SVGLookup.getInstance().getSVGLInfo(frameID, version); 222 siIcon = SVGLookup.getInstance().getSVGLInfo(iconID, version); 223 224 if(siFrame == null) 225 { 226 frameID = SVGLookup.getFrameID(SymbolUtilities.reconcileSymbolID(symbolID)); 227 siFrame = SVGLookup.getInstance().getSVGLInfo(frameID, version); 228 if(siFrame == null)//still no match, get unknown frame 229 { 230 frameID = SVGLookup.getFrameID(SymbolID.setSymbolSet(symbolID,SymbolID.SymbolSet_Unknown)); 231 siFrame = SVGLookup.getInstance().getSVGLInfo(frameID, version); 232 } 233 } 234 235 if(siIcon == null) 236 { 237 if(SymbolID.getSymbolSet(symbolID) == SymbolID.SymbolSet_Unknown) 238 siIcon = SVGLookup.getInstance().getSVGLInfo("00000000", version);//question mark 239 /*else if(iconID.substring(2,8).equals("000000")==false && MSLookup.getInstance().getMSLInfo(symbolID) == null) 240 siIcon = SVGLookup.getInstance().getSVGLInfo("98100000", version);//inverted question mark//*/ 241 } 242 243 if(RendererSettings.getInstance().getScaleMainIcon()) 244 siIcon = RendererUtilities.scaleIcon(symbolID,siIcon); 245 246 siMod1 = SVGLookup.getInstance().getSVGLInfo(mod1ID, version); 247 siMod2 = SVGLookup.getInstance().getSVGLInfo(mod2ID, version); 248 top = Math.round(siFrame.getBbox().top); 249 left = Math.round(siFrame.getBbox().left); 250 width = Math.round(siFrame.getBbox().width()); 251 height = Math.round(siFrame.getBbox().height()); 252 if(siFrame.getBbox().bottom > 400) 253 svgStart = "<svg xmlns:svg=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewBox=\"0 0 612 792\">"; 254 else 255 svgStart = "<svg xmlns:svg=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewBox=\"0 0 400 400\">"; 256 257 //update line and fill color of frame SVG 258 if(lineColor != null || fillColor != null) 259 strSVGFrame = RendererUtilities.setSVGFrameColors(symbolID,siFrame.getSVG(),lineColor,fillColor); 260 else 261 strSVGFrame = siFrame.getSVG(); 262 263 if(frameID.equals("octagon"))//for the 1 unit symbol that doesn't have a frame: 30 + 15000 264 { 265 noFrame = true; 266 strSVGFrame = strSVGFrame.replaceFirst("<g id=\"octagon\">", "<g id=\"octagon\" display=\"none\">"); 267 } 268 269 270 //get SVG dimensions and target dimensions 271 symbolBounds = RectUtilities.makeRect(left,top,width,height); 272 Rect rect = new Rect(symbolBounds); 273 float ratio = -1; 274 275 if (pixelSize > 0 && keepUnitRatio == true) 276 { 277 float heightRatio = SymbolUtilities.getUnitRatioHeight(symbolID); 278 float widthRatio = SymbolUtilities.getUnitRatioWidth(symbolID); 279 280 if(noFrame == true)//using octagon with display="none" as frame for a 1x1 shape 281 { 282 heightRatio = 1.0f; 283 widthRatio = 1.0f; 284 } 285 286 if (heightRatio > widthRatio) 287 { 288 pixelSize = (int) ((pixelSize / 1.5f) * heightRatio); 289 } 290 else 291 { 292 pixelSize = (int) ((pixelSize / 1.5f) * widthRatio); 293 } 294 } 295 if (pixelSize > 0) 296 { 297 float p = pixelSize; 298 float h = rect.height(); 299 float w = rect.width(); 300 301 ratio = Math.min((p / h), (p / w)); 302 303 symbolBounds = RectUtilities.makeRect(0f, 0f, w * ratio, h * ratio); 304 } 305 306 //center of octagon is the center of all unit symbols 307 Point centerOctagon = new Point(306, 396); 308 centerOctagon.offset(-left,-top);//offset for the symbol bounds x,y 309 //scale center point by same ratio as the symbol 310 centerOctagon = new Point((int)(centerOctagon.x * ratio), (int)(centerOctagon.y * ratio)); 311 312 //set centerpoint of the image 313 Point centerPoint = centerOctagon; 314 Point centerCache = new Point(centerOctagon.x, centerOctagon.y); 315 316 //y offset to get centerpoint so we set back to zero when done. 317 symbolBounds.top = 0; 318 319 //Create destination BMP 320 Bitmap bmp = Bitmap.createBitmap(symbolBounds.width(), symbolBounds.height(), Config.ARGB_8888); 321 Canvas canvas = new Canvas(bmp); 322 323 //draw unit from SVG 324 StringBuilder sb = new StringBuilder(); 325 sb.append(svgStart); 326 327 if(strSVGFrame != null) 328 sb.append(strSVGFrame); 329 330 String color = ""; 331 String strokeFill = ""; 332 if(iconColor != null) 333 { 334 //make sure string is properly formatted. 335 color = RendererUtilities.colorToHexString(iconColor,false); 336 if(color != null && color != "#000000" && color != "") 337 strokeFill = " fill=\"" + color + "\" "; 338 else 339 color = null; 340 } 341 String unit = "<g" + strokeFill + ">"; 342 if (siIcon != null) 343 unit += (siIcon.getSVG()); 344 if (siMod1 != null) 345 unit += (siMod1.getSVG()); 346 if (siMod2 != null) 347 unit += (siMod2.getSVG()); 348 if(iconColor != null && color != null && color != "") 349 unit = unit.replaceAll("#000000",color); 350 sb.append(unit + "</g>"); 351 352 sb.append("</svg>"); 353 354 strSVG = sb.toString(); 355 356 mySVG = SVG.getFromString(strSVG); 357 mySVG.setDocumentViewBox(left,top,width,height); 358 mySVG.renderToCanvas(canvas); 359 360 361 //adjust centerpoint for HQStaff if present 362 if (SymbolUtilities.isHQ(symbolID)) 363 { 364 PointF point1 = new PointF(); 365 PointF point2 = new PointF(); 366 int affiliation = SymbolID.getAffiliation(symbolID); 367 int ss = SymbolID.getStandardIdentity(symbolID); 368 if (affiliation == SymbolID.StandardIdentity_Affiliation_Friend 369 || affiliation == SymbolID.StandardIdentity_Affiliation_AssumedFriend 370 || affiliation == SymbolID.StandardIdentity_Affiliation_Neutral 371 || ss == 15 || ss == 16)//exercise joker or faker 372 { 373 point1.x = (symbolBounds.left); 374 point1.y = symbolBounds.top + (symbolBounds.height()); 375 point2.x = point1.x; 376 point2.y = point1.y + symbolBounds.height(); 377 } 378 else 379 { 380 point1.x = (symbolBounds.left + 1); 381 point1.y = symbolBounds.top + (symbolBounds.height() / 2); 382 point2.x = point1.x; 383 point2.y = point1.y + symbolBounds.height(); 384 } 385 centerPoint = new Point((int) point2.x, (int) point2.y); 386 } 387 388 ii = new ImageInfo(bmp, centerPoint, symbolBounds); 389 390 if(cacheEnabled && icon == false && bmp.getAllocationByteCount() <= maxCachedEntrySize) 391 { 392 synchronized (_UnitCacheMutex) 393 { 394 if(_unitCache != null && _unitCache.get(key) == null) 395 _unitCache.put(key, new ImageInfo(bmp, new Point(centerCache), new Rect(symbolBounds))); 396 } 397 } 398 399 /*if(icon == false && pixelSize <= 100) 400 { 401 _unitCache.put(key, new ImageInfo(bmp, new Point(centerCache), new Rect(symbolBounds))); 402 }//*/ 403 } 404 405 ImageInfo iiNew = null; 406 SymbolDimensionInfo sdiTemp = null; 407 //////////////////////////////////////////////////////////////////// 408 //process display modifiers 409 if (hasDisplayModifiers) 410 { 411 sdiTemp = ModifierRenderer.processUnitDisplayModifiers( ii, symbolID, modifiers, hasTextModifiers, attributes); 412 iiNew = (sdiTemp instanceof ImageInfo ? (ImageInfo)sdiTemp : null); 413 sdiTemp = null; 414 } 415 416 if (iiNew != null) 417 { 418 ii = iiNew; 419 } 420 iiNew = null; 421 422 //process text modifiers 423 if (hasTextModifiers) 424 { 425 sdiTemp = ModifierRenderer.processSPTextModifiers(ii, symbolID, modifiers, attributes); 426 } 427 428 iiNew = (sdiTemp instanceof ImageInfo ? (ImageInfo)sdiTemp : null); 429 if (iiNew != null) 430 { 431 ii = iiNew; 432 } 433 iiNew = null; 434 435 if(modifiers != null) 436 ii = (ImageInfo) ModifierRenderer.processSpeedLeader(ii,symbolID,modifiers,attributes); 437 438 //cleanup/////////////////////////////////////////////////////////// 439 //bmp.recycle(); 440 symbolBounds = null; 441 fullBMP = null; 442 fullBounds = null; 443 mySVG = null; 444 //////////////////////////////////////////////////////////////////// 445 446 if (icon == true) 447 { 448 return ii.getSquareImageInfo(); 449 } 450 else 451 { 452 return ii; 453 } 454 455 } 456 catch (Exception exc) 457 { 458 ErrorLogger.LogException("SinglePointRenderer", "RenderUnit", exc); 459 } 460 return null; 461 } 462 463 /** 464 * 465 * @param symbolID 466 * @param modifiers 467 * @return 468 */ 469 @SuppressWarnings("unused") 470 public ImageInfo RenderSP(String symbolID, Map<String,String> modifiers, Map<String,String> attributes) 471 { 472 ImageInfo temp = null; 473 String basicSymbolID = null; 474 475 Color lineColor = SymbolUtilities.getDefaultLineColor(symbolID); 476 Color fillColor = null;//SymbolUtilities.getFillColorOfAffiliation(symbolID); 477 int outlineWidth = RendererUtilities.calculateOutlineWidth(); 478 int alpha = -1; 479 480 481 //SVG rendering variables 482 MSInfo msi = null; 483 String iconID = null; 484 SVGInfo siIcon = null; 485 String mod1ID = null; 486 SVGInfo siMod1 = null; 487 int top = 0; 488 int left = 0; 489 int width = 0; 490 int height = 0; 491 String svgStart = null; 492 String strSVG = null; 493 SVG mySVG = null; 494 495 float ratio = 0; 496 497 RectF symbolBounds = null; 498 RectF imageBounds = null; 499 500 Bitmap fullBMP = null; 501 502 boolean drawAsIcon = false; 503 int pixelSize = -1; 504 boolean keepUnitRatio = true; 505 boolean hasDisplayModifiers = false; 506 boolean hasTextModifiers = false; 507 boolean drawCustomOutline = false; 508 509 msi = MSLookup.getInstance().getMSLInfo(symbolID); 510 int ss = SymbolID.getSymbolSet(symbolID); 511 int ec = SymbolID.getEntityCode(symbolID); 512 int mod1 = 0; 513 int drawRule = 0; 514 if(msi!=null){drawRule = msi.getDrawRule();} 515 boolean hasAPFill = false; 516 if(RendererSettings.getInstance().getActionPointDefaultFill()) { 517 if (SymbolUtilities.isActionPoint(symbolID) || //action points 518 ec/100 == 2135 || //sonobuoy 519 ec == 180100 || ec == 180200 || ec == 180400) //ACP, CCP, PUP 520 { 521 if (SymbolID.getSymbolSet(symbolID) == SymbolID.SymbolSet_ControlMeasure) { 522 lineColor = Color.BLACK; 523 hasAPFill = true; 524 } 525 } 526 } 527 528 try 529 { 530 if (modifiers == null) 531 { 532 modifiers = new HashMap<>(); 533 } 534 535 536 //get symbol info 537 538 msi = MSLookup.getInstance().getMSLInfo(symbolID); 539 540 if (msi == null)//if lookup fails, fix code/use unknown symbol code. 541 { 542 //TODO: change symbolID to Action Point with bad symbolID in the T or H field 543 } 544 545 /* Fills built into SVG 546 if (SymbolUtilities.hasDefaultFill(symbolID)) 547 { 548 fillColor = SymbolUtilities.getFillColorOfAffiliation(symbolID); 549 } 550 if (SymbolUtilities.isTGSPWithFill(symbolID)) 551 { 552 fillID = SymbolUtilities.getTGFillSymbolCode(symbolID); 553 if (fillID != null) 554 { 555 charFillIndex = SinglePointLookup.getInstance().getCharCodeFromSymbol(fillID, symStd); 556 } 557 } 558 else if (SymbolUtilities.isWeatherSPWithFill(symbolID)) 559 { 560 charFillIndex = charFrameIndex + 1; 561 fillColor = SymbolUtilities.getFillColorOfWeather(symbolID); 562 563 }//*/ 564 565 if (attributes != null) 566 { 567 if (attributes.containsKey(MilStdAttributes.KeepUnitRatio)) 568 { 569 keepUnitRatio = Boolean.parseBoolean(attributes.get(MilStdAttributes.KeepUnitRatio)); 570 } 571 572 if (attributes.containsKey(MilStdAttributes.LineColor)) 573 { 574 lineColor = RendererUtilities.getColorFromHexString(attributes.get(MilStdAttributes.LineColor)); 575 } 576 577 if (attributes.containsKey(MilStdAttributes.FillColor)) 578 { 579 fillColor = RendererUtilities.getColorFromHexString(attributes.get(MilStdAttributes.FillColor)); 580 } 581 582 if (attributes.containsKey(MilStdAttributes.Alpha)) 583 { 584 alpha = Integer.parseInt(attributes.get(MilStdAttributes.Alpha)); 585 } 586 587 if (attributes.containsKey(MilStdAttributes.DrawAsIcon)) 588 { 589 drawAsIcon = Boolean.parseBoolean(attributes.get(MilStdAttributes.DrawAsIcon)); 590 } 591 592 if (attributes.containsKey(MilStdAttributes.PixelSize)) 593 { 594 pixelSize = Integer.parseInt(attributes.get(MilStdAttributes.PixelSize)); 595 } 596 else 597 { 598 pixelSize = RendererSettings.getInstance().getDefaultPixelSize(); 599 } 600 /*if(keepUnitRatio == true && msi.getSymbolSet() == SymbolID.SymbolSet_ControlMeasure && msi.getGeometry().equalsIgnoreCase("point")) 601 { 602 if(msi.getDrawRule() == DrawRules.POINT1)//Action Points 603 pixelSize = (int)Math.ceil((pixelSize/1.5f) * 2.0f); 604 else if(SymbolID.getSymbolSet(symbolID)==SymbolID.SymbolSet_ControlMeasure && 605 ec/100 == 2135)//Sonobuoy 606 { 607 pixelSize = (int)Math.ceil((pixelSize/1.5f) * 2.0f); 608 } 609 else 610 pixelSize = (int)Math.ceil((pixelSize/1.5f) * 1.2f); 611 }//*/ 612 613 if(!(drawAsIcon==true || hasAPFill==true))//don't outline icons because they're not going on the map and icons with fills don't need it 614 { 615 if (attributes.containsKey(MilStdAttributes.OutlineSymbol)) 616 drawCustomOutline = Boolean.parseBoolean(attributes.get(MilStdAttributes.OutlineSymbol)); 617 else 618 drawCustomOutline = RendererSettings.getInstance().getOutlineSPControlMeasures(); 619 620 //Protection of Cultural Property doesn't get outlined 621 if(ss==25 && ec >= 360000 && ec < 360400) 622 drawCustomOutline = false; 623 } 624 625 if(SymbolUtilities.isMultiPoint(symbolID)) 626 drawCustomOutline=false;//icon previews for multipoints do not need outlines since they shouldn't be on the map 627 } 628 629 if (drawAsIcon)//icon won't show modifiers or display icons 630 { 631 keepUnitRatio = false; 632 hasDisplayModifiers = false; 633 hasTextModifiers = false; 634 drawCustomOutline = false; 635 } 636 else 637 { 638 hasDisplayModifiers = ModifierRenderer.hasDisplayModifiers(symbolID, modifiers); 639 hasTextModifiers = ModifierRenderer.hasTextModifiers(symbolID, modifiers); 640 } 641 642 //Check if we need to set 'N' to "ENY" 643 int aff = SymbolID.getAffiliation(symbolID); 644 //int ss = msi.getSymbolSet(); 645 if (ss == SymbolID.SymbolSet_ControlMeasure && 646 (aff == SymbolID.StandardIdentity_Affiliation_Hostile_Faker || 647 aff == SymbolID.StandardIdentity_Affiliation_Suspect_Joker ) && 648 modifiers.containsKey(Modifiers.N_HOSTILE) && 649 drawAsIcon == false) 650 { 651 modifiers.put(Modifiers.N_HOSTILE, "ENY"); 652 } 653 654 } 655 catch (Exception excModifiers) 656 { 657 ErrorLogger.LogException("SinglePointRenderer", "RenderSP", excModifiers); 658 } 659 660 try 661 { 662 ImageInfo ii = null; 663 int intFill = -1; 664 if (fillColor != null) 665 { 666 intFill = fillColor.toInt(); 667 } 668 669 670 if(msi.getSymbolSet() != SymbolID.SymbolSet_ControlMeasure) 671 lineColor = Color.BLACK;//color isn't black but should be fine for weather since colors can't be user defined. 672 673 674 675 if (SymbolID.getSymbolSet(symbolID)==SymbolID.SymbolSet_ControlMeasure && SymbolID.getEntityCode(symbolID) == 270701)//static depiction 676 { 677 //add mine fill to image 678 mod1 = SymbolID.getModifier1(symbolID); 679 if (!(mod1 >= 13 && mod1 <= 50)) 680 symbolID = SymbolID.setModifier1(symbolID, 13); 681 } 682 683 String key = makeCacheKey(symbolID, lineColor.toInt(), intFill, pixelSize, keepUnitRatio, drawCustomOutline); 684 685 //see if it's in the cache 686 if(_tgCache != null) { 687 ii = _tgCache.get(key); 688 //safety check in case bitmaps are getting recycled while still in the LRU cache 689 if (ii != null && ii.getImage() != null && ii.getImage().isRecycled()) { 690 synchronized (_SinglePointCacheMutex) { 691 _tgCache.remove(key); 692 ii = null; 693 } 694 } 695 } 696 697 //if not, generate symbol. 698 if (ii == null)//*/ 699 { 700 int version = SymbolID.getVersion(symbolID); 701 //check symbol size//////////////////////////////////////////// 702 Rect rect = null; 703 iconID = SVGLookup.getMainIconID(symbolID); 704 siIcon = SVGLookup.getInstance().getSVGLInfo(iconID, version); 705 if(siIcon==null) { 706 return null; 707 } 708 mod1ID = SVGLookup.getMod1ID(symbolID); 709 siMod1 = SVGLookup.getInstance().getSVGLInfo(mod1ID, version); 710 float borderPadding = 0; 711 if (drawCustomOutline) { 712 borderPadding = (int)Math.ceil(outlineWidth/2f); 713 if(borderPadding % 2 > 0) 714 borderPadding++; 715 } 716 top = (int)Math.floor(siIcon.getBbox().top); 717 left = (int)Math.floor(siIcon.getBbox().left); 718 width = (int)Math.ceil(siIcon.getBbox().width() + (siIcon.getBbox().left - left)); 719 height = (int)Math.ceil(siIcon.getBbox().height() + (siIcon.getBbox().top - top)); 720 if(siIcon.getBbox().bottom > 400) 721 svgStart = "<svg xmlns:svg=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewBox=\"0 0 612 792\">"; 722 else 723 svgStart = "<svg xmlns:svg=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewBox=\"0 0 400 400\">"; 724 725 String strSVGIcon = null; 726 727 if(keepUnitRatio) 728 { 729 double scaler = Math.max(width/(float)height, height/(float)width); 730 if (scaler < 1.2) 731 scaler = 1.2; 732 if (scaler > 2) 733 scaler = 2; 734 735 if(!SymbolUtilities.isCBRNEvent(symbolID)) 736 pixelSize = (int) Math.ceil((pixelSize / 1.5f) * scaler); 737 738 /* 739 double min = Math.min(width/(float)height, height/(float)width); 740 if (min < 0.6)//Rectangle 741 pixelSize = (int) Math.ceil((pixelSize / 1.5f) * 2.0f); 742 else if(min < 0.85) 743 pixelSize = (int) Math.ceil((pixelSize / 1.5f) * 1.8f); 744 else //more of a square 745 pixelSize = (int) Math.ceil((pixelSize / 1.5f) * 1.2f);//*/ 746 } 747 748 if(hasAPFill) //action points and a few others //Sonobuoy //ACP, CCP, PUP 749 { 750 String apFill; 751 if(fillColor != null) 752 apFill = RendererUtilities.colorToHexString(fillColor,false); 753 else 754 apFill = RendererUtilities.colorToHexString(SymbolUtilities.getFillColorOfAffiliation(symbolID),false); 755 siIcon = new SVGInfo(siIcon.getID(),siIcon.getBbox(), siIcon.getSVG().replaceAll("fill=\"none\"","fill=\"" + apFill + "\"")); 756 } 757 758 //Set dash array depending on affiliation and status 759 siIcon = RendererUtilities.setAffiliationDashArray(symbolID, siIcon); 760 761 //Generate Affiliation Planned Circle for version 16 762 SVGSymbolInfo circle = ModifierRenderer.createPlannedCircle(siIcon.getBbox(),symbolID); 763 764 if(circle != null) 765 { 766 //workaround for bug in androidsvg: dash-array on circle seems to start at 0 degreeds instead of 90 degrees 767 //submitted ticket here: https://github.com/BigBadaboom/androidsvg/issues/297 768 String rotation = " rotate(90) scale"; 769 circle = new SVGSymbolInfo(circle.getSVG().replace("scale",rotation),circle.getCenterPointF(),circle.getSymbolBoundsF(),circle.getImageBoundsF()); 770 771 symbolBounds = circle.getSymbolBoundsF(); 772 top = (int)Math.floor(circle.getImageBoundsF().top); 773 left = (int)Math.floor(circle.getImageBoundsF().left); 774 width = (int)Math.round(Math.ceil(circle.getImageBoundsF().width() + (circle.getImageBoundsF().left - left))); 775 height = (int)Math.round(Math.ceil(circle.getImageBoundsF().height() + (circle.getImageBoundsF().top - top))); 776 if(keepUnitRatio) 777 pixelSize = (int)(pixelSize * (width / Math.max(siIcon.getBbox().width(),siIcon.getBbox().height()))); 778 String newSVG = siIcon.getSVG().substring(0,siIcon.getSVG().lastIndexOf("</g>")); 779 newSVG += circle.getSVG() + "</g>"; 780 siIcon = new SVGInfo(siIcon.getID(),circle.getImageBoundsF(), newSVG); 781 } 782 783 //update line and fill color of frame SVG 784 if(msi.getSymbolSet() == SymbolID.SymbolSet_ControlMeasure && (lineColor != null || fillColor != null)) { 785 if (drawCustomOutline) { 786 // create outline with larger stroke-width first (if selected) 787 strSVGIcon = RendererUtilities.setSVGSPCMColors(symbolID, siIcon.getSVG(), RendererUtilities.getIdealOutlineColor(lineColor), fillColor, true,siIcon.getBbox(),pixelSize,outlineWidth); 788 } 789 790 // append normal symbol SVG to be layered on top of outline 791 strSVGIcon += RendererUtilities.setSVGSPCMColors(symbolID, siIcon.getSVG(), lineColor, fillColor); 792 } 793 else//weather symbol (don't change color of weather graphics) 794 strSVGIcon = siIcon.getSVG(); 795 796 //If symbol is Static Depiction, add internal mine graphic based on sector modifier 1 797 if(SymbolID.getEntityCode(symbolID) == 270701 && siMod1 != null) 798 { 799 if (drawCustomOutline) { 800 // create outline with larger stroke-width first (if selected) 801 strSVGIcon += RendererUtilities.setSVGSPCMColors(mod1ID, siMod1.getSVG(), RendererUtilities.getIdealOutlineColor(RendererUtilities.getColorFromHexString("#00A651")), RendererUtilities.getColorFromHexString("#00A651"), true,siIcon.getBbox(),pixelSize,outlineWidth); 802 } 803 //strSVGIcon += siMod1.getSVG(); 804 strSVGIcon += RendererUtilities.setSVGSPCMColors(mod1ID, siMod1.getSVG(), lineColor, fillColor); 805 } 806 807 if (pixelSize > 0) 808 { 809 imageBounds = RectUtilities.makeRectF(left,top,width,height); 810 if(circle != null) 811 symbolBounds = circle.getSymbolBoundsF(); 812 else 813 symbolBounds = new RectF(imageBounds); 814 815 rect = RectUtilities.makeRectFromRectF(imageBounds); 816 817 //adjust size 818 float p = pixelSize; 819 float h = rect.height(); 820 float w = rect.width(); 821 822 ratio = Math.min((p / h), (p / w)); 823 824 symbolBounds = RectUtilities.makeRectF((symbolBounds.left - imageBounds.left)*ratio, (symbolBounds.top - imageBounds.top)*ratio, symbolBounds.width() * ratio, symbolBounds.height() * ratio); 825 imageBounds = RectUtilities.makeRectF(0f, 0f, w * ratio, h * ratio); 826 827 //make sure border padding isn't excessive. 828 w = symbolBounds.width(); 829 h = symbolBounds.height(); 830 831 /*if(borderPadding > 0) { 832 if (h / (h + borderPadding) > 0.10) { 833 borderPadding = (float) (h * 0.1); 834 } else if (w / (w + borderPadding) > 0.10) { 835 borderPadding = (float) (w * 0.1); 836 } 837 }*/ 838 } 839 840 841 //grow size SVG to accommodate the outline we added 842 int offset = 0; 843 if(drawCustomOutline) 844 { 845 RectUtilities.grow(rect, (int)Math.ceil(borderPadding / ratio)); 846 offset = (int)Math.ceil(borderPadding); 847 }//*/ 848 849 //Draw glyphs to bitmap 850 imageBounds = RectUtilities.makeRectF(0f, 0f, (int)(imageBounds.width() + 0.5f + (borderPadding)*2), (int)(imageBounds.height() + 0.5f + (borderPadding)*2)); 851 RectUtilities.shift(symbolBounds,offset,offset); 852 Bitmap bmp = Bitmap.createBitmap(Math.round(imageBounds.width()), Math.round(imageBounds.height()), Config.ARGB_8888); 853 Canvas canvas = new Canvas(bmp); 854 855 856 if(SymbolUtilities.isActionPoint(symbolID))//smooth out action points 857 strSVGIcon = "/n<g stroke-linejoin=\"round\" >/n" + strSVGIcon + "/n</g>"; 858 859 strSVG = svgStart + strSVGIcon + "</svg>"; 860 mySVG = SVG.getFromString(strSVG); 861 //mySVG.setDocumentViewBox(left,top,width,height); 862 mySVG.setDocumentViewBox(rect.left,rect.top,rect.width(),rect.height()); 863 mySVG.renderToCanvas(canvas); 864 865 Point centerPoint = SymbolUtilities.getCMSymbolAnchorPoint(symbolID,symbolBounds); 866 867 //now that we're done building symbol and applying outlines if needed, 868 //imageBounds and symbolBounds can be considered to be the same 869 symbolBounds = new RectF(imageBounds);//circle.getSymbolBounds(); 870 871 ii = new ImageInfo(bmp, new Point(Math.round(centerPoint.x),Math.round(centerPoint.y)), RectUtilities.makeRectFromRectF(symbolBounds)); 872 873 if(cacheEnabled && !drawAsIcon && bmp.getAllocationByteCount() <= maxCachedEntrySize) 874 { 875 synchronized (_SinglePointCacheMutex) 876 { 877 if(_tgCache.get(key) == null) 878 _tgCache.put(key, ii); 879 } 880 } 881 /*if (drawAsIcon == false && pixelSize <= 100) 882 883 _tgCache.put(key, ii); 884 }//*/ 885 } 886 887 //Process Modifiers 888 ImageInfo iiNew = null; 889 if (drawAsIcon == false && (hasTextModifiers || hasDisplayModifiers)) 890 { 891 SymbolDimensionInfo sdiTemp = null; 892 if (SymbolUtilities.isSPWithSpecialModifierLayout(symbolID))//(SymbolUtilitiesD.isTGSPWithSpecialModifierLayout(symbolID)) 893 { 894 sdiTemp = ModifierRenderer.ProcessTGSPWithSpecialModifierLayout(ii, symbolID, modifiers, attributes, lineColor); 895 } 896 else 897 { 898 sdiTemp = ModifierRenderer.ProcessTGSPModifiers(ii, symbolID, modifiers, attributes, lineColor); 899 } 900 iiNew = (sdiTemp instanceof ImageInfo ? (ImageInfo)sdiTemp : null); 901 } 902 903 if (iiNew != null) 904 { 905 ii = iiNew; 906 } 907 908 //cleanup 909 //bmp.recycle(); 910 symbolBounds = null; 911 fullBMP = null; 912 imageBounds = null; 913 mySVG = null; 914 915 916 if (drawAsIcon) 917 { 918 return ii.getSquareImageInfo(); 919 } 920 else 921 { 922 return ii; 923 } 924 925 } 926 catch (Exception exc) 927 { 928 ErrorLogger.LogException("SinglePointRenderer", "RenderSP(" + SymbolUtilities.getBasicSymbolID(symbolID) + ")", exc); 929 } 930 return null; 931 } 932 933 934 /** 935 * 936 * @param symbolID 937 * @return 938 */ 939 @SuppressWarnings("unused") 940 public ImageInfo RenderModifier(String symbolID, Map<String,String> attributes) 941 { 942 ImageInfo temp = null; 943 String basicSymbolID = null; 944 945 Color lineColor = null; 946 Color fillColor = null;//SymbolUtilities.getFillColorOfAffiliation(symbolID); 947 948 int outlineWidth = RendererUtilities.calculateOutlineWidth(); 949 950 int alpha = -1; 951 952 953 //SVG rendering variables 954 MSInfo msi = null; 955 String iconID = null; 956 SVGInfo siIcon = null; 957 int top = 0; 958 int left = 0; 959 int width = 0; 960 int height = 0; 961 String svgStart = null; 962 String strSVG = null; 963 SVG mySVG = null; 964 965 float ratio = 0; 966 967 Rect symbolBounds = null; 968 RectF fullBounds = null; 969 Bitmap fullBMP = null; 970 971 boolean drawAsIcon = false; 972 int pixelSize = -1; 973 boolean keepUnitRatio = true; 974 boolean hasDisplayModifiers = false; 975 boolean hasTextModifiers = false; 976 int symbolOutlineWidth = RendererSettings.getInstance().getSinglePointSymbolOutlineWidth(); 977 boolean drawCustomOutline = false; 978 979 try 980 { 981 982 msi = MSLookup.getInstance().getMSLInfo(symbolID); 983 if (attributes != null) 984 { 985 if (attributes.containsKey(MilStdAttributes.KeepUnitRatio)) 986 { 987 keepUnitRatio = Boolean.parseBoolean(attributes.get(MilStdAttributes.KeepUnitRatio)); 988 } 989 990 if (attributes.containsKey(MilStdAttributes.LineColor)) 991 { 992 lineColor = RendererUtilities.getColorFromHexString(attributes.get(MilStdAttributes.LineColor)); 993 } 994 995 if (attributes.containsKey(MilStdAttributes.FillColor)) 996 { 997 fillColor = RendererUtilities.getColorFromHexString(attributes.get(MilStdAttributes.FillColor)); 998 } 999 1000 if (attributes.containsKey(MilStdAttributes.Alpha)) 1001 { 1002 alpha = Integer.parseInt(attributes.get(MilStdAttributes.Alpha)); 1003 } 1004 1005 if (attributes.containsKey(MilStdAttributes.DrawAsIcon)) 1006 { 1007 drawAsIcon = Boolean.parseBoolean(attributes.get(MilStdAttributes.DrawAsIcon)); 1008 } 1009 1010 if (attributes.containsKey(MilStdAttributes.PixelSize)) 1011 { 1012 pixelSize = Integer.parseInt(attributes.get(MilStdAttributes.PixelSize)); 1013 if(msi.getSymbolSet() == SymbolID.SymbolSet_ControlMeasure) 1014 { 1015 if(SymbolID.getEntityCode(symbolID)==270701)//static depiction 1016 pixelSize = (int)(pixelSize * 0.9);//try to scale to be somewhat in line with units 1017 } 1018 } 1019 1020 if(drawAsIcon==false)//don't outline icons because they're not going on the map 1021 { 1022 if(attributes.containsKey(MilStdAttributes.OutlineSymbol)) 1023 drawCustomOutline = Boolean.parseBoolean(attributes.get(MilStdAttributes.OutlineSymbol)); 1024 else 1025 drawCustomOutline = RendererSettings.getInstance().getOutlineSPControlMeasures(); 1026 } 1027 1028 if(SymbolUtilities.isMultiPoint(symbolID)) 1029 drawCustomOutline=false;//icon previews for multipoints do not need outlines since they shouldn't be on the map 1030 1031 /*if (attributes.containsKey(MilStdAttributes.OutlineWidth)>=0) 1032 symbolOutlineWidth = Integer.parseInt(attributes.get(MilStdAttributes.OutlineWidth));//*/ 1033 } 1034 1035 int outlineOffset = symbolOutlineWidth; 1036 if (drawCustomOutline && outlineOffset > 2) 1037 { 1038 outlineOffset = (outlineOffset - 1) / 2; 1039 } 1040 else 1041 { 1042 outlineOffset = 0; 1043 } 1044 1045 } 1046 catch (Exception excModifiers) 1047 { 1048 ErrorLogger.LogException("SinglePointRenderer", "RenderModifier", excModifiers); 1049 } 1050 1051 try 1052 { 1053 ImageInfo ii = null; 1054 int intFill = -1; 1055 if (fillColor != null) 1056 { 1057 intFill = fillColor.toInt(); 1058 } 1059 1060 1061 if(msi.getSymbolSet() != SymbolID.SymbolSet_ControlMeasure) 1062 lineColor = Color.BLACK;//color isn't black but should be fine for weather since colors can't be user defined. 1063 1064 1065 //if not, generate symbol 1066 if (ii == null)//*/ 1067 { 1068 int version = SymbolID.getVersion(symbolID); 1069 //check symbol size//////////////////////////////////////////// 1070 Rect rect = null; 1071 1072 iconID = SVGLookup.getMod1ID(symbolID); 1073 siIcon = SVGLookup.getInstance().getSVGLInfo(iconID, version); 1074 top = Math.round(siIcon.getBbox().top); 1075 left = Math.round(siIcon.getBbox().left); 1076 width = Math.round(siIcon.getBbox().width()); 1077 height = Math.round(siIcon.getBbox().height()); 1078 if(siIcon.getBbox().bottom > 400) 1079 svgStart = "<svg xmlns:svg=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewBox=\"0 0 612 792\">"; 1080 else 1081 svgStart = "<svg xmlns:svg=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewBox=\"0 0 400 400\">"; 1082 1083 String strSVGIcon = null; 1084 String strSVGOutline = null; 1085 1086 //update line and fill color of frame SVG 1087 if(msi.getSymbolSet() == SymbolID.SymbolSet_ControlMeasure && (lineColor != null || fillColor != null)) 1088 { 1089 if(drawCustomOutline) 1090 strSVGIcon += RendererUtilities.setSVGSPCMColors(iconID,siIcon.getSVG(), RendererUtilities.getIdealOutlineColor(lineColor), fillColor,true,siIcon.getBbox(),pixelSize,outlineWidth); 1091 strSVGIcon += RendererUtilities.setSVGSPCMColors(iconID, siIcon.getSVG(), lineColor, fillColor); 1092 } 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("SinglePointRenderer", "RenderModifier", 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}