diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /mobile/android/base/java/org/mozilla/gecko/icons/processing | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'mobile/android/base/java/org/mozilla/gecko/icons/processing')
5 files changed, 224 insertions, 0 deletions
diff --git a/mobile/android/base/java/org/mozilla/gecko/icons/processing/ColorProcessor.java b/mobile/android/base/java/org/mozilla/gecko/icons/processing/ColorProcessor.java new file mode 100644 index 000000000..3f7110034 --- /dev/null +++ b/mobile/android/base/java/org/mozilla/gecko/icons/processing/ColorProcessor.java @@ -0,0 +1,61 @@ +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko.icons.processing; + +import android.support.v7.graphics.Palette; +import android.util.Log; + +import org.mozilla.gecko.gfx.BitmapUtils; +import org.mozilla.gecko.icons.IconRequest; +import org.mozilla.gecko.icons.IconResponse; +import org.mozilla.gecko.util.HardwareUtils; + +/** + * Processor implementation to extract the dominant color from the icon and attach it to the icon + * response object. + */ +public class ColorProcessor implements Processor { + private static final String LOGTAG = "GeckoColorProcessor"; + private static final int DEFAULT_COLOR = 0; // 0 == No color + + @Override + public void process(IconRequest request, IconResponse response) { + if (response.hasColor()) { + return; + } + + if (HardwareUtils.isX86System()) { + // (Bug 1318667) We are running into crashes when using the palette library with + // specific icons on x86 devices. They take down the whole VM and are not recoverable. + // Unfortunately our release icon is triggering this crash. Until we can switch to a + // newer version of the support library where this does not happen, we are using our + // own slower implementation. + extractColorUsingCustomImplementation(response); + } else { + extractColorUsingPaletteSupportLibrary(response); + } + } + + private void extractColorUsingPaletteSupportLibrary(final IconResponse response) { + try { + final Palette palette = Palette.from(response.getBitmap()).generate(); + response.updateColor(palette.getVibrantColor(DEFAULT_COLOR)); + } catch (ArrayIndexOutOfBoundsException e) { + // We saw the palette library fail with an ArrayIndexOutOfBoundsException intermittently + // in automation. In this case lets just swallow the exception and move on without a + // color. This is a valid condition and callers should handle this gracefully (Bug 1318560). + Log.e(LOGTAG, "Palette generation failed with ArrayIndexOutOfBoundsException", e); + + response.updateColor(DEFAULT_COLOR); + } + } + + private void extractColorUsingCustomImplementation(final IconResponse response) { + final int dominantColor = BitmapUtils.getDominantColor(response.getBitmap()); + + response.updateColor(dominantColor); + } +} diff --git a/mobile/android/base/java/org/mozilla/gecko/icons/processing/DiskProcessor.java b/mobile/android/base/java/org/mozilla/gecko/icons/processing/DiskProcessor.java new file mode 100644 index 000000000..150aa503b --- /dev/null +++ b/mobile/android/base/java/org/mozilla/gecko/icons/processing/DiskProcessor.java @@ -0,0 +1,36 @@ +package org.mozilla.gecko.icons.processing; + +import org.mozilla.gecko.icons.IconRequest; +import org.mozilla.gecko.icons.IconResponse; +import org.mozilla.gecko.icons.storage.DiskStorage; +import org.mozilla.gecko.util.StringUtils; + +public class DiskProcessor implements Processor { + @Override + public void process(IconRequest request, IconResponse response) { + if (request.shouldSkipDisk()) { + return; + } + + if (!response.hasUrl() || !StringUtils.isHttpOrHttps(response.getUrl())) { + // If the response does not contain an URL from which the icon was loaded or if this is + // not a http(s) URL then we cannot store this or do not need to (because it's already + // stored somewhere else, like for URLs pointing inside the omni.ja). + return; + } + + final DiskStorage storage = DiskStorage.get(request.getContext()); + + if (response.isFromNetwork()) { + // The icon has been loaded from the network. Store it on the disk now. + storage.putIcon(response); + } + + if (response.isFromMemory() || response.isFromDisk() || response.isFromNetwork()) { + // Remember mapping between page URL and storage URL. Even when this icon has been loaded + // from memory or disk this does not mean that we stored this mapping already: We could + // have loaded this icon for a different page URL previously. + storage.putMapping(request, response.getUrl()); + } + } +} diff --git a/mobile/android/base/java/org/mozilla/gecko/icons/processing/MemoryProcessor.java b/mobile/android/base/java/org/mozilla/gecko/icons/processing/MemoryProcessor.java new file mode 100644 index 000000000..245faded5 --- /dev/null +++ b/mobile/android/base/java/org/mozilla/gecko/icons/processing/MemoryProcessor.java @@ -0,0 +1,38 @@ +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko.icons.processing; + +import org.mozilla.gecko.icons.IconRequest; +import org.mozilla.gecko.icons.IconResponse; +import org.mozilla.gecko.icons.storage.MemoryStorage; + +public class MemoryProcessor implements Processor { + private final MemoryStorage storage; + + public MemoryProcessor() { + storage = MemoryStorage.get(); + } + + @Override + public void process(IconRequest request, IconResponse response) { + if (request.shouldSkipMemory() || request.getIconCount() == 0 || response.isGenerated()) { + // Do not cache this icon in memory if we should skip the memory cache or if this icon + // has been generated. We can re-generate it if needed. + return; + } + + final String iconUrl = request.getBestIcon().getUrl(); + + if (iconUrl.startsWith("data:image/")) { + // The image data is encoded in the URL. It doesn't make sense to store the URL and the + // bitmap in cache. + return; + } + + storage.putMapping(request, iconUrl); + storage.putIcon(iconUrl, response); + } +} diff --git a/mobile/android/base/java/org/mozilla/gecko/icons/processing/Processor.java b/mobile/android/base/java/org/mozilla/gecko/icons/processing/Processor.java new file mode 100644 index 000000000..df7d63c6c --- /dev/null +++ b/mobile/android/base/java/org/mozilla/gecko/icons/processing/Processor.java @@ -0,0 +1,21 @@ +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko.icons.processing; + +import org.mozilla.gecko.icons.IconRequest; +import org.mozilla.gecko.icons.IconResponse; + +/** + * Generic interface for a class that processes a response object after an icon has been loaded and + * decoded. A class implementing this interface can attach additional data to the response or modify + * the bitmap (e.g. resizing). + */ +public interface Processor { + /** + * Process a response object containing an icon loaded for this request. + */ + void process(IconRequest request, IconResponse response); +} diff --git a/mobile/android/base/java/org/mozilla/gecko/icons/processing/ResizingProcessor.java b/mobile/android/base/java/org/mozilla/gecko/icons/processing/ResizingProcessor.java new file mode 100644 index 000000000..63b479021 --- /dev/null +++ b/mobile/android/base/java/org/mozilla/gecko/icons/processing/ResizingProcessor.java @@ -0,0 +1,68 @@ +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko.icons.processing; + +import android.graphics.Bitmap; +import android.support.annotation.VisibleForTesting; + +import org.mozilla.gecko.icons.IconRequest; +import org.mozilla.gecko.icons.IconResponse; + +/** + * Processor implementation for resizing the loaded icon based on the target size. + */ +public class ResizingProcessor implements Processor { + @Override + public void process(IconRequest request, IconResponse response) { + if (response.isFromMemory()) { + // This bitmap has been loaded from memory, so it has already gone through the resizing + // process. We do not want to resize the image every time we hit the memory cache. + return; + } + + final Bitmap originalBitmap = response.getBitmap(); + final int size = originalBitmap.getWidth(); + + final int targetSize = request.getTargetSize(); + + if (size == targetSize) { + // The bitmap has exactly the size we are looking for. + return; + } + + final Bitmap resizedBitmap; + + if (size > targetSize) { + resizedBitmap = resize(originalBitmap, targetSize); + } else { + // Our largest primary is smaller than the desired size. Upscale by a maximum of 2x. + // 'largestSize' now reflects the maximum size we can upscale to. + final int largestSize = size * 2; + + if (largestSize > targetSize) { + // Perfect! We can upscale by less than 2x and reach the needed size. Do it. + resizedBitmap = resize(originalBitmap, targetSize); + } else { + // We don't have enough information to make the target size look non terrible. Best effort: + resizedBitmap = resize(originalBitmap, largestSize); + } + } + + response.updateBitmap(resizedBitmap); + + originalBitmap.recycle(); + } + + @VisibleForTesting Bitmap resize(Bitmap bitmap, int targetSize) { + try { + return Bitmap.createScaledBitmap(bitmap, targetSize, targetSize, true); + } catch (OutOfMemoryError error) { + // There's not enough memory to create a resized copy of the bitmap in memory. Let's just + // use what we have. + return bitmap; + } + } +} |