diff options
author | kylechar <kylechar@chromium.org> | 2015-12-21 10:43:01 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-12-21 18:43:55 +0000 |
commit | fd9f15be2e290d54095d1b3c6b2285d89447e984 (patch) | |
tree | 9b467918c3d45f25bba9a99980e0c85c1069ea3e | |
parent | 6dc3bf73c353723a434a55008ffd354b1b682705 (diff) | |
download | chromium_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.cc | 37 | ||||
-rw-r--r-- | ui/gfx/skbitmap_operations.cc | 3 |
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); |