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