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