Commit 7def85d7 authored by nancylingwang@google.com's avatar nancylingwang@google.com Committed by Commit Bot

Modify AppService for to handle compressed standard icons.

For web apps icon, only modify the effects for uncompressed icon,
because for compressed icons, we still need apply those icon effects.

For Arc apps, when the standard icon flag is enable, call ArcAppIcon to
generate the adaptive icon for both the compressed and uncompressed
icon, so that AppService can generate the standard compressed and
uncompressed icons.

BUG=1083331

Change-Id: Icf6381ea8de96bfdc176d4df687403b72691f426
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2272659
Commit-Queue: Nancy Wang <nancylingwang@chromium.org>
Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Cr-Commit-Position: refs/heads/master@{#783873}
parent d532b5f5
...@@ -209,36 +209,6 @@ void LoadCompressedDataFromExtension( ...@@ -209,36 +209,6 @@ void LoadCompressedDataFromExtension(
std::move(compressed_data_callback)); std::move(compressed_data_callback));
} }
// Encode the ImageSkia to the compressed PNG data with the image's 1.0f scale
// factor representation. Return the encoded PNG data.
//
// This function should not be called on the UI thread.
std::vector<uint8_t> EncodeImage(const gfx::ImageSkia image) {
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::MAY_BLOCK);
std::vector<uint8_t> image_data;
const gfx::ImageSkiaRep& image_skia_rep = image.GetRepresentation(1.0f);
if (image_skia_rep.scale() != 1.0f) {
return image_data;
}
const SkBitmap& bitmap = image_skia_rep.GetBitmap();
if (bitmap.drawsNothing()) {
return image_data;
}
base::AssertLongCPUWorkAllowed();
constexpr bool discard_transparency = false;
bool success = gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, discard_transparency,
&image_data);
if (!success) {
return std::vector<uint8_t>();
}
return image_data;
}
// This pipeline is meant to: // This pipeline is meant to:
// * Simplify loading icons, as things like effects and type are common // * Simplify loading icons, as things like effects and type are common
// to all loading. // to all loading.
...@@ -362,19 +332,20 @@ void IconLoadingPipeline::LoadWebAppIcon( ...@@ -362,19 +332,20 @@ void IconLoadingPipeline::LoadWebAppIcon(
return; return;
} }
FALLTHROUGH; FALLTHROUGH;
case apps::mojom::IconType::kUncompressed: { case apps::mojom::IconType::kUncompressed:
// For uncompressed icon, apply the resize and pad effect. if (icon_type_ == apps::mojom::IconType::kUncompressed) {
icon_effects_ = static_cast<apps::IconEffects>( // For uncompressed icon, apply the resize and pad effect.
icon_effects_ | apps::IconEffects::kResizeAndPad); icon_effects_ = static_cast<apps::IconEffects>(
icon_effects_ | apps::IconEffects::kResizeAndPad);
// For uncompressed icon, clear the standard icon effects: kBackground
// and kMask. // For uncompressed icon, clear the standard icon effects: kBackground
icon_effects_ = static_cast<apps::IconEffects>( // and kMask.
icon_effects_ & ~apps::IconEffects::kCrOsStandardBackground); icon_effects_ = static_cast<apps::IconEffects>(
icon_effects_ = static_cast<apps::IconEffects>( icon_effects_ & ~apps::IconEffects::kCrOsStandardBackground);
icon_effects_ & ~apps::IconEffects::kCrOsStandardMask); icon_effects_ = static_cast<apps::IconEffects>(
icon_effects_ & ~apps::IconEffects::kCrOsStandardMask);
}
FALLTHROUGH; FALLTHROUGH;
}
case apps::mojom::IconType::kStandard: case apps::mojom::IconType::kStandard:
// If |icon_effects| are requested, we must always load the // If |icon_effects| are requested, we must always load the
// uncompressed image to apply the icon effects, and then re-encode the // uncompressed image to apply the icon effects, and then re-encode the
...@@ -553,7 +524,7 @@ void IconLoadingPipeline::MaybeApplyEffectsAndComplete( ...@@ -553,7 +524,7 @@ void IconLoadingPipeline::MaybeApplyEffectsAndComplete(
processed_image.MakeThreadSafe(); processed_image.MakeThreadSafe();
base::ThreadPool::PostTaskAndReplyWithResult( base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE}, FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
base::BindOnce(&EncodeImage, processed_image), base::BindOnce(&apps::EncodeImageToPngBytes, processed_image),
base::BindOnce(&IconLoadingPipeline::CompleteWithCompressed, base::BindOnce(&IconLoadingPipeline::CompleteWithCompressed,
base::WrapRefCounted(this))); base::WrapRefCounted(this)));
} }
...@@ -649,6 +620,32 @@ void IconLoadingPipeline::MaybeLoadFallbackOrCompleteEmpty() { ...@@ -649,6 +620,32 @@ void IconLoadingPipeline::MaybeLoadFallbackOrCompleteEmpty() {
namespace apps { namespace apps {
std::vector<uint8_t> EncodeImageToPngBytes(const gfx::ImageSkia image) {
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::MAY_BLOCK);
std::vector<uint8_t> image_data;
const gfx::ImageSkiaRep& image_skia_rep = image.GetRepresentation(1.0f);
if (image_skia_rep.scale() != 1.0f) {
return image_data;
}
const SkBitmap& bitmap = image_skia_rep.GetBitmap();
if (bitmap.drawsNothing()) {
return image_data;
}
base::AssertLongCPUWorkAllowed();
constexpr bool discard_transparency = false;
bool success = gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, discard_transparency,
&image_data);
if (!success) {
return std::vector<uint8_t>();
}
return image_data;
}
void ApplyIconEffects(IconEffects icon_effects, void ApplyIconEffects(IconEffects icon_effects,
int size_hint_in_dip, int size_hint_in_dip,
gfx::ImageSkia* image_skia) { gfx::ImageSkia* image_skia) {
......
...@@ -44,6 +44,11 @@ enum IconEffects : uint32_t { ...@@ -44,6 +44,11 @@ enum IconEffects : uint32_t {
kCrOsStandardMask = 0x80, // Apply the mask to the standard icon. kCrOsStandardMask = 0x80, // Apply the mask to the standard icon.
}; };
// Encode the ImageSkia to the compressed PNG data with the image's 1.0f scale
// factor representation. Return the encoded PNG data.
// This function should not be called on the UI thread.
std::vector<uint8_t> EncodeImageToPngBytes(const gfx::ImageSkia image);
// Modifies |image_skia| to apply icon post-processing effects like badging and // Modifies |image_skia| to apply icon post-processing effects like badging and
// desaturation to gray. // desaturation to gray.
void ApplyIconEffects(IconEffects icon_effects, void ApplyIconEffects(IconEffects icon_effects,
......
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/optional.h" #include "base/optional.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/apps/app_service/app_service_proxy.h"
#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
#include "chrome/browser/apps/app_service/arc_apps_factory.h" #include "chrome/browser/apps/app_service/arc_apps_factory.h"
...@@ -48,6 +50,19 @@ ...@@ -48,6 +50,19 @@
namespace { namespace {
void CompleteWithCompressed(apps::mojom::Publisher::LoadIconCallback callback,
std::vector<uint8_t> data) {
if (data.empty()) {
std::move(callback).Run(apps::mojom::IconValue::New());
return;
}
apps::mojom::IconValuePtr iv = apps::mojom::IconValue::New();
iv->icon_type = apps::mojom::IconType::kCompressed;
iv->compressed = std::move(data);
iv->is_placeholder_icon = false;
std::move(callback).Run(std::move(iv));
}
void OnArcAppIconCompletelyLoaded( void OnArcAppIconCompletelyLoaded(
apps::mojom::IconType icon_type, apps::mojom::IconType icon_type,
int32_t size_hint_in_dip, int32_t size_hint_in_dip,
...@@ -64,23 +79,26 @@ void OnArcAppIconCompletelyLoaded( ...@@ -64,23 +79,26 @@ void OnArcAppIconCompletelyLoaded(
iv->is_placeholder_icon = false; iv->is_placeholder_icon = false;
switch (icon_type) { switch (icon_type) {
case apps::mojom::IconType::kCompressed: { case apps::mojom::IconType::kCompressed:
auto& compressed_images = icon->compressed_images(); if (!base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon)) {
auto iter = auto& compressed_images = icon->compressed_images();
compressed_images.find(apps_util::GetPrimaryDisplayUIScaleFactor()); auto iter =
if (iter == compressed_images.end()) { compressed_images.find(apps_util::GetPrimaryDisplayUIScaleFactor());
std::move(callback).Run(apps::mojom::IconValue::New()); if (iter == compressed_images.end()) {
return; std::move(callback).Run(apps::mojom::IconValue::New());
} return;
const std::string& data = iter->second; }
iv->compressed = std::vector<uint8_t>(data.begin(), data.end()); const std::string& data = iter->second;
if (icon_effects != apps::IconEffects::kNone) { iv->compressed = std::vector<uint8_t>(data.begin(), data.end());
// TODO(crbug.com/988321): decompress the image, apply icon effects then if (icon_effects != apps::IconEffects::kNone) {
// re-compress. // TODO(crbug.com/988321): decompress the image, apply icon effects
// then re-compress.
}
break;
} }
break; FALLTHROUGH;
}
case apps::mojom::IconType::kUncompressed: case apps::mojom::IconType::kUncompressed:
FALLTHROUGH;
case apps::mojom::IconType::kStandard: { case apps::mojom::IconType::kStandard: {
if (base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon)) { if (base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon)) {
iv->uncompressed = gfx::ImageSkiaOperations::CreateSuperimposedImage( iv->uncompressed = gfx::ImageSkiaOperations::CreateSuperimposedImage(
...@@ -99,6 +117,15 @@ void OnArcAppIconCompletelyLoaded( ...@@ -99,6 +117,15 @@ void OnArcAppIconCompletelyLoaded(
break; break;
} }
if (base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon) &&
icon_type == apps::mojom::IconType::kCompressed) {
iv->uncompressed.MakeThreadSafe();
base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
base::BindOnce(&apps::EncodeImageToPngBytes, iv->uncompressed),
base::BindOnce(&CompleteWithCompressed, std::move(callback)));
return;
}
std::move(callback).Run(std::move(iv)); std::move(callback).Run(std::move(iv));
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "chrome/browser/apps/app_service/arc_icon_once_loader.h" #include "chrome/browser/apps/app_service/arc_icon_once_loader.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/app_list/arc/arc_app_icon.h" #include "chrome/browser/ui/app_list/arc/arc_app_icon.h"
#include "chrome/common/chrome_features.h"
namespace apps { namespace apps {
...@@ -73,10 +74,16 @@ void ArcIconOnceLoader::SizeSpecificLoader::LoadIcon( ...@@ -73,10 +74,16 @@ void ArcIconOnceLoader::SizeSpecificLoader::LoadIcon(
switch (icon_type_) { switch (icon_type_) {
case apps::mojom::IconType::kUnknown: case apps::mojom::IconType::kUnknown:
case apps::mojom::IconType::kUncompressed: case apps::mojom::IconType::kUncompressed:
icon_type = ArcAppIcon::IconType::kUncompressed; icon_type =
base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon)
? ArcAppIcon::IconType::kAdaptive
: ArcAppIcon::IconType::kUncompressed;
break; break;
case apps::mojom::IconType::kCompressed: case apps::mojom::IconType::kCompressed:
icon_type = ArcAppIcon::IconType::kCompressed; icon_type =
base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon)
? ArcAppIcon::IconType::kAdaptive
: ArcAppIcon::IconType::kCompressed;
break; break;
case apps::mojom::IconType::kStandard: case apps::mojom::IconType::kStandard:
icon_type = ArcAppIcon::IconType::kAdaptive; icon_type = ArcAppIcon::IconType::kAdaptive;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment