0

I am implementing a map viewer based on openstreetmap tiles. Each tile has the same size of 256x256 pixels.

When a tile is not available to draw, I look at its "parent" size (one from lower zoom) and cut the region corresponding to the tile I need.

Here's the preudocode:

class TileDrawer:

  Canvas canvas;

  class TileSource:
      Canvas canvas;
      Bitmap placeHolder;

      canvas.setBitmap(placeHolder);

      Bitmap getTile(x, y, z):
         if x,y,z in cache:
             return cache[x,y,z];
         else if parent in cache:
             canvas.drawBitmap(parent, tileRect, parentRect);
             return placeHolder;
         else
             return null;

   drawTiles(tileSource):
         for tileXYZ in tilesXYZ:
             tile = tileSource.getTile(tileXYZ)
             canvas.drawBitmap(tile)

The problem is after drawing the screen is tiled with the very same drawing. So I suspect that the code canvas.drawTile doesn' draw immediately, and hence the tile displayed is the one that called getTile last. As an experiment, I copied the bitmap before returning in the getTile, and everything worked as needed.

Can anyone confirm this behavior? How can I avoid this without having to keep a bunch of tile placeholders and without copying bitmaps all the time?

Clarification

I guess the behaviour is equivalent to modifying a member bitmap in the loop and then calling canvas.drawBitmap after each modification. The problem is that only the final modification is drawn, and not the ones in between.

iggy
  • 1,613
  • 1
  • 18
  • 35
  • no idea what you are talking about – pskink Feb 02 '14 at 14:16
  • @pskink java passes objects by reference, so when you say canvas.drawTile(tile), you pass a reference to placeHolder bitmap. If the call canvas.drawTile(tile) doesn't draw immediately (by maybe storing the tile object somewhere), by the end of the loop `for tileXYZ in tilesXYZ:`, the canvas of TileDrawer will have a bunch of references to placeHolder and will draw same thing for each tile – iggy Feb 02 '14 at 14:42
  • ok, maybe i am wrong, but are we talking about android? what Canvas.drawTile do you mean? – pskink Feb 02 '14 at 15:07
  • @pskink sorry for confusion. Yes, we are talking about android. I meant `canvas.drawBitmap` – iggy Feb 02 '14 at 15:12
  • ok then, why do you use canvas.setBitmap? – pskink Feb 02 '14 at 15:25
  • in order to draw a tile that I need, I extract it from the parent tile using the canvas. The result of this extraction is in the placeHolder. Note that extraction and the actual drawing is done by two different canvases. I guess the behaviour is equivalent to modifying a member bitmap in the loop and then calling canvas.drawBitmap after each modification. The problem is that only the final modification is drawn, and not the ones in between. – iggy Feb 02 '14 at 15:36
  • i still dont understand why you draw on Bitmap rather than directly on Canvas? – pskink Feb 02 '14 at 16:06
  • It has mostly to do with the current design of the application. But I mean in general you don't expect such a behavior right? – iggy Feb 02 '14 at 16:13
  • to be honest i dont get your pseufocode, so im not sure what bad behaviour you mean: maybe some minimal piece of java code ilustrating that? – pskink Feb 02 '14 at 16:24

1 Answers1

0

Refer to answers here

Android, canvas: How do I clear (delete contents of) a canvas (= bitmaps), living in a surfaceView?

I called this after drawing each bitmap:

Canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)

The problem as I said was that the canvas in the class TileSource used the latest tile to be drawn instead of drawing the requested tiles each time. The line above forces all the changes of the canvas be applied immediately (seems so)

Community
  • 1
  • 1
iggy
  • 1,613
  • 1
  • 18
  • 35