Ejemplo n.º 1
0
 public virtual void Put(Job key, ITileBitmap bitmap)
 {
     lock (this)
     {
         // no-op
     }
 }
Ejemplo n.º 2
0
        public virtual void Put(Job key, ITileBitmap bitmap)
        {
            lock (this)
            {
                if (key == null)
                {
                    throw new System.ArgumentException("key must not be null");
                }
                else if (bitmap == null)
                {
                    throw new System.ArgumentException("bitmap must not be null");
                }

                ITileBitmap old = this.lruCache.Get(key);
                if (old != null)
                {
                    old.DecrementRefCount();
                }

                if (this.lruCache.Add(key, bitmap) != null)
                {
                    LOGGER.Warn("overwriting cached entry: " + key);
                }
                bitmap.IncrementRefCount();
                this.observable.NotifyObservers();
            }
        }
Ejemplo n.º 3
0
        public override void Draw(BoundingBox boundingBox, sbyte zoomLevel, ICanvas canvas, Point topLeftPoint)
        {
            IList <TilePosition> tilePositions = LayerUtil.GetTilePositions(boundingBox, zoomLevel, topLeftPoint, this.displayModel.TileSize);

            // In a rotation situation it is possible that drawParentTileBitmap sets the
            // clipping bounds to portrait, while the device is just being rotated into
            // landscape: the result is a partially painted screen that only goes away
            // after zooming (which has the effect of resetting the clip bounds if drawParentTileBitmap
            // is called again).
            // Always resetting the clip bounds here seems to avoid the problem,
            // I assume that this is a pretty cheap operation, otherwise it would be better
            // to hook this into the onConfigurationChanged call chain.
            canvas.ResetClip();

            if (!isTransparent)
            {
                canvas.FillColor(this.displayModel.BackgroundColor);
            }

            ISet <Job> jobs = new HashSet <Job>();

            foreach (TilePosition tilePosition in tilePositions)
            {
                jobs.Add(CreateJob(tilePosition.Tile));
            }
            this.tileCache.WorkingSet = jobs;

            for (int i = tilePositions.Count - 1; i >= 0; --i)
            {
                TilePosition tilePosition = tilePositions[i];
                Point        point        = tilePosition.Point;
                Tile         tile         = tilePosition.Tile;
                T            job          = CreateJob(tile);
                ITileBitmap  bitmap       = this.tileCache.GetImmediately(job);

                if (bitmap == null)
                {
                    if (this.hasJobQueue && !this.tileCache.ContainsKey(job))
                    {
                        this.jobQueue.Add(job);
                    }
                    DrawParentTileBitmap(canvas, point, tile);
                }
                else
                {
                    if (IsTileStale(tile, bitmap) && this.hasJobQueue && !this.tileCache.ContainsKey(job))
                    {
                        this.jobQueue.Add(job);
                    }
                    RetrieveLabelsOnly(job);
                    canvas.DrawBitmap(bitmap, (int)Math.Round(point.X), (int)Math.Round(point.Y));
                    bitmap.DecrementRefCount();
                }
            }
            if (this.hasJobQueue)
            {
                this.jobQueue.NotifyWorkers();
            }
        }
Ejemplo n.º 4
0
 /// <summary>
 /// Whether the tile is stale and should be refreshed.
 /// <para>
 /// This method is called from <seealso cref="#draw(BoundingBox, byte, Canvas, Point)"/> to determine whether the tile needs to
 /// be refreshed.
 /// </para>
 /// <para>
 /// A tile is considered stale if one or more of the following two conditions apply:
 /// <ul>
 /// <li>The {@code bitmap}'s <seealso cref="MapsforgeSharp.Core.Graphics.ITileBitmap#isExpired()"/> method returns {@code True}.</li>
 /// <li>The layer has a time-to-live (TTL) set (<seealso cref="#getCacheTimeToLive()"/> returns a nonzero value) and the sum of
 /// the {@code bitmap}'s <seealso cref="MapsforgeSharp.Core.Graphics.ITileBitmap#getTimestamp()"/> and TTL is less than current
 /// time (as returned by <seealso cref="java.lang.System#currentTimeMillis()"/>).</li>
 /// </ul>
 /// </para>
 /// <para>
 /// When a tile has become stale, the layer will first display the tile referenced by {@code bitmap} and attempt to
 /// obtain a fresh copy in the background. When a fresh copy becomes available, the layer will replace it and update
 /// the cache. If a fresh copy cannot be obtained (e.g. because the tile is obtained from an online source which
 /// cannot be reached), the stale tile will continue to be used until another
 /// {@code #draw(BoundingBox, byte, Canvas, Point)} operation requests it again.
 ///
 /// </para>
 /// </summary>
 /// <param name="tile">
 ///            A tile. This parameter is not used for a {@code TileDownloadLayer} and can be null. </param>
 /// <param name="bitmap">
 ///            The bitmap for {@code tile} currently held in the layer's cache. </param>
 protected internal override bool IsTileStale(Tile tile, ITileBitmap bitmap)
 {
     if (bitmap.Expired)
     {
         return(true);
     }
     return(cacheTimeToLive != 0 && ((bitmap.Timestamp + cacheTimeToLive) < DateTimeHelperClass.CurrentUnixTimeMillis()));
 }
Ejemplo n.º 5
0
 public virtual void Put(Job key, ITileBitmap bitmap)
 {
     if (this.workingSet.Contains(key))
     {
         this.firstLevelTileCache.Put(key, bitmap);
     }
     this.secondLevelTileCache.Put(key, bitmap);
 }
Ejemplo n.º 6
0
            public override void run()
            {
                ITileBitmap bitmap = null;

                try
                {
                    long start = 0;

                    if (outerInstance.inShutdown)
                    {
                        return;
                    }

                    if (DEBUG_TIMING)
                    {
                        start = DateTimeHelperClass.CurrentUnixTimeMillis();
                        LOGGER.Info("ConcurrentJobs " + Interlocked.Increment(ref outerInstance.concurrentJobs));
                    }

                    bitmap = outerInstance.databaseRenderer.ExecuteJob(rendererJob);

                    if (outerInstance.inShutdown)
                    {
                        return;
                    }

                    if (!rendererJob.labelsOnly && bitmap != null)
                    {
                        outerInstance.tileCache.Put(rendererJob, bitmap);
                        outerInstance.databaseRenderer.RemoveTileInProgress(rendererJob.tile);
                    }
                    outerInstance.layer.RequestRedraw();

                    if (DEBUG_TIMING)
                    {
                        long end = DateTimeHelperClass.CurrentUnixTimeMillis();
                        long te  = Interlocked.Increment(ref outerInstance.totalExecutions);
                        long tt  = Interlocked.Add(ref outerInstance.totalTime, end - start);
                        if (te % 10 == 0)
                        {
                            LOGGER.Info("TIMING " + Convert.ToString(te) + " " + Convert.ToString(tt / te));
                        }
                        Interlocked.Decrement(ref outerInstance.concurrentJobs);
                    }
                }
                finally
                {
                    this.rendererJob.renderThemeFuture.DecrementRefCount();
                    outerInstance.jobQueue.Remove(rendererJob);
                    if (bitmap != null)
                    {
                        bitmap.DecrementRefCount();
                    }
                }
            }
Ejemplo n.º 7
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private void downloadTile(DownloadJob downloadJob) throws java.io.IOException
        private void downloadTile(DownloadJob downloadJob)
        {
            TileDownloader tileDownloader = new TileDownloader(downloadJob, this.graphicFactory);
            ITileBitmap    bitmap         = tileDownloader.DownloadImage();

            if (!Interrupted && bitmap != null)
            {
                bitmap.ScaleTo(this.displayModel.TileSize, this.displayModel.TileSize);
                this.tileCache.Put(downloadJob, bitmap);
                this.layer.RequestRedraw();
            }
        }
Ejemplo n.º 8
0
 public virtual ITileBitmap Get(Job key)
 {
     lock (this)
     {
         ITileBitmap bitmap = this.lruCache.Get(key);
         if (bitmap != null)
         {
             bitmap.IncrementRefCount();
         }
         return(bitmap);
     }
 }
Ejemplo n.º 9
0
        /// <summary>
        /// Draws a bitmap just with outside colour, used for bitmaps outside of map area. </summary>
        /// <param name="renderContext"> the RenderContext </param>
        /// <returns> bitmap drawn in single colour. </returns>
        private ITileBitmap CreateBackgroundBitmap(RenderContext renderContext)
        {
            ITileBitmap bitmap = this.graphicFactory.CreateTileBitmap(renderContext.rendererJob.tile.TileSize, renderContext.rendererJob.hasAlpha);

            renderContext.canvasRasterer.CanvasBitmap = bitmap;
            if (!renderContext.rendererJob.hasAlpha)
            {
                renderContext.canvasRasterer.Fill(renderContext.renderTheme.MapBackgroundOutside);
            }

            return(bitmap);
        }
Ejemplo n.º 10
0
 /// <summary>
 /// stores the bitmap data on disk with filename key
 /// </summary>
 /// <param name="key">
 ///            filename </param>
 /// <param name="bitmap">
 ///            tile image </param>
 private void StoreData(Job key, ITileBitmap bitmap)
 {
     try
     {
         IFile file = GetOutputFile(key);
         if (file == null)
         {
             // if the file cannot be written, silently return
             return;
         }
         using (System.IO.Stream outputStream = file.OpenAsync(FileAccess.ReadAndWrite).Result)
         {
             bitmap.Compress(outputStream);
             try
             {
                 //@lock.writeLock().@lock();
                 if (this.lruCache.Add(key.Key, file) != null)
                 {
                     LOGGER.Warn("overwriting cached entry: " + key.Key);
                 }
             }
             finally
             {
                 //@lock.writeLock().unlock();
             }
         }
     }
     catch (Exception e)
     {
         // we are catching now any exception and then disable the file cache
         // this should ensure that no exception in the storage thread will
         // ever crash the main app. If there is a runtime exception, the thread
         // will exit (via destroy).
         LOGGER.Fatal("Disabling filesystem cache", e);
         // most likely cause is that the disk is full, just disable the
         // cache otherwise
         // more and more exceptions will be thrown.
         this.Destroy();
         try
         {
             //@lock.writeLock().@lock();
             this.lruCache = new FileWorkingSetCache <string>(0);
         }
         finally
         {
             //@lock.writeLock().unlock();
         }
     }
 }
Ejemplo n.º 11
0
        public virtual ITileBitmap Get(Job key)
        {
            ITileBitmap returnBitmap = this.firstLevelTileCache.Get(key);

            if (returnBitmap != null)
            {
                return(returnBitmap);
            }
            returnBitmap = this.secondLevelTileCache.Get(key);
            if (returnBitmap != null)
            {
                this.firstLevelTileCache.Put(key, returnBitmap);
                return(returnBitmap);
            }
            return(null);
        }
Ejemplo n.º 12
0
        public virtual ITileBitmap Get(Job key)
        {
            IFile file;

            try
            {
                //@lock.readLock().@lock();
                file = this.lruCache.Get(key.Key);
            }
            finally
            {
                //@lock.readLock().unlock();
            }
            if (file == null)
            {
                return(null);
            }

            try
            {
                using (System.IO.Stream inputStream = file.OpenAsync(FileAccess.Read).Result)
                {
                    ITileBitmap result = this.graphicFactory.CreateTileBitmap(inputStream, key.tile.TileSize, key.hasAlpha);
                    // TODO
                    //result.Timestamp = file.lastModified();
                    return(result);
                }
            }
            catch (CorruptedInputStreamException e)
            {
                // this can happen, at least on Android, when the input stream
                // is somehow corrupted, returning null ensures it will be loaded
                // from another source
                Remove(key);
                LOGGER.Warn("input stream from file system cache invalid " + key.Key, e);
                return(null);
            }
            catch (IOException e)
            {
                Remove(key);
                LOGGER.Fatal(e.Message, e);
                return(null);
            }
        }
Ejemplo n.º 13
0
        public virtual void Put(Job key, ITileBitmap bitmap)
        {
            if (key == null)
            {
                throw new System.ArgumentException("key must not be null");
            }
            else if (bitmap == null)
            {
                throw new System.ArgumentException("bitmap must not be null");
            }

            if (Capacity == 0)
            {
                return;
            }

            StoreData(key, bitmap);
            this.observable.NotifyObservers();
        }
Ejemplo n.º 14
0
        internal virtual ITileBitmap DownloadImage()
        {
            Uri url = this.downloadJob.tileSource.GetTileUrl(this.downloadJob.tile);

            using (var httpClient = new System.Net.Http.HttpClient())
            {
                httpClient.Timeout = new TimeSpan(50000);

                using (var request = new HttpRequestMessage(HttpMethod.Get, url))
                {
                    var response = httpClient.SendAsync(request).Result;

                    if (response.IsSuccessStatusCode)
                    {
                        Stream stream;
                        if (response.Headers.TransferEncoding.Contains(new System.Net.Http.Headers.TransferCodingHeaderValue("gzip")))
                        {
                            stream = new GZipStream(response.Content.ReadAsStreamAsync().Result, CompressionMode.Decompress);
                        }
                        else
                        {
                            stream = response.Content.ReadAsStreamAsync().Result;
                        }

                        try {
                            ITileBitmap result = this.graphicFactory.CreateTileBitmap(stream, this.downloadJob.tile.TileSize, this.downloadJob.hasAlpha);
                            result.Expiration = response.Headers..Content..httpClient.Expiration;
                            return(result);
                        }
                        catch (CorruptedInputStreamException)
                        {
                            // the creation of the tile bit map can fail at, at least on Android,
                            // when the connection is slow or busy, returning null here ensures that
                            // the tile will be downloaded again
                            return(null);
                        }
                    }
                }
            }

            return(null);
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Called when a job needs to be executed.
        /// </summary>
        /// <param name="rendererJob">
        ///            the job that should be executed. </param>
        public virtual ITileBitmap ExecuteJob(RendererJob rendererJob)
        {
            RenderTheme renderTheme;

            try
            {
                // Wait until RenderTheme is ready
                renderTheme = rendererJob.renderThemeFuture.Result;
            }
            catch (Exception e)
            {
                LOGGER.Fatal("Error to retrieve render theme from future", e);
                return(null);
            }

            RenderContext renderContext = null;

            try
            {
                renderContext = new RenderContext(renderTheme, rendererJob, new CanvasRasterer(graphicFactory));

                if (RenderBitmap(renderContext))
                {
                    ITileBitmap bitmap = null;

                    if (this.mapDatabase != null)
                    {
                        MapReadResult mapReadResult = this.mapDatabase.ReadMapData(rendererJob.tile);
                        ProcessReadMapData(renderContext, mapReadResult);
                    }

                    if (!rendererJob.labelsOnly)
                    {
                        bitmap           = this.graphicFactory.CreateTileBitmap(renderContext.rendererJob.tile.TileSize, renderContext.rendererJob.hasAlpha);
                        bitmap.Timestamp = rendererJob.mapDataStore.GetDataTimestamp(renderContext.rendererJob.tile);
                        renderContext.canvasRasterer.CanvasBitmap = bitmap;
                        if (!rendererJob.hasAlpha && rendererJob.displayModel.BackgroundColor != renderContext.renderTheme.MapBackground)
                        {
                            renderContext.canvasRasterer.Fill(renderContext.renderTheme.MapBackground);
                        }
                        renderContext.canvasRasterer.DrawWays(renderContext);
                    }

                    if (renderLabels)
                    {
                        ISet <MapElementContainer> labelsToDraw = ProcessLabels(renderContext);
                        // now draw the ways and the labels
                        renderContext.canvasRasterer.DrawMapElements(labelsToDraw, renderContext.rendererJob.tile);
                    }
                    else
                    {
                        // store elements for this tile in the label cache
                        this.labelStore.StoreMapItems(renderContext.rendererJob.tile, renderContext.labels);
                    }

                    if (!rendererJob.labelsOnly && renderContext.renderTheme.HasMapBackgroundOutside())
                    {
                        // blank out all areas outside of map
                        Rectangle insideArea = this.mapDatabase.BoundingBox.GetPositionRelativeToTile(renderContext.rendererJob.tile);
                        if (!rendererJob.hasAlpha)
                        {
                            renderContext.canvasRasterer.FillOutsideAreas(renderContext.renderTheme.MapBackgroundOutside, insideArea);
                        }
                        else
                        {
                            renderContext.canvasRasterer.FillOutsideAreas(Color.TRANSPARENT, insideArea);
                        }
                    }
                    return(bitmap);
                }
                // outside of map area with background defined:
                return(CreateBackgroundBitmap(renderContext));
            }
            finally
            {
                if (renderContext != null)
                {
                    renderContext.Destroy();
                }
            }
        }
Ejemplo n.º 16
0
 /// <summary>
 /// Whether the tile is stale and should be refreshed.
 /// <para>
 /// This method is not needed for a TileStoreLayer and will always return {@code false}. Both arguments can be null.
 ///
 /// </para>
 /// </summary>
 /// <param name="tile">
 ///            A tile. </param>
 /// <param name="bitmap">
 ///            The bitmap for {@code tile} currently held in the layer's cache. </param>
 protected internal override bool IsTileStale(Tile tile, ITileBitmap bitmap)
 {
     return(false);
 }
Ejemplo n.º 17
0
 /// <summary>
 /// Whether the tile is stale and should be refreshed.
 /// <para>
 /// This method is called from <seealso cref="#draw(BoundingBox, byte, Canvas, Point)"/> to determine whether the tile needs to
 /// be refreshed. Subclasses must override this method and implement appropriate checks to determine when a tile is
 /// stale.
 /// </para>
 /// <para>
 /// Return {@code false} to use the cached copy without attempting to refresh it.
 /// </para>
 /// <para>
 /// Return {@code true} to cause the layer to attempt to obtain a fresh copy of the tile. The layer will first
 /// display the tile referenced by {@code bitmap} and attempt to obtain a fresh copy in the background. When a fresh
 /// copy becomes available, the layer will replace is and update the cache. If a fresh copy cannot be obtained (e.g.
 /// because the tile is obtained from an online source which cannot be reached), the stale tile will continue to be
 /// used until another {@code #draw(BoundingBox, byte, Canvas, Point)} operation requests it again.
 ///
 /// </para>
 /// </summary>
 /// <param name="tile">
 ///            A tile. </param>
 /// <param name="bitmap">
 ///            The bitmap for {@code tile} currently held in the layer's cache. </param>
 protected internal abstract bool IsTileStale(Tile tile, ITileBitmap bitmap);
Ejemplo n.º 18
0
 /// <summary>
 /// Whether the tile is stale and should be refreshed.
 /// <para>
 /// This method is called from <seealso cref="#draw(MapsforgeSharp.Core.Model.BoundingBox, byte, MapsforgeSharp.Core.Graphics.Canvas, MapsforgeSharp.Core.Model.Point)"/> to determine whether the tile needs to
 /// be refreshed.
 /// </para>
 /// <para>
 /// A tile is considered stale if the timestamp of the layer's <seealso cref="#mapDataStore"/> is more recent than the
 /// {@code bitmap}'s <seealso cref="MapsforgeSharp.Core.Graphics.ITileBitmap#getTimestamp()"/>.
 /// </para>
 /// <para>
 /// When a tile has become stale, the layer will first display the tile referenced by {@code bitmap} and attempt to
 /// obtain a fresh copy in the background. When a fresh copy becomes available, the layer will replace is and update
 /// the cache. If a fresh copy cannot be obtained for whatever reason, the stale tile will continue to be used until
 /// another {@code #draw(BoundingBox, byte, Canvas, Point)} operation requests it again.
 ///
 /// </para>
 /// </summary>
 /// <param name="tile">
 ///            A tile. </param>
 /// <param name="bitmap">
 ///            The bitmap for {@code tile} currently held in the layer's cache. </param>
 protected internal override bool IsTileStale(Tile tile, ITileBitmap bitmap)
 {
     return(this.mapDataStore.GetDataTimestamp(tile) > bitmap.Timestamp);
 }