summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkylechar <kylechar@chromium.org>2015-12-21 10:43:01 -0800
committerCommit bot <commit-bot@chromium.org>2015-12-21 18:43:55 +0000
commitfd9f15be2e290d54095d1b3c6b2285d89447e984 (patch)
tree9b467918c3d45f25bba9a99980e0c85c1069ea3e
parent6dc3bf73c353723a434a55008ffd354b1b682705 (diff)
downloadchromium_src-fd9f15be2e290d54095d1b3c6b2285d89447e984.zip
chromium_src-fd9f15be2e290d54095d1b3c6b2285d89447e984.tar.gz
chromium_src-fd9f15be2e290d54095d1b3c6b2285d89447e984.tar.bz2
Fix bug where custom cursors would disappear when screen was rotated for ozone based platforms. This was caused by commit cd0a8ae72380dc461eea58084325d9d981942192. The change modified the cursor SkBitmap to always be in unpremultiplied alpha format. However, the SkCanvas::drawBitmap() operation fails silently if the SkBitmap is in unpremultiplied format and the ui::ScaleAndRotateCursorBitmapAndHotpoint() function relies on SkCanvas::drawBitmap() to rotate the cursor. This fails and the cursor disappears.
This fix temporarily converts the cursor bitmap back to premultiplied alpha before rotating. It also adds a DCHECK to SkBitmapOperations::Rotate() to document the alpha type requirement. BUG=533748 Review URL: https://codereview.chromium.org/1514723003 Cr-Commit-Position: refs/heads/master@{#366423}
-rw-r--r--ui/base/cursor/cursor_util.cc37
-rw-r--r--ui/gfx/skbitmap_operations.cc3
2 files changed, 40 insertions, 0 deletions
diff --git a/ui/base/cursor/cursor_util.cc b/ui/base/cursor/cursor_util.cc
index 193ab73..0e1d36e 100644
--- a/ui/base/cursor/cursor_util.cc
+++ b/ui/base/cursor/cursor_util.cc
@@ -15,10 +15,43 @@
namespace ui {
+namespace {
+
+// Converts the SkBitmap to use a different alpha type. Returns true if bitmap
+// was modified, otherwise returns false.
+bool ConvertSkBitmapAlphaType(SkBitmap* bitmap, SkAlphaType alpha_type) {
+ if (bitmap->info().alphaType() == alpha_type) {
+ return false;
+ }
+
+ // Copy the bitmap into a temporary buffer. This will convert alpha type.
+ SkImageInfo image_info =
+ SkImageInfo::MakeN32(bitmap->width(), bitmap->height(), alpha_type);
+ std::vector<char> buffer(bitmap->getSize());
+ bitmap->readPixels(image_info, &buffer[0], image_info.minRowBytes(), 0, 0);
+ // Read the temporary buffer back into the original bitmap.
+ bitmap->reset();
+ bitmap->allocPixels(image_info);
+ memcpy(bitmap->getPixels(), &buffer[0], buffer.size());
+
+ return true;
+}
+
+} // namespace
+
void ScaleAndRotateCursorBitmapAndHotpoint(float scale,
gfx::Display::Rotation rotation,
SkBitmap* bitmap,
gfx::Point* hotpoint) {
+ // SkBitmapOperations::Rotate() needs the bitmap to have premultiplied alpha,
+ // so convert bitmap alpha type if we are going to rotate.
+ bool was_converted = false;
+ if (rotation != gfx::Display::ROTATE_0 &&
+ bitmap->info().alphaType() == kUnpremul_SkAlphaType) {
+ ConvertSkBitmapAlphaType(bitmap, kPremul_SkAlphaType);
+ was_converted = true;
+ }
+
switch (rotation) {
case gfx::Display::ROTATE_0:
break;
@@ -40,6 +73,10 @@ void ScaleAndRotateCursorBitmapAndHotpoint(float scale,
break;
}
+ if (was_converted) {
+ ConvertSkBitmapAlphaType(bitmap, kUnpremul_SkAlphaType);
+ }
+
if (scale < FLT_EPSILON) {
NOTREACHED() << "Scale must be larger than 0.";
scale = 1.0f;
diff --git a/ui/gfx/skbitmap_operations.cc b/ui/gfx/skbitmap_operations.cc
index a12ef83..7d16bff 100644
--- a/ui/gfx/skbitmap_operations.cc
+++ b/ui/gfx/skbitmap_operations.cc
@@ -757,6 +757,9 @@ SkBitmap SkBitmapOperations::CreateDropShadow(
// static
SkBitmap SkBitmapOperations::Rotate(const SkBitmap& source,
RotationAmount rotation) {
+ // SkCanvas::drawBitmap() fails silently with unpremultiplied SkBitmap.
+ DCHECK_NE(source.info().alphaType(), kUnpremul_SkAlphaType);
+
SkBitmap result;
SkScalar angle = SkFloatToScalar(0.0f);