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, |