| Index: chrome/browser/tab_contents/thumbnail_generator.cc
|
| diff --git a/chrome/browser/tab_contents/thumbnail_generator.cc b/chrome/browser/tab_contents/thumbnail_generator.cc
|
| index f5cfb5790b4a28ef32796fc61f404515a21408da..dab34e52167198d0c0386f76557b0543aa462d88 100644
|
| --- a/chrome/browser/tab_contents/thumbnail_generator.cc
|
| +++ b/chrome/browser/tab_contents/thumbnail_generator.cc
|
| @@ -30,6 +30,7 @@
|
| #include "third_party/skia/include/core/SkBitmap.h"
|
| #include "ui/gfx/color_utils.h"
|
| #include "ui/gfx/rect.h"
|
| +#include "ui/gfx/scrollbar_size.h"
|
| #include "ui/gfx/skbitmap_operations.h"
|
|
|
| #if defined(OS_WIN)
|
| @@ -91,26 +92,77 @@ gfx::Size GetCopySizeForThumbnail(const gfx::Size& view_size,
|
| static_cast<int>(scale * view_size.height()));
|
| }
|
|
|
| +// Returns the clipping rectangle that is used for creating a thumbnail with
|
| +// the size of |desired_size| from the bitmap with the size of |source_size|.
|
| +// The type of clipping that needs to be done is assigned to |clip_result|.
|
| +gfx::Rect GetClippingRect(const gfx::Size& source_size,
|
| + const gfx::Size& desired_size,
|
| + ThumbnailGenerator::ClipResult* clip_result) {
|
| + DCHECK(clip_result);
|
| +
|
| + float desired_aspect =
|
| + static_cast<float>(desired_size.width()) / desired_size.height();
|
| +
|
| + // Get the clipping rect so that we can preserve the aspect ratio while
|
| + // filling the destination.
|
| + gfx::Rect clipping_rect;
|
| + if (source_size.width() < desired_size.width() ||
|
| + source_size.height() < desired_size.height()) {
|
| + // Source image is smaller: we clip the part of source image within the
|
| + // dest rect, and then stretch it to fill the dest rect. We don't respect
|
| + // the aspect ratio in this case.
|
| + clipping_rect = gfx::Rect(desired_size);
|
| + *clip_result = ThumbnailGenerator::kSourceIsSmaller;
|
| + } else {
|
| + float src_aspect =
|
| + static_cast<float>(source_size.width()) / source_size.height();
|
| + if (src_aspect > desired_aspect) {
|
| + // Wider than tall, clip horizontally: we center the smaller
|
| + // thumbnail in the wider screen.
|
| + int new_width = static_cast<int>(source_size.height() * desired_aspect);
|
| + int x_offset = (source_size.width() - new_width) / 2;
|
| + clipping_rect.SetRect(x_offset, 0, new_width, source_size.height());
|
| + *clip_result = (src_aspect >= ThumbnailScore::kTooWideAspectRatio) ?
|
| + ThumbnailGenerator::kTooWiderThanTall :
|
| + ThumbnailGenerator::kWiderThanTall;
|
| + } else if (src_aspect < desired_aspect) {
|
| + clipping_rect =
|
| + gfx::Rect(source_size.width(), source_size.width() / desired_aspect);
|
| + *clip_result = ThumbnailGenerator::kTallerThanWide;
|
| + } else {
|
| + clipping_rect = gfx::Rect(source_size);
|
| + *clip_result = ThumbnailGenerator::kNotClipped;
|
| + }
|
| + }
|
| + return clipping_rect;
|
| +}
|
| +
|
| // Creates a downsampled thumbnail from the given bitmap.
|
| // store. The returned bitmap will be isNull if there was an error creating it.
|
| SkBitmap CreateThumbnail(
|
| - const SkBitmap& bmp_with_scrollbars,
|
| + const SkBitmap& bitmap,
|
| int desired_width,
|
| int desired_height,
|
| ThumbnailGenerator::ClipResult* clip_result) {
|
| base::TimeTicks begin_compute_thumbnail = base::TimeTicks::Now();
|
|
|
| - // Clip the edgemost 15 pixels as that will commonly hold a scrollbar, which
|
| - // looks bad in thumbnails.
|
| - SkIRect scrollbarless_rect =
|
| - { 0, 0,
|
| - std::max(1, bmp_with_scrollbars.width() - 15),
|
| - std::max(1, bmp_with_scrollbars.height() - 15) };
|
| - SkBitmap bmp;
|
| - bmp_with_scrollbars.extractSubset(&bmp, scrollbarless_rect);
|
| -
|
| - SkBitmap clipped_bitmap = ThumbnailGenerator::GetClippedBitmap(
|
| - bmp, desired_width, desired_height, clip_result);
|
| + SkBitmap clipped_bitmap;
|
| + if (*clip_result == ThumbnailGenerator::kUnprocessed) {
|
| + // Clip the pixels that will commonly hold a scrollbar, which looks bad in
|
| + // thumbnails.
|
| + int scrollbar_size = gfx::scrollbar_size();
|
| + SkIRect scrollbarless_rect =
|
| + { 0, 0,
|
| + std::max(1, bitmap.width() - scrollbar_size),
|
| + std::max(1, bitmap.height() - scrollbar_size) };
|
| + SkBitmap bmp;
|
| + bitmap.extractSubset(&bmp, scrollbarless_rect);
|
| +
|
| + clipped_bitmap = ThumbnailGenerator::GetClippedBitmap(
|
| + bmp, desired_width, desired_height, clip_result);
|
| + } else {
|
| + clipped_bitmap = bitmap;
|
| + }
|
|
|
| // Need to resize it to the size we want, so downsample until it's
|
| // close, and let the caller make it the exact size if desired.
|
| @@ -376,49 +428,12 @@ SkBitmap ThumbnailGenerator::GetClippedBitmap(const SkBitmap& bitmap,
|
| int desired_width,
|
| int desired_height,
|
| ClipResult* clip_result) {
|
| - const SkRect dest_rect = { 0, 0,
|
| - SkIntToScalar(desired_width),
|
| - SkIntToScalar(desired_height) };
|
| - const float dest_aspect = dest_rect.width() / dest_rect.height();
|
| -
|
| - // Get the src rect so that we can preserve the aspect ratio while filling
|
| - // the destination.
|
| - SkIRect src_rect;
|
| - if (bitmap.width() < dest_rect.width() ||
|
| - bitmap.height() < dest_rect.height()) {
|
| - // Source image is smaller: we clip the part of source image within the
|
| - // dest rect, and then stretch it to fill the dest rect. We don't respect
|
| - // the aspect ratio in this case.
|
| - src_rect.set(0, 0, static_cast<S16CPU>(dest_rect.width()),
|
| - static_cast<S16CPU>(dest_rect.height()));
|
| - if (clip_result)
|
| - *clip_result = ThumbnailGenerator::kSourceIsSmaller;
|
| - } else {
|
| - const float src_aspect =
|
| - static_cast<float>(bitmap.width()) / bitmap.height();
|
| - if (src_aspect > dest_aspect) {
|
| - // Wider than tall, clip horizontally: we center the smaller
|
| - // thumbnail in the wider screen.
|
| - S16CPU new_width = static_cast<S16CPU>(bitmap.height() * dest_aspect);
|
| - S16CPU x_offset = (bitmap.width() - new_width) / 2;
|
| - src_rect.set(x_offset, 0, new_width + x_offset, bitmap.height());
|
| - if (clip_result) {
|
| - *clip_result = (src_aspect >= ThumbnailScore::kTooWideAspectRatio) ?
|
| - ThumbnailGenerator::kTooWiderThanTall :
|
| - ThumbnailGenerator::kWiderThanTall;
|
| - }
|
| - } else if (src_aspect < dest_aspect) {
|
| - src_rect.set(0, 0, bitmap.width(),
|
| - static_cast<S16CPU>(bitmap.width() / dest_aspect));
|
| - if (clip_result)
|
| - *clip_result = ThumbnailGenerator::kTallerThanWide;
|
| - } else {
|
| - src_rect.set(0, 0, bitmap.width(), bitmap.height());
|
| - if (clip_result)
|
| - *clip_result = ThumbnailGenerator::kNotClipped;
|
| - }
|
| - }
|
| -
|
| + gfx::Rect clipping_rect =
|
| + GetClippingRect(gfx::Size(bitmap.width(), bitmap.height()),
|
| + gfx::Size(desired_width, desired_height),
|
| + clip_result);
|
| + SkIRect src_rect = { clipping_rect.x(), clipping_rect.y(),
|
| + clipping_rect.right(), clipping_rect.bottom() };
|
| SkBitmap clipped_bitmap;
|
| bitmap.extractSubset(&clipped_bitmap, src_rect);
|
| return clipped_bitmap;
|
| @@ -443,7 +458,7 @@ void ThumbnailGenerator::UpdateThumbnailIfNecessary(
|
|
|
| void ThumbnailGenerator::UpdateThumbnail(
|
| WebContents* web_contents, const SkBitmap& thumbnail,
|
| - const ThumbnailGenerator::ClipResult& clip_result) {
|
| + const ClipResult& clip_result) {
|
|
|
| Profile* profile =
|
| Profile::FromBrowserContext(web_contents->GetBrowserContext());
|
| @@ -486,7 +501,8 @@ void ThumbnailGenerator::AsyncUpdateThumbnail(
|
| AskForSnapshot(render_widget_host,
|
| base::Bind(&ThumbnailGenerator::UpdateThumbnailWithBitmap,
|
| weak_factory_.GetWeakPtr(),
|
| - web_contents),
|
| + web_contents,
|
| + ThumbnailGenerator::kUnprocessed),
|
| view_size,
|
| view_size);
|
| }
|
| @@ -494,28 +510,37 @@ void ThumbnailGenerator::AsyncUpdateThumbnail(
|
| return;
|
| }
|
|
|
| + gfx::Rect copy_rect = gfx::Rect(view->GetViewBounds().size());
|
| + // Clip the pixels that will commonly hold a scrollbar, which looks bad in
|
| + // thumbnails.
|
| + int scrollbar_size = gfx::scrollbar_size();
|
| + copy_rect.Inset(0, 0, scrollbar_size, scrollbar_size);
|
| + ClipResult clip_result = ThumbnailGenerator::kUnprocessed;
|
| + copy_rect = GetClippingRect(copy_rect.size(),
|
| + gfx::Size(kThumbnailWidth, kThumbnailHeight),
|
| + &clip_result);
|
| gfx::Size copy_size =
|
| - GetCopySizeForThumbnail(view->GetViewBounds().size(),
|
| - gfx::Size(kThumbnailWidth, kThumbnailHeight));
|
| + gfx::Size(kThumbnailWidth, kThumbnailHeight).Scale(kThumbnailCopyScale);
|
| skia::PlatformCanvas* temp_canvas = new skia::PlatformCanvas;
|
| render_widget_host->CopyFromBackingStore(
|
| - gfx::Rect(),
|
| + copy_rect,
|
| copy_size,
|
| base::Bind(&ThumbnailGenerator::UpdateThumbnailWithCanvas,
|
| weak_factory_.GetWeakPtr(),
|
| web_contents,
|
| + clip_result,
|
| base::Owned(temp_canvas)),
|
| temp_canvas);
|
| }
|
|
|
| void ThumbnailGenerator::UpdateThumbnailWithBitmap(
|
| WebContents* web_contents,
|
| + ClipResult clip_result,
|
| const SkBitmap& bitmap) {
|
| DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
| if (bitmap.isNull() || bitmap.empty())
|
| return;
|
|
|
| - ClipResult clip_result;
|
| SkBitmap thumbnail = CreateThumbnail(bitmap,
|
| kThumbnailWidth,
|
| kThumbnailHeight,
|
| @@ -525,15 +550,15 @@ void ThumbnailGenerator::UpdateThumbnailWithBitmap(
|
|
|
| void ThumbnailGenerator::UpdateThumbnailWithCanvas(
|
| WebContents* web_contents,
|
| + ClipResult clip_result,
|
| skia::PlatformCanvas* temp_canvas,
|
| bool succeeded) {
|
| DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
| if (!succeeded)
|
| return;
|
|
|
| - SkBitmap bmp_with_scrollbars =
|
| - skia::GetTopDevice(*temp_canvas)->accessBitmap(false);
|
| - UpdateThumbnailWithBitmap(web_contents, bmp_with_scrollbars);
|
| + SkBitmap bitmap = skia::GetTopDevice(*temp_canvas)->accessBitmap(false);
|
| + UpdateThumbnailWithBitmap(web_contents, clip_result, bitmap);
|
| }
|
|
|
| bool ThumbnailGenerator::ShouldUpdateThumbnail(Profile* profile,
|
|
|