Commit e8d58900 authored by wutao's avatar wutao Committed by Commit Bot

ambient: Tile related photos in landscape

This patch shows two related photos together when device is in landscape
orientation.

Major changes:
1. Only show paired photos in landscape mode.
2. Use flex layout to dynamically add and show the secondary image.
3. If the primary image is fetched, it will be shown in the UI.
4. If the primary image is not fetched, then will ignore the secondary
   image, i.e. read from cache.
5. If the second image is fetched, it will be added to the UI if the
   screen orientation is landscape.
6. There is a 8px wide separator between two photos.
7. Only update the cache with primary image.
8. Paired photos share the same attributes.

Screenshot: https://screenshot.googleplex.com/9UirWBGxheYVqV4

Bug: b/157080996
Test: added new tests.
Change-Id: I25fb18104f317ffad629bbf7d1fcc5302806cf20
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2407176
Commit-Queue: Tao Wu <wutao@chromium.org>
Reviewed-by: default avatarXiaohui Chen <xiaohuic@chromium.org>
Cr-Commit-Position: refs/heads/master@{#809702}
parent 4c5c54a6
......@@ -48,6 +48,10 @@ constexpr char kAmbientModeDirectoryName[] = "ambient-mode";
constexpr base::TimeDelta kTokenUsageTimeBuffer =
base::TimeDelta::FromMinutes(10);
// PhotoView related constants.
// Spacing between two portrait images.
constexpr int kMarginLeftOfRelatedImageDip = 8;
} // namespace ash
#endif // ASH_AMBIENT_AMBIENT_CONSTANTS_H_
......@@ -14,6 +14,7 @@
#include "ash/public/cpp/ambient/ambient_client.h"
#include "ash/public/cpp/image_downloader.h"
#include "ash/shell.h"
#include "base/barrier_closure.h"
#include "base/base64.h"
#include "base/base_paths.h"
#include "base/bind.h"
......@@ -324,15 +325,44 @@ void AmbientPhotoController::OnScreenUpdateInfoFetched(
StartDownloadingWeatherConditionIcon(screen_update.weather_info);
}
void AmbientPhotoController::ResetImageData() {
image_data_.reset();
related_image_data_.reset();
image_details_.reset();
image_ = gfx::ImageSkia();
related_image_ = gfx::ImageSkia();
}
void AmbientPhotoController::FetchPhotoRawData() {
const AmbientModeTopic* topic = GetNextTopic();
ResetImageData();
if (topic) {
const int num_callbacks = (topic->related_image_url) ? 2 : 1;
auto on_done = base::BarrierClosure(
num_callbacks,
base::BindOnce(&AmbientPhotoController::OnAllPhotoRawDataAvailable,
weak_factory_.GetWeakPtr(),
/*from_downloading=*/true));
url_loader_->Download(
topic->GetUrl(),
topic->url,
base::BindOnce(&AmbientPhotoController::OnPhotoRawDataAvailable,
weak_factory_.GetWeakPtr(),
/*from_downloading=*/true,
/*is_related_image=*/false, on_done,
std::make_unique<std::string>(topic->details)));
if (topic->related_image_url) {
url_loader_->Download(
*(topic->related_image_url),
base::BindOnce(&AmbientPhotoController::OnPhotoRawDataAvailable,
weak_factory_.GetWeakPtr(),
/*from_downloading=*/true,
/*is_related_image=*/true, on_done,
std::make_unique<std::string>(topic->details)));
}
return;
}
......@@ -367,6 +397,10 @@ void AmbientPhotoController::TryReadPhotoRawData() {
auto photo_data = std::make_unique<std::string>();
auto photo_details = std::make_unique<std::string>();
auto on_done =
base::BindRepeating(&AmbientPhotoController::OnAllPhotoRawDataAvailable,
weak_factory_.GetWeakPtr(),
/*from_downloading=*/false);
task_runner_->PostTaskAndReply(
FROM_HERE,
base::BindOnce(
......@@ -386,14 +420,27 @@ void AmbientPhotoController::TryReadPhotoRawData() {
file_name, photo_data.get(), photo_details.get()),
base::BindOnce(&AmbientPhotoController::OnPhotoRawDataAvailable,
weak_factory_.GetWeakPtr(), /*from_downloading=*/false,
/*is_related_image=*/false, on_done,
std::move(photo_details), std::move(photo_data)));
}
void AmbientPhotoController::OnPhotoRawDataAvailable(
bool from_downloading,
bool is_related_image,
base::RepeatingClosure on_done,
std::unique_ptr<std::string> details,
std::unique_ptr<std::string> data) {
if (!data || data->empty()) {
if (is_related_image)
related_image_data_ = std::move(data);
else {
image_data_ = std::move(data);
image_details_ = std::move(details);
}
std::move(on_done).Run();
}
void AmbientPhotoController::OnAllPhotoRawDataAvailable(bool from_downloading) {
if (!image_data_ || image_data_->empty()) {
if (from_downloading) {
LOG(ERROR) << "Failed to download image";
resume_fetch_image_backoff_.InformOfRequest(/*succeeded=*/false);
......@@ -414,6 +461,12 @@ void AmbientPhotoController::OnPhotoRawDataAvailable(
if (cache_index_for_store_ == kMaxNumberOfCachedImages)
cache_index_for_store_ = 0;
const int num_callbacks = related_image_data_ ? 2 : 1;
auto on_done = base::BarrierClosure(
num_callbacks,
base::BindOnce(&AmbientPhotoController::OnAllPhotoDecoded,
weak_factory_.GetWeakPtr(), from_downloading));
task_runner_->PostTaskAndReply(
FROM_HERE,
base::BindOnce(
......@@ -425,28 +478,44 @@ void AmbientPhotoController::OnPhotoRawDataAvailable(
details);
}
},
file_name, from_downloading, *data, *details),
file_name, from_downloading, *image_data_, *image_details_),
base::BindOnce(&AmbientPhotoController::DecodePhotoRawData,
weak_factory_.GetWeakPtr(), from_downloading,
std::move(details), std::move(data)));
/*is_related_image=*/false, on_done,
std::move(image_data_)));
if (related_image_data_) {
DecodePhotoRawData(from_downloading, /*is_related_image=*/true, on_done,
std::move(related_image_data_));
}
}
void AmbientPhotoController::DecodePhotoRawData(
bool from_downloading,
std::unique_ptr<std::string> details,
bool is_related_image,
base::RepeatingClosure on_done,
std::unique_ptr<std::string> data) {
std::vector<uint8_t> image_bytes(data->begin(), data->end());
image_decoder_->Decode(
image_bytes, base::BindOnce(&AmbientPhotoController::OnPhotoDecoded,
weak_factory_.GetWeakPtr(), from_downloading,
std::move(details)));
is_related_image, on_done));
}
void AmbientPhotoController::OnPhotoDecoded(
bool from_downloading,
std::unique_ptr<std::string> details,
void AmbientPhotoController::OnPhotoDecoded(bool from_downloading,
bool is_related_image,
base::RepeatingClosure on_done,
const gfx::ImageSkia& image) {
if (image.isNull()) {
if (is_related_image)
related_image_ = image;
else
image_ = image;
std::move(on_done).Run();
}
void AmbientPhotoController::OnAllPhotoDecoded(bool from_downloading) {
if (image_.isNull()) {
LOG(WARNING) << "Image is null";
if (from_downloading)
resume_fetch_image_backoff_.InformOfRequest(/*succeeded=*/false);
......@@ -461,8 +530,12 @@ void AmbientPhotoController::OnPhotoDecoded(
resume_fetch_image_backoff_.InformOfRequest(/*succeeded=*/true);
PhotoWithDetails detailed_photo;
detailed_photo.photo = image;
detailed_photo.details = *details;
detailed_photo.photo = image_;
detailed_photo.related_photo = related_image_;
detailed_photo.details = *image_details_;
ResetImageData();
ambient_backend_model_.AddNextImage(std::move(detailed_photo));
ScheduleRefreshImage();
......
......@@ -118,6 +118,9 @@ class ASH_EXPORT AmbientPhotoController : public AmbientBackendModelObserver {
void OnScreenUpdateInfoFetched(const ash::ScreenUpdate& screen_update);
// Clear temporary image data to prepare next photos.
void ResetImageData();
// Fetch photo raw data by downloading or reading from cache.
void FetchPhotoRawData();
......@@ -125,17 +128,25 @@ class ASH_EXPORT AmbientPhotoController : public AmbientBackendModelObserver {
void TryReadPhotoRawData();
void OnPhotoRawDataAvailable(bool from_downloading,
bool is_related_image,
base::RepeatingClosure on_done,
std::unique_ptr<std::string> details,
std::unique_ptr<std::string> data);
void OnAllPhotoRawDataAvailable(bool from_downloading);
void DecodePhotoRawData(bool from_downloading,
std::unique_ptr<std::string> details,
bool is_related_image,
base::RepeatingClosure on_done,
std::unique_ptr<std::string> data);
void OnPhotoDecoded(bool from_downloading,
std::unique_ptr<std::string> details,
bool is_related_image,
base::RepeatingClosure on_done,
const gfx::ImageSkia& image);
void OnAllPhotoDecoded(bool from_downloading);
void StartDownloadingWeatherConditionIcon(
const base::Optional<WeatherInfo>& weather_info);
......@@ -209,6 +220,13 @@ class ASH_EXPORT AmbientPhotoController : public AmbientBackendModelObserver {
scoped_refptr<base::SequencedTaskRunner> task_runner_;
// Temporary data store when fetching images and details.
std::unique_ptr<std::string> image_data_;
std::unique_ptr<std::string> related_image_data_;
std::unique_ptr<std::string> image_details_;
gfx::ImageSkia image_;
gfx::ImageSkia related_image_;
base::WeakPtrFactory<AmbientPhotoController> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(AmbientPhotoController);
......
......@@ -127,9 +127,22 @@ ScreenUpdate ToScreenUpdate(
for (auto& backdrop_topic : backdrop_screen_update.next_topics()) {
AmbientModeTopic ambient_topic;
DCHECK(backdrop_topic.has_url());
ambient_topic.url = backdrop_topic.url();
if (backdrop_topic.has_portrait_image_url())
ambient_topic.portrait_image_url = backdrop_topic.portrait_image_url();
ambient_topic.url = backdrop_topic.portrait_image_url();
else
ambient_topic.url = backdrop_topic.url();
if (backdrop_topic.has_related_topic()) {
if (backdrop_topic.related_topic().has_portrait_image_url()) {
ambient_topic.related_image_url =
backdrop_topic.related_topic().portrait_image_url();
} else {
ambient_topic.related_image_url =
backdrop_topic.related_topic().url();
}
}
BuildBackdropTopicDetails(backdrop_topic, ambient_topic);
screen_update.next_topics.emplace_back(ambient_topic);
}
......
......@@ -34,6 +34,7 @@ struct ASH_EXPORT PhotoWithDetails {
bool IsNull() const;
gfx::ImageSkia photo;
gfx::ImageSkia related_photo;
std::string details;
};
......
......@@ -6,17 +6,22 @@
#include <memory>
#include "ash/ambient/ambient_constants.h"
#include "ash/ambient/ui/glanceable_info_view.h"
#include "ash/ambient/util/ambient_util.h"
#include "ash/assistant/ui/assistant_view_ids.h"
#include "base/rand_util.h"
#include "ui/events/event.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/layout/flex_layout.h"
#include "ui/views/layout/flex_layout_types.h"
#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/view_class_properties.h"
namespace ash {
......@@ -39,6 +44,37 @@ int translate_y_direction = -1;
int current_x_translation = 0;
int current_y_translation = 0;
const views::FlexSpecification kUnboundedScaleToZero(
views::MinimumFlexSizeRule::kScaleToZero,
views::MaximumFlexSizeRule::kUnbounded);
gfx::ImageSkia ResizeImage(const gfx::ImageSkia& image,
const gfx::Size& view_size) {
if (image.isNull())
return gfx::ImageSkia();
const double image_width = image.width();
const double image_height = image.height();
const double view_width = view_size.width();
const double view_height = view_size.height();
const double horizontal_ratio = view_width / image_width;
const double vertical_ratio = view_height / image_height;
const double image_ratio = image_height / image_width;
const double view_ratio = view_height / view_width;
// If the image and the container view has the same orientation, e.g. both
// portrait, the |scale| will make the image filled the whole view with
// possible cropping on one direction. If they are in different orientation,
// the |scale| will display the image in the view without any cropping, but
// with empty background.
const double scale = (image_ratio - 1) * (view_ratio - 1) > 0
? std::max(horizontal_ratio, vertical_ratio)
: std::min(horizontal_ratio, vertical_ratio);
const gfx::Size& resized = gfx::ScaleToCeiledSize(image.size(), scale);
return gfx::ImageSkiaOperations::CreateResizedImage(
image, skia::ImageOperations::RESIZE_BEST, resized);
}
} // namespace
AmbientBackgroundImageView::AmbientBackgroundImageView(
......@@ -65,10 +101,43 @@ void AmbientBackgroundImageView::OnGestureEvent(ui::GestureEvent* event) {
}
}
void AmbientBackgroundImageView::UpdateImage(const gfx::ImageSkia& img) {
image_view_->SetImage(img);
void AmbientBackgroundImageView::OnBoundsChanged(
const gfx::Rect& previous_bounds) {
if (!GetVisible())
return;
if (width() == 0)
return;
// When bounds changes, recalculate the visibility of related image view.
UpdateRelatedImageViewVisibility();
}
void AmbientBackgroundImageView::OnViewBoundsChanged(
views::View* observed_view) {
if (observed_view == image_view_)
SetResizedImage(image_view_, image_unscaled_);
else
SetResizedImage(related_image_view_, related_image_unscaled_);
}
void AmbientBackgroundImageView::UpdateImage(
const gfx::ImageSkia& image,
const gfx::ImageSkia& related_image) {
image_unscaled_ = image;
related_image_unscaled_ = related_image;
UpdateGlanceableInfoPosition();
const bool has_change = UpdateRelatedImageViewVisibility();
// If there is no change in the visibility of related image view, call
// SetResizedImages() directly. Otherwise it will be called from
// OnViewBoundsChanged().
if (!has_change) {
SetResizedImage(image_view_, image_unscaled_);
SetResizedImage(related_image_view_, related_image_unscaled_);
}
}
void AmbientBackgroundImageView::UpdateImageDetails(
......@@ -80,15 +149,49 @@ const gfx::ImageSkia& AmbientBackgroundImageView::GetCurrentImage() {
return image_view_->GetImage();
}
gfx::Rect AmbientBackgroundImageView::GetCurrentImageBoundsForTesting() const {
gfx::Rect AmbientBackgroundImageView::GetImageBoundsForTesting() const {
return image_view_->GetImageBounds();
}
gfx::Rect AmbientBackgroundImageView::GetRelatedImageBoundsForTesting() const {
return related_image_view_->GetVisible()
? related_image_view_->GetImageBounds()
: gfx::Rect();
}
void AmbientBackgroundImageView::ResetRelatedImageForTesting() {
related_image_unscaled_ = gfx::ImageSkia();
UpdateRelatedImageViewVisibility();
}
void AmbientBackgroundImageView::InitLayout() {
SetLayoutManager(std::make_unique<views::FillLayout>());
// Inits the image view. This view should have the same size of the screen.
image_view_ = AddChildView(std::make_unique<views::ImageView>());
// Inits container for images.
image_container_ = AddChildView(std::make_unique<views::View>());
views::FlexLayout* image_layout =
image_container_->SetLayoutManager(std::make_unique<views::FlexLayout>());
image_layout->SetOrientation(views::LayoutOrientation::kHorizontal);
image_layout->SetMainAxisAlignment(views::LayoutAlignment::kCenter);
image_layout->SetCrossAxisAlignment(views::LayoutAlignment::kStretch);
image_view_ =
image_container_->AddChildView(std::make_unique<views::ImageView>());
// Set a place holder size for Flex layout to assign bounds.
image_view_->SetPreferredSize(gfx::Size(1, 1));
image_view_->SetProperty(views::kFlexBehaviorKey, kUnboundedScaleToZero);
observed_views_.Add(image_view_);
related_image_view_ =
image_container_->AddChildView(std::make_unique<views::ImageView>());
// Set a place holder size for Flex layout to assign bounds.
related_image_view_->SetPreferredSize(gfx::Size(1, 1));
related_image_view_->SetProperty(views::kFlexBehaviorKey,
kUnboundedScaleToZero);
observed_views_.Add(related_image_view_);
// Set spacing between two images.
related_image_view_->SetProperty(
views::kMarginsKey, gfx::Insets(0, kMarginLeftOfRelatedImageDip, 0, 0));
gfx::Insets shadow_insets =
gfx::ShadowValue::GetMargin(ambient::util::GetTextShadowValues());
......@@ -161,6 +264,41 @@ void AmbientBackgroundImageView::UpdateGlanceableInfoPosition() {
details_label_->layer()->SetTransform(transform);
}
bool AmbientBackgroundImageView::UpdateRelatedImageViewVisibility() {
const bool did_show_pair = related_image_view_->GetVisible();
const bool show_pair = IsLandscapeOrientation() && HasPairedPortraitImages();
related_image_view_->SetVisible(show_pair);
return did_show_pair != show_pair;
}
void AmbientBackgroundImageView::SetResizedImage(
views::ImageView* image_view,
const gfx::ImageSkia& image_unscaled) {
if (!image_view->GetVisible())
return;
if (image_unscaled.isNull())
return;
image_view->SetImage(ResizeImage(image_unscaled, image_view->size()));
// Intend to update the image origin in image view.
// There is no bounds change or preferred size change when updating image from
// landscape to portrait when device is in portrait orientation because we
// only show one photo. Call ResetImageSize() to trigger UpdateImageOrigin().
image_view->ResetImageSize();
}
bool AmbientBackgroundImageView::IsLandscapeOrientation() const {
return width() > height();
}
bool AmbientBackgroundImageView::HasPairedPortraitImages() const {
const auto& primary_image = image_unscaled_;
return !primary_image.isNull() && !related_image_unscaled_.isNull() &&
primary_image.height() > primary_image.width();
}
BEGIN_METADATA(AmbientBackgroundImageView, views::View)
END_METADATA
......
......@@ -9,9 +9,11 @@
#include "ash/ambient/ui/ambient_view_delegate.h"
#include "ash/ash_export.h"
#include "base/scoped_observer.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/metadata/metadata_header_macros.h"
#include "ui/views/view.h"
#include "ui/views/view_observer.h"
namespace views {
class Label;
......@@ -25,7 +27,8 @@ class GlanceableInfoView;
// A custom ImageView to display photo image and details information on ambient.
// It also handles specific mouse/gesture events to dismiss ambient when user
// interacts with the background photos.
class ASH_EXPORT AmbientBackgroundImageView : public views::View {
class ASH_EXPORT AmbientBackgroundImageView : public views::View,
public views::ViewObserver {
public:
METADATA_HEADER(AmbientBackgroundImageView);
......@@ -34,36 +37,60 @@ class ASH_EXPORT AmbientBackgroundImageView : public views::View {
AmbientBackgroundImageView& operator=(AmbientBackgroundImageView&) = delete;
~AmbientBackgroundImageView() override;
// views::View
// views::View:
bool OnMousePressed(const ui::MouseEvent& event) override;
void OnGestureEvent(ui::GestureEvent* event) override;
void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
// Updates the display image.
void UpdateImage(const gfx::ImageSkia& img);
// views::ViewObserver:
void OnViewBoundsChanged(views::View* observed_view) override;
// Updates the display images.
void UpdateImage(const gfx::ImageSkia& image,
const gfx::ImageSkia& related_image);
// Updates the details for the currently displayed image.
void UpdateImageDetails(const base::string16& details);
const gfx::ImageSkia& GetCurrentImage();
gfx::Rect GetCurrentImageBoundsForTesting() const;
gfx::Rect GetImageBoundsForTesting() const;
gfx::Rect GetRelatedImageBoundsForTesting() const;
void ResetRelatedImageForTesting();
private:
void InitLayout();
void UpdateGlanceableInfoPosition();
bool UpdateRelatedImageViewVisibility();
void SetResizedImage(views::ImageView* image_view,
const gfx::ImageSkia& image_unscaled);
// Whether the device is in landscape orientation.
bool IsLandscapeOrientation() const;
bool HasPairedPortraitImages() const;
// Owned by |AmbientController| and should always outlive |this|.
AmbientViewDelegate* delegate_ = nullptr;
// View to display the current image on ambient. Owned by the view hierarchy.
// View to display current image(s) on ambient. Owned by the view hierarchy.
views::View* image_container_ = nullptr;
views::ImageView* image_view_ = nullptr;
views::ImageView* related_image_view_ = nullptr;
// The unscaled images used for scaling and displaying in different bounds.
gfx::ImageSkia image_unscaled_;
gfx::ImageSkia related_image_unscaled_;
GlanceableInfoView* glanceable_info_view_ = nullptr;
// Label to show details text, i.e. attribution, to be displayed for the
// current image. Owned by the view hierarchy.
views::Label* details_label_ = nullptr;
ScopedObserver<views::View, views::ViewObserver> observed_views_{this};
};
} // namespace ash
......
......@@ -21,7 +21,6 @@
#include "ui/compositor/animation_throughput_reporter.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/layout/fill_layout.h"
......@@ -36,32 +35,6 @@ void ReportSmoothness(int value) {
base::UmaHistogramPercentage(kPhotoTransitionSmoothness, value);
}
gfx::ImageSkia ResizeImage(const gfx::ImageSkia& image,
const gfx::Size& view_size) {
if (image.isNull())
return gfx::ImageSkia();
const double image_width = image.width();
const double image_height = image.height();
const double view_width = view_size.width();
const double view_height = view_size.height();
const double horizontal_ratio = view_width / image_width;
const double vertical_ratio = view_height / image_height;
const double image_ratio = image_height / image_width;
const double view_ratio = view_height / view_width;
// If the image and the container view has the same orientation, e.g. both
// portrait, the |scale| will make the image filled the whole view with
// possible cropping on one direction. If they are in different orientation,
// the |scale| will display the image in the view without any cropping, but
// with empty background.
const double scale = (image_ratio - 1) * (view_ratio - 1) > 0
? std::max(horizontal_ratio, vertical_ratio)
: std::min(horizontal_ratio, vertical_ratio);
const gfx::Size& resized = gfx::ScaleToCeiledSize(image.size(), scale);
return gfx::ImageSkiaOperations::CreateResizedImage(
image, skia::ImageOperations::RESIZE_BEST, resized);
}
} // namespace
......@@ -80,14 +53,6 @@ const char* PhotoView::GetClassName() const {
return "PhotoView";
}
void PhotoView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
for (const int index : {0, 1}) {
auto image = images_unscaled_[index];
auto image_resized = ResizeImage(image, size());
image_views_[index]->UpdateImage(image_resized);
}
}
void PhotoView::OnImagesChanged() {
// If NeedToAnimate() is true, will start transition animation and
// UpdateImages() when animation completes. Otherwise, update images
......@@ -123,12 +88,11 @@ void PhotoView::Init() {
void PhotoView::UpdateImages() {
auto* model = delegate_->GetAmbientBackendModel();
auto& next_image = model->GetNextImage();
images_unscaled_[image_index_] = next_image.photo;
if (images_unscaled_[image_index_].isNull())
if (next_image.photo.isNull())
return;
auto next_resized = ResizeImage(images_unscaled_[image_index_], size());
image_views_[image_index_]->UpdateImage(next_resized);
image_views_[image_index_]->UpdateImage(next_image.photo,
next_image.related_photo);
image_views_[image_index_]->UpdateImageDetails(
base::UTF8ToUTF16(next_image.details));
image_index_ = 1 - image_index_;
......@@ -178,7 +142,7 @@ void PhotoView::OnImplicitAnimationsCompleted() {
bool PhotoView::NeedToAnimateTransition() const {
// Can do transition animation if both two images in |images_unscaled_| are
// not nullptr. Check the image index 1 is enough.
return !images_unscaled_[1].isNull();
return !image_views_[1]->GetCurrentImage().isNull();
}
const gfx::ImageSkia& PhotoView::GetCurrentImagesForTesting() {
......
......@@ -35,7 +35,6 @@ class ASH_EXPORT PhotoView : public views::View,
// views::View:
const char* GetClassName() const override;
void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
// AmbientBackendModelObserver:
void OnImagesChanged() override;
......@@ -47,7 +46,9 @@ class ASH_EXPORT PhotoView : public views::View,
friend class AmbientAshTestBase;
void Init();
void UpdateImages();
void StartTransitionAnimation();
// Return if can start transition animation.
......@@ -62,9 +63,6 @@ class ASH_EXPORT PhotoView : public views::View,
// Image containers used for animation. Owned by view hierarchy.
AmbientBackgroundImageView* image_views_[2]{nullptr, nullptr};
// The unscaled images used for scaling and displaying in different bounds.
gfx::ImageSkia images_unscaled_[2];
// The index of |image_views_| to update the next image.
int image_index_ = 0;
};
......
This diff is collapsed.
......@@ -31,10 +31,6 @@ AmbientModeTopic& AmbientModeTopic::operator=(const AmbientModeTopic&) =
AmbientModeTopic::~AmbientModeTopic() = default;
std::string AmbientModeTopic::GetUrl() const {
return portrait_image_url.value_or(url);
}
// WeatherInfo------------------------------------------------------------------
WeatherInfo::WeatherInfo() = default;
......
......@@ -27,9 +27,6 @@ struct ASH_PUBLIC_EXPORT AmbientModeTopic {
AmbientModeTopic& operator=(const AmbientModeTopic&);
~AmbientModeTopic();
// Returns a non-empty url to load the landscape or portrait image.
std::string GetUrl() const;
// Details, i.e. the attribution, to be displayed for the current photo on
// ambient.
std::string details;
......@@ -37,9 +34,8 @@ struct ASH_PUBLIC_EXPORT AmbientModeTopic {
// Image url.
std::string url;
// Optional for non-cropped portrait style images. The same image as in
// |url| but it is not cropped and is better for portrait displaying.
base::Optional<std::string> portrait_image_url;
// Only support portrait image tiling in landscape orientation.
base::Optional<std::string> related_image_url;
};
// WeatherInfo contains the weather information we need for rendering a
......
......@@ -81,6 +81,7 @@ void FakeAmbientBackendControllerImpl::FetchScreenUpdateInfo(
ash::AmbientModeTopic topic;
topic.url = kFakeUrl;
topic.details = kFakeDetails;
topic.related_image_url = kFakeUrl;
ash::WeatherInfo weather_info;
weather_info.temp_f = .0f;
......
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