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