// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "ui/gfx/android/java_bitmap.h" #include #include "base/android/jni_string.h" #include "base/logging.h" #include "jni/BitmapHelper_jni.h" #include "ui/gfx/geometry/size.h" using base::android::AttachCurrentThread; using base::android::ConvertUTF8ToJavaString; using base::android::ScopedJavaLocalRef; using base::android::JavaRef; namespace gfx { JavaBitmap::JavaBitmap(const JavaRef& bitmap) : bitmap_(bitmap), pixels_(NULL) { int err = AndroidBitmap_lockPixels(AttachCurrentThread(), bitmap_.obj(), &pixels_); DCHECK(!err); DCHECK(pixels_); AndroidBitmapInfo info; err = AndroidBitmap_getInfo(AttachCurrentThread(), bitmap_.obj(), &info); DCHECK(!err); size_ = gfx::Size(info.width, info.height); format_ = info.format; stride_ = info.stride; byte_count_ = Java_BitmapHelper_getByteCount(AttachCurrentThread(), bitmap_); } JavaBitmap::~JavaBitmap() { int err = AndroidBitmap_unlockPixels(AttachCurrentThread(), bitmap_.obj()); DCHECK(!err); } static int SkColorTypeToBitmapFormat(SkColorType color_type) { switch (color_type) { case kAlpha_8_SkColorType: return BITMAP_FORMAT_ALPHA_8; case kARGB_4444_SkColorType: return BITMAP_FORMAT_ARGB_4444; case kN32_SkColorType: return BITMAP_FORMAT_ARGB_8888; case kRGB_565_SkColorType: return BITMAP_FORMAT_RGB_565; case kUnknown_SkColorType: default: NOTREACHED(); return BITMAP_FORMAT_NO_CONFIG; } } ScopedJavaLocalRef CreateJavaBitmap(int width, int height, SkColorType color_type) { DCHECK_GT(width, 0); DCHECK_GT(height, 0); int java_bitmap_config = SkColorTypeToBitmapFormat(color_type); return Java_BitmapHelper_createBitmap( AttachCurrentThread(), width, height, java_bitmap_config); } ScopedJavaLocalRef ConvertToJavaBitmap(const SkBitmap* skbitmap) { DCHECK(skbitmap); DCHECK(!skbitmap->isNull()); SkColorType color_type = skbitmap->colorType(); DCHECK((color_type == kRGB_565_SkColorType) || (color_type == kN32_SkColorType)); ScopedJavaLocalRef jbitmap = CreateJavaBitmap( skbitmap->width(), skbitmap->height(), color_type); JavaBitmap dst_lock(jbitmap); void* src_pixels = skbitmap->getPixels(); void* dst_pixels = dst_lock.pixels(); memcpy(dst_pixels, src_pixels, skbitmap->computeByteSize()); return jbitmap; } SkBitmap CreateSkBitmapFromJavaBitmap(const JavaBitmap& jbitmap) { DCHECK(!jbitmap.size().IsEmpty()); DCHECK_GT(jbitmap.stride(), 0U); DCHECK(jbitmap.pixels()); gfx::Size src_size = jbitmap.size(); SkBitmap skbitmap; switch (jbitmap.format()) { case ANDROID_BITMAP_FORMAT_RGBA_8888: skbitmap.allocPixels(SkImageInfo::MakeN32Premul(src_size.width(), src_size.height()), jbitmap.stride()); break; case ANDROID_BITMAP_FORMAT_A_8: skbitmap.allocPixels(SkImageInfo::MakeA8(src_size.width(), src_size.height()), jbitmap.stride()); break; default: CHECK(false) << "Invalid Java bitmap format: " << jbitmap.format(); break; } CHECK_EQ(jbitmap.byte_count(), static_cast(skbitmap.computeByteSize())); const void* src_pixels = jbitmap.pixels(); void* dst_pixels = skbitmap.getPixels(); memcpy(dst_pixels, src_pixels, skbitmap.computeByteSize()); return skbitmap; } SkColorType ConvertToSkiaColorType(const JavaRef& bitmap_config) { int jbitmap_config = Java_BitmapHelper_getBitmapFormatForConfig( AttachCurrentThread(), bitmap_config); switch (jbitmap_config) { case BITMAP_FORMAT_ALPHA_8: return kAlpha_8_SkColorType; case BITMAP_FORMAT_ARGB_4444: return kARGB_4444_SkColorType; case BITMAP_FORMAT_ARGB_8888: return kN32_SkColorType; case BITMAP_FORMAT_RGB_565: return kRGB_565_SkColorType; case BITMAP_FORMAT_NO_CONFIG: default: return kUnknown_SkColorType; } } } // namespace gfx