michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: package org.mozilla.gecko.favicons.cache; michael@0: michael@0: import android.graphics.Bitmap; michael@0: michael@0: /** michael@0: * Objects stored in the Favicon cache - allow for the bitmap to be tagged to indicate if it has michael@0: * been scaled. Unscaled bitmaps are not included in the scaled-bitmap cache's size calculation. michael@0: */ michael@0: public class FaviconCacheElement implements Comparable { michael@0: // Was this Favicon computed via scaling another primary Favicon, or is this a primary Favicon? michael@0: final boolean isPrimary; michael@0: michael@0: // The Favicon bitmap. michael@0: Bitmap faviconPayload; michael@0: michael@0: // If set, faviconPayload is absent. Since the underlying ICO may contain multiple primary michael@0: // payloads, primary payloads are never truly deleted from the cache, but instead have their michael@0: // payload deleted and this flag set on their FaviconCacheElement. That way, the cache always michael@0: // has a record of the existence of a primary payload, even if it is no longer in the cache. michael@0: // This means that when a request comes in that will be best served using a primary that is in michael@0: // the database but no longer cached, we know that it exists and can go get it (Useful when ICO michael@0: // support is added). michael@0: volatile boolean invalidated; michael@0: michael@0: final int imageSize; michael@0: michael@0: // Used for LRU pruning. michael@0: final FaviconsForURL backpointer; michael@0: michael@0: public FaviconCacheElement(Bitmap payload, boolean primary, int size, FaviconsForURL backpointer) { michael@0: this.faviconPayload = payload; michael@0: this.isPrimary = primary; michael@0: this.imageSize = size; michael@0: this.backpointer = backpointer; michael@0: } michael@0: michael@0: public FaviconCacheElement(Bitmap faviconPayload, boolean isPrimary, FaviconsForURL backpointer) { michael@0: this.faviconPayload = faviconPayload; michael@0: this.isPrimary = isPrimary; michael@0: this.backpointer = backpointer; michael@0: michael@0: if (faviconPayload != null) { michael@0: imageSize = faviconPayload.getWidth(); michael@0: } else { michael@0: imageSize = 0; michael@0: } michael@0: } michael@0: michael@0: public int sizeOf() { michael@0: if (invalidated) { michael@0: return 0; michael@0: } michael@0: return faviconPayload.getRowBytes() * faviconPayload.getHeight(); michael@0: } michael@0: michael@0: /** michael@0: * Establish an ordering on FaviconCacheElements based on size and validity. An element is michael@0: * considered "greater than" another if it is valid and the other is not, or if it contains a michael@0: * larger payload. michael@0: * michael@0: * @param another The FaviconCacheElement to compare to this one. michael@0: * @return -1 if this element is less than the given one, 1 if the other one is larger than this michael@0: * and 0 if both are of equal value. michael@0: */ michael@0: @Override michael@0: public int compareTo(FaviconCacheElement another) { michael@0: if (invalidated && !another.invalidated) { michael@0: return -1; michael@0: } michael@0: michael@0: if (!invalidated && another.invalidated) { michael@0: return 1; michael@0: } michael@0: michael@0: if (invalidated) { michael@0: return 0; michael@0: } michael@0: michael@0: final int w1 = imageSize; michael@0: final int w2 = another.imageSize; michael@0: if (w1 > w2) { michael@0: return 1; michael@0: } else if (w2 > w1) { michael@0: return -1; michael@0: } michael@0: return 0; michael@0: } michael@0: michael@0: /** michael@0: * Called when this element is evicted from the cache. michael@0: * michael@0: * If primary, drop the payload and set invalid. If secondary, just unlink from parent node. michael@0: */ michael@0: public void onEvictedFromCache() { michael@0: if (isPrimary) { michael@0: // So we keep a record of which primaries exist in the database for this URL, we michael@0: // don't actually delete the entry for primaries. Instead, we delete their payload michael@0: // and flag them as invalid. This way, we can later figure out that what a request michael@0: // really want is one of the primaries that have been dropped from the cache, and we michael@0: // can go get it. michael@0: invalidated = true; michael@0: faviconPayload = null; michael@0: } else { michael@0: // Secondaries don't matter - just delete them. michael@0: if (backpointer == null) { michael@0: return; michael@0: } michael@0: backpointer.favicons.remove(this); michael@0: } michael@0: } michael@0: }