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