text: // 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 <android/bitmap.h>
  
  #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<jobject>& 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<jobject> 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<jobject> 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<jobject> jbitmap = CreateJavaBitmap(
        skbitmap->width(), skbitmap->height(), color_type);
    SkAutoLockPixels src_lock(*skbitmap);
    JavaBitmap dst_lock(jbitmap);
    void* src_pixels = skbitmap->getPixels();
    void* dst_pixels = dst_lock.pixels();
    memcpy(dst_pixels, src_pixels, skbitmap->getSize());
  
    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<int>(skbitmap.getSize()));
    const void* src_pixels = jbitmap.pixels();
    void* dst_pixels = skbitmap.getPixels();
    memcpy(dst_pixels, src_pixels, skbitmap.getSize());
  
    return skbitmap;
  }
  
  SkColorType ConvertToSkiaColorType(const JavaRef<jobject>& 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
  