/* * Created on Oct 24, 2006 */ package com.mgmaps.cache; import javax.microedition.lcdui.Graphics; import javax.microedition.lcdui.Image; import com.nutiteq.components.MapPos; import com.nutiteq.components.MapTile; import com.nutiteq.log.Log; import com.nutiteq.maps.GeoMap; import com.nutiteq.ui.ImageProcessor; /** * Caches tiles uncompressed. */ public class ScreenCache { private MapTile[] tiles; private int size; private Image[] images; private boolean[] valid; //BattleTac code starts //Added by Krisztian Schaffer, 2010.02.26 private ImageProcessor imageProcessor; private static ScreenCache instance; /** * Creates a new ScreenCache and returns it. The created instance is installed * as the current screen cache, the previous instance will be removed if any. * * @param n * maximum number of tiles stored in the created cache */ public static ScreenCache createScreenCache(final int n) { ScreenCache newInstance = new ScreenCache(n); if (instance != null) { newInstance.imageProcessor = instance.imageProcessor; } return instance = newInstance; } /** * Returns the current ScreenCache. (null if no cache is created yet) */ public static ScreenCache getInstance() { return instance; } //BattleTac code ends /** * Constructor for ScreenCache. * * @param n * maximum number of tiles stored */ private ScreenCache(final int n) {//BattleTac code: Modified to private by Krisztian Schaffer, 2010.03.01 resize(n); } /** * Resize the screen cache when switching full screen. * * @param n * new size (number of tiles) */ public void resize(final int n) { final int minSize = Math.min(size, n); size = n; final boolean cond = minSize > 0; final boolean[] oldValid = valid; valid = new boolean[size]; if (cond) { System.arraycopy(oldValid, 0, valid, 0, minSize); } final Image[] oldImages = images; images = new Image[size]; if (cond) { System.arraycopy(oldImages, 0, images, 0, minSize); } final MapTile[] oldTiles = tiles; tiles = new MapTile[size]; if (cond) { System.arraycopy(oldTiles, 0, tiles, 0, minSize); } } /** * Paint a tile * * @param g * graphics object * @param i * tile number * @param centerCopy * copy of the map center, used for synchronization */ public void paint(final Graphics g, final int i, final MapPos centerCopy, final int screenCenterX, final int screenCenterY) { if (images[i] == null) { //TODO jaanus : why does this sometimes happen with streamed tiles? Log.debug(">>>>>>>>>>>>>>>>>>>>>>> SC: null image!"); images[i] = tiles[i].getMap().getMissingTileImage(); } final int left = tiles[i].getX() - centerCopy.getX() + screenCenterX; final int top = tiles[i].getY() - centerCopy.getY() + screenCenterY; g.drawImage(images[i], left, top, Graphics.TOP | Graphics.LEFT); } /** * Find the position for a map tile. * * @param t * tile to search * @return -1 if not found */ public int find(final MapTile t) { for (int i = 0; i < size; i++) { if (valid[i] && tiles[i].equals(t)) { return i; } } return -1; } /** * Add a tile to this cache. * * @param t * the tile to add * @param update */ public int add(final MapTile t, final MapPos mp, final GeoMap displayedMap, final int screenCenterX, final int screenCenterY, final boolean update) { // if the tile is not (no longer) visible, return -1 if (!t.isVisible(mp, displayedMap, screenCenterX, screenCenterY)) { return -1; } // sweep at every add final int pos = sweepFind(t, mp, displayedMap, screenCenterX, screenCenterY); if (pos >= 0 && !update) { // found? return return pos; } // LOW rewrite if it slows down the app too much (it's O(n)) // find a place to add for (int i = 0; i < size; i++) { if (!valid[i] || t.equals(tiles[i])) { valid[i] = true; tiles[i] = t; //BattleTac code starts //Modified by Krisztian Schaffer, 2010.02.26 Image image = t.getImage(); if (imageProcessor != null) { image = imageProcessor.processImage(image); } images[i] = image; //BattleTac code ends return i; } } return -1; } /** * Remove unneeded tiles (invalidate them). Also search for a map tile. * * @param t * map tile to search for * @return the position of the map tile, or -1 if not found */ private int sweepFind(final MapTile t, final MapPos mp, final GeoMap displayedMap, final int screenCenterX, final int screenCenterY) { int found = -1; for (int i = 0; i < size; i++) { if (!valid[i]) { continue; } if (tiles[i].equals(t)) { found = i; } else if (!tiles[i].isVisible(mp, displayedMap, screenCenterX, screenCenterY)) { // if found, do not remove it valid[i] = false; tiles[i] = null; images[i] = null; } } return found; } //BattleTac code starts //Added by Krisztian Schaffer, 2010.02.26 /** * Sets the tile image processor. The given ImageProcessor will process every * tile which is added after this call. This method also clears the cache. * * @param processor * the new ImageProcessor to use, can be null to delete the current * processor. */ public void setImageProcessor(final ImageProcessor processor) { imageProcessor = processor; for (int i = 0; i < size; i++) { valid[i] = false; tiles[i] = null; images[i] = null; } } //BattleTac code ends }