// #if polish.api.paintdirect public Node paintDirect(PaintContext createPC) { tr.resetClickableMarkers(); iDrawState = 2; long startTime = System.currentTimeMillis(); // Projection p = ProjFactory.getInstance(createPC.center, // nextSc.course, nextSc.scale, xSize, ySize); // p.inverse(xSize, 0, createPC.screenRU); // p.inverse(0, ySize, createPC.screenLD); // pcCollect.trace = nextSc.trace; // pcCollect.dataReader = nextSc.dataReader; // cleans the screen // jkp createPC.g = img[nextCreate].getGraphics(); // jkp createPC.g.setColor(Legend.COLORS[Legend.COLOR_MAP_BACKGROUND]); // createPC.g.fillRect(0, 0, xSize, ySize); // createPC.g.setColor(0x00FF0000); // createPC.g.drawRect(0, 0, xSize - 1, ySize - 1); // createPC.g.drawRect(20, 20, xSize - 41, ySize - 41); createPC.squareDstWithPenToWay = Float.MAX_VALUE; createPC.squareDstWithPenToActualRoutableWay = Float.MAX_VALUE; createPC.squareDstWithPenToRoutePath = Float.MAX_VALUE; createPC.squareDstToRoutePath = Float.MAX_VALUE; createPC.dest = nextSc.dest; createPC.waysPainted = 0; // Projection p = ProjFactory.getInstance(createPC.center, nextSc.course, nextSc.scale, xSize, // (createPC.trace.isShowingSplitScreen()) ? (int) (ySize / 2) : ySize); // System.out.println("p =" + p); Projection p = ProjFactory.getInstance( createPC.center, createPC.course, createPC.scale, xSize, (createPC.trace.isShowingSplitScreen()) ? (int) (ySize / 2) : ySize); Projection p1 = p; createPC.setP(p); // System.out.println("create " + pcCollect); Way.setupDirectionalPenalty(createPC, tr.speed, tr.gpsRecenter && !tr.gpsRecenterInvalid); float boost = Configuration.getMaxDetailBoostMultiplier(); /* * layers containing highlighted path segments */ createPC.hlLayers = 0; /* * highlighted path is on top if gps recentered, but if not it might still come to top * when we determine during painting that the cursor is closer than 25 meters at the route line. */ createPC.highlightedPathOnTop = tr.gpsRecenter; /** * At the moment we don't really have proper layer support in the data yet, so only split it * into Area, Way and Node layers */ byte layersToRender[] = { Tile.LAYER_AREA, 1 | Tile.LAYER_AREA, 2 | Tile.LAYER_AREA, 3 | Tile.LAYER_AREA, 4 | Tile.LAYER_AREA, 0, 1, 2, 3, 4, Tile.LAYER_NODE, 0 | Tile.LAYER_HIGHLIGHT, 1 | Tile.LAYER_HIGHLIGHT, 2 | Tile.LAYER_HIGHLIGHT, 3 | Tile.LAYER_HIGHLIGHT }; /** * Draw each layer separately to enforce paint ordering: * * <p>Go through the entire tile tree multiple times to get the drawing order correct. * * <p>The first 5 layers correspond to drawing areas with the osm layer tag of (< -1, -1, 0, 1, * >1), then next 5 layers are drawing streets with osm layer tag (< -1, -1, 0, 1, >1). * * <p>Then we draw the highlighted streets and finally we draw the POI layer. * * <p>So e. g. layer 7 corresponds to all streets that have no osm layer tag or layer = 0. */ boolean simplifyMap = Configuration.getCfgBitState(Configuration.CFGBIT_SIMPLIFY_MAP_WHEN_BUSY); boolean skippableLayer = false; for (byte layer = 0; layer < layersToRender.length; layer++) { if (simplifyMap) { skippableLayer = ((layer < 5 && layer > 1) // #if polish.api.finland // don't skip node layer where speed camera is if camera alert is o || (layer == 14 && !Configuration.getCfgBitState(Configuration.CFGBIT_SPEEDCAMERA_ALERT)) // #else || (layer == 14) // #endif // #if polish.android || (Trace.getInstance().mapBrowsing && ((layer < 5) || layer == 14)) // #else || (Trace.getInstance().mapBrowsing && ((layer < 5 && layer > 1) || layer == 14)) // #endif ); // skip update if a new one is queued if (needRedraw && skippableLayer) { // continue; } } // render only highlight layers which actually have highlighted path segments if ((layersToRender[layer] & Tile.LAYER_HIGHLIGHT) > 0 && layersToRender[layer] != Tile.LAYER_NODE) { /** * as we do two passes for each way layer when gps recentered - one for the ways and one for * the route line on top, we can use in the second pass the determined route path connection * / idx to highlight the route line in the correct / prior route line color. when not gps * recentered, this info will be by one image obsolete however */ if (layersToRender[layer] == Tile.LAYER_HIGHLIGHT /*(0 | Tile.LAYER_HIGHLIGHT) pointless bitwise operation*/) { /* * only take ImageCollector loops into account for dstToRoutePath if ways were painted * otherwise this would trigger wrong route recalculations */ if (createPC.waysPainted != 0) { // RouteInstructions.dstToRoutePath = // createPC.getDstFromSquareDst(createPC.squareDstToRoutePath); RouteInstructions.dstToRoutePath = createPC.getDstFromRouteSegment(); if (RouteInstructions.dstToRoutePath != RouteInstructions.DISTANCE_UNKNOWN) { RouteInstructions.routePathConnection = createPC.routePathConnection; RouteInstructions.pathIdxInRoutePathConnection = createPC.pathIdxInRoutePathConnection; RouteInstructions.actualRoutePathWay = createPC.actualRoutePathWay; // when we determine during painting that the cursor is closer than 25 meters at the // route line, bring it to the top if (RouteInstructions.dstToRoutePath < 25) { createPC.highlightedPathOnTop = true; } } // System.out.println("waysPainted: " + createPC.waysPainted); } else { // FIXME: Sometimes there are ImageCollector loop with no way pained even when ways // would be there and tile data is fully loaded // Update 2011-06-11: Might be fixed with the patch from gojkos at [ // sharenav-Bugs-3310178 ] Delayed map draw on LG cookie phone // Update 2012-03-17 (patch from walter9): The image collector has been started twice. // This seems to be fixed now in Trace.java.startImageCollector() System.out.println("No ways painted in this ImageCollector loop"); } } byte relLayer = (byte) (((int) layersToRender[layer]) & 0x0000000F); if ((createPC.hlLayers & (1 << relLayer)) == 0) { continue; } } minTile = Legend.scaleToTile((int) (createPC.scale / (boost * overviewTileScaleBoost))); if (t[0] != null) { if (needRedraw && skippableLayer) { continue; } t[0].paint(createPC, layersToRender[layer]); if (needRedraw && skippableLayer) { continue; } } if ((minTile >= 1) && (t[1] != null)) { if (needRedraw && skippableLayer) { continue; } t[1].paint(createPC, layersToRender[layer]); if (needRedraw && skippableLayer) { continue; } // Thread.yield(); } if ((minTile >= 2) && (t[2] != null)) { if (needRedraw && skippableLayer) { continue; } t[2].paint(createPC, layersToRender[layer]); if (needRedraw && skippableLayer) { continue; } // Thread.yield(); } if ((minTile >= 3) && (t[3] != null)) { if (needRedraw && skippableLayer) { continue; } t[3].paint(createPC, layersToRender[layer]); if (needRedraw && skippableLayer) { continue; } // Thread.yield(); } /** Drawing waypoints */ if (t[DictReader.GPXZOOMLEVEL] != null) { t[DictReader.GPXZOOMLEVEL].paint(createPC, layersToRender[layer]); } if (suspended) { // Don't continue rendering if suspended createPC.state = PaintContext.STATE_READY; break; } } /** Drawing debuginfo for routing */ if (!suspended && t[DictReader.ROUTEZOOMLEVEL] != null && (Configuration.getCfgBitState(Configuration.CFGBIT_ROUTE_CONNECTIONS) || Configuration.getCfgBitState(Configuration.CFGBIT_SHOW_TURN_RESTRICTIONS))) { t[DictReader.ROUTEZOOMLEVEL].paint(createPC, (byte) 0); } iDrawState = 0; icDuration = System.currentTimeMillis() - startTime; // #mdebug logger.info("Painting map took " + icDuration + " ms"); // #enddebug System.out.println("Painting map took " + icDuration + " ms " + xSize + "/" + ySize); createPC.state = PaintContext.STATE_READY; // lastCreatedSc=createPC.cloneToScreenContext(); if (!shutdown) { // newCollected(); } createImageCount++; // needRedraw = false; // tr.cleanup(); // System.out.println("create ready"); // System.gc(); if (Configuration.getCfgBitState(Configuration.CFGBIT_KEEP_ON_ROAD_IN_ROUTE_GUIDANCE)) { return createPC.gpsNode.copy(); } else { return createPC.center.copy(); } }
public void run() { PaintContext createPC = null; final byte MAXCRASHES = 5; byte crash = 0; do { try { while (!shutdown) { if (!needRedraw || suspended) { synchronized (this) { try { /* FIXME: We still have some situations where redraw is not done automatically immediately, * e.g. on Nokia 5800 after returning from another Displayable * Therefore reduce the timeout for redrawing anyway from 30 seconds to 1 seconds * if the last user interaction happened less than 1.5 secs before if (Trace.getDurationSinceLastUserActionTime() > 1500 ) { wait(30000); } else { wait(1000); } */ wait(30000); } catch (InterruptedException e) { continue; // Recheck condition of the loop } } } needRedraw = false; // moved here and deleted from the bottom of this routine // #debug debug logger.debug("Redrawing Map"); iDrawState = 1; synchronized (this) { while (pc[nextCreate].state != PaintContext.STATE_READY && !shutdown) { try { // System.out.println("img not ready"); wait(1000); } catch (InterruptedException e) { } } if (suspended || shutdown) { continue; } pc[nextCreate].state = PaintContext.STATE_IN_CREATE; } iDrawState = 2; createPC = pc[nextCreate]; long startTime = System.currentTimeMillis(); // create PaintContext createPC.xSize = nextSc.xSize; createPC.ySize = nextSc.ySize; createPC.center = nextSc.center.copy(); mapCenter = nextSc.center.copy(); createPC.scale = nextSc.scale; createPC.course = nextSc.course; // Projection p = ProjFactory.getInstance(createPC.center, // nextSc.course, nextSc.scale, xSize, ySize); createPC.setP(nextSc.getP()); // p.inverse(xSize, 0, createPC.screenRU); // p.inverse(0, ySize, createPC.screenLD); // pcCollect.trace = nextSc.trace; // pcCollect.dataReader = nextSc.dataReader; // cleans the screen createPC.g = img[nextCreate].getGraphics(); createPC.g.setColor(Legend.COLORS[Legend.COLOR_MAP_BACKGROUND]); createPC.g.fillRect(0, 0, xSize, ySize); // createPC.g.setColor(0x00FF0000); // createPC.g.drawRect(0, 0, xSize - 1, ySize - 1); // createPC.g.drawRect(20, 20, xSize - 41, ySize - 41); createPC.squareDstWithPenToWay = Float.MAX_VALUE; createPC.squareDstWithPenToActualRoutableWay = Float.MAX_VALUE; createPC.squareDstWithPenToRoutePath = Float.MAX_VALUE; createPC.squareDstToRoutePath = Float.MAX_VALUE; createPC.dest = nextSc.dest; createPC.waysPainted = 0; // System.out.println("create " + pcCollect); Way.setupDirectionalPenalty(createPC, tr.speed, tr.gpsRecenter && !tr.gpsRecenterInvalid); float boost = Configuration.getMaxDetailBoostMultiplier(); /* * layers containing highlighted path segments */ createPC.hlLayers = 0; /* * highlighted path is on top if gps recentered, but if not it might still come to top * when we determine during painting that the cursor is closer than 25 meters at the route line. */ createPC.highlightedPathOnTop = tr.gpsRecenter; /** * At the moment we don't really have proper layer support in the data yet, so only split * it into Area, Way and Node layers */ byte layersToRender[] = { Tile.LAYER_AREA, 1 | Tile.LAYER_AREA, 2 | Tile.LAYER_AREA, 3 | Tile.LAYER_AREA, 4 | Tile.LAYER_AREA, 0, 1, 2, 3, 4, Tile.LAYER_NODE, 0 | Tile.LAYER_HIGHLIGHT, 1 | Tile.LAYER_HIGHLIGHT, 2 | Tile.LAYER_HIGHLIGHT, 3 | Tile.LAYER_HIGHLIGHT }; /** * Draw each layer separately to enforce paint ordering: * * <p>Go through the entire tile tree multiple times to get the drawing order correct. * * <p>The first 5 layers correspond to drawing areas with the osm layer tag of (< -1, -1, * 0, 1, >1), then next 5 layers are drawing streets with osm layer tag (< -1, -1, 0, 1, * >1). * * <p>Then we draw the highlighted streets and finally we draw the POI layer. * * <p>So e. g. layer 7 corresponds to all streets that have no osm layer tag or layer = 0. */ boolean simplifyMap = Configuration.getCfgBitState(Configuration.CFGBIT_SIMPLIFY_MAP_WHEN_BUSY); boolean skippableLayer = false; if (Configuration.getCfgBitState(Configuration.CFGBIT_TMS_BACKGROUND)) { RasterTile.drawRasterMap(createPC, createPC.trace.rootWindow); } for (byte layer = 0; layer < layersToRender.length; layer++) { if (simplifyMap) { skippableLayer = ((layer < 5 && layer > 1) // #if polish.api.finland // don't skip node layer where speed camera is if camera alert is on || (layer == 14 && !Configuration.getCfgBitState(Configuration.CFGBIT_SPEEDCAMERA_ALERT)) // #else || (layer == 14) // #endif // #if polish.android || (Trace.getInstance().mapBrowsing && ((layer < 5) || layer == 14)) // #else || (Trace.getInstance().mapBrowsing && ((layer < 5 && layer > 1) || layer == 14)) // #endif ); // skip update if a new one is queued if (needRedraw && skippableLayer) { continue; } } if (layersToRender[layer] == Tile.LAYER_NODE) { tr.resetClickableMarkers(); } // render only highlight layers which actually have highlighted path segments if ((layersToRender[layer] & Tile.LAYER_HIGHLIGHT) > 0 && layersToRender[layer] != Tile.LAYER_NODE) { /** * as we do two passes for each way layer when gps recentered - one for the ways and * one for the route line on top, we can use in the second pass the determined route * path connection / idx to highlight the route line in the correct / prior route line * color. when not gps recentered, this info will be by one image obsolete however */ if (layersToRender[layer] == Tile .LAYER_HIGHLIGHT /*(0 | Tile.LAYER_HIGHLIGHT) pointless bitwise operation*/) { /* * only take ImageCollector loops into account for dstToRoutePath if ways were painted * otherwise this would trigger wrong route recalculations */ if (createPC.waysPainted != 0) { // RouteInstructions.dstToRoutePath = // createPC.getDstFromSquareDst(createPC.squareDstToRoutePath); RouteInstructions.dstToRoutePath = createPC.getDstFromRouteSegment(); if (RouteInstructions.dstToRoutePath != RouteInstructions.DISTANCE_UNKNOWN) { RouteInstructions.routePathConnection = createPC.routePathConnection; RouteInstructions.pathIdxInRoutePathConnection = createPC.pathIdxInRoutePathConnection; RouteInstructions.actualRoutePathWay = createPC.actualRoutePathWay; // when we determine during painting that the cursor is closer than 25 meters at // the route line, bring it to the top if (RouteInstructions.dstToRoutePath < 25) { createPC.highlightedPathOnTop = true; } } // System.out.println("waysPainted: " + createPC.waysPainted); } else { // FIXME: Sometimes there are ImageCollector loop with no way pained even when // ways would be there and tile data is fully loaded // Update 2011-06-11: Might be fixed with the patch from gojkos at [ // sharenav-Bugs-3310178 ] Delayed map draw on LG cookie phone // Update 2012-03-17 (patch from walter9): The image collector has been started // twice. This seems to be fixed now in Trace.java.startImageCollector() System.out.println("No ways painted in this ImageCollector loop"); } } byte relLayer = (byte) (((int) layersToRender[layer]) & 0x0000000F); if ((createPC.hlLayers & (1 << relLayer)) == 0) { continue; } } minTile = Legend.scaleToTile((int) (createPC.scale / (boost * overviewTileScaleBoost))); if (t[0] != null) { if (needRedraw && skippableLayer) { continue; } t[0].paint(createPC, layersToRender[layer]); if (needRedraw && skippableLayer) { continue; } } if ((minTile >= 1) && (t[1] != null)) { if (needRedraw && skippableLayer) { continue; } t[1].paint(createPC, layersToRender[layer]); if (needRedraw && skippableLayer) { continue; } Thread.yield(); } if ((minTile >= 2) && (t[2] != null)) { if (needRedraw && skippableLayer) { continue; } t[2].paint(createPC, layersToRender[layer]); if (needRedraw && skippableLayer) { continue; } Thread.yield(); } if ((minTile >= 3) && (t[3] != null)) { if (needRedraw && skippableLayer) { continue; } t[3].paint(createPC, layersToRender[layer]); if (needRedraw && skippableLayer) { continue; } Thread.yield(); } /** Drawing waypoints */ if (t[DictReader.GPXZOOMLEVEL] != null) { t[DictReader.GPXZOOMLEVEL].paint(createPC, layersToRender[layer]); } if (suspended) { // Don't continue rendering if suspended createPC.state = PaintContext.STATE_READY; break; } } /** Drawing debuginfo for routing */ if (!suspended && t[DictReader.ROUTEZOOMLEVEL] != null && (Configuration.getCfgBitState(Configuration.CFGBIT_ROUTE_CONNECTIONS) || Configuration.getCfgBitState(Configuration.CFGBIT_SHOW_TURN_RESTRICTIONS))) { t[DictReader.ROUTEZOOMLEVEL].paint(createPC, (byte) 0); } iDrawState = 0; icDuration = System.currentTimeMillis() - startTime; // #mdebug logger.info("Painting map took " + icDuration + " ms"); // #enddebug System.out.println("Painting map took " + icDuration + " ms " + xSize + "/" + ySize); createPC.state = PaintContext.STATE_READY; lastCreatedSc = createPC.cloneToScreenContext(); if (!shutdown) { newCollected(); } createImageCount++; // needRedraw = false; tr.cleanup(); // System.out.println("create ready"); // System.gc(); } } catch (OutOfMemoryError oome) { if (createPC != null) { createPC.state = PaintContext.STATE_READY; } String recoverZoomedIn = ""; crash++; if (tr.scale > 10000 && crash < MAXCRASHES) { tr.scale /= 1.5f; recoverZoomedIn = Locale.get("imagecollector.ZoomingInToRecover") /* Zooming in to recover.*/; } logger.fatal( Locale.get( "imagecollector.ImageCollectorRanOutOfMemory") /*ImageCollector ran out of memory: */ + oome.getMessage() + recoverZoomedIn); } catch (Exception e) { crash++; logger.exception( Locale.get( "imagecollector.ImageCollectorCrashed") /*ImageCollector thread crashed unexpectedly with error */, e); } if (crash >= MAXCRASHES) { logger.fatal( Locale.get( "imagecollector.ImageCollectorCrashedAborting") /*ImageCollector crashed too often. Aborting.*/); } } while (!shutdown && crash < MAXCRASHES); processorThread = null; synchronized (this) { notifyAll(); } }