PageRenderTime 65ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/core/jni/android/graphics/Bitmap.cpp

https://bitbucket.org/codefirex/frameworks_base
C++ | 712 lines | 575 code | 113 blank | 24 comment | 116 complexity | 95c7d19534d5f54859173b9f2f86c8f5 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, CC0-1.0
  1. #include "SkBitmap.h"
  2. #include "SkPixelRef.h"
  3. #include "SkImageEncoder.h"
  4. #include "SkColorPriv.h"
  5. #include "GraphicsJNI.h"
  6. #include "SkDither.h"
  7. #include "SkUnPreMultiply.h"
  8. #include <binder/Parcel.h>
  9. #include "android_os_Parcel.h"
  10. #include "android_util_Binder.h"
  11. #include "android_nio_utils.h"
  12. #include "CreateJavaOutputStreamAdaptor.h"
  13. #include <jni.h>
  14. #include <Caches.h>
  15. #if 0
  16. #define TRACE_BITMAP(code) code
  17. #else
  18. #define TRACE_BITMAP(code)
  19. #endif
  20. #ifdef USE_NEON_BITMAP_OPTS
  21. #define __BITMAP_OPTS __attribute__((optimize("-ftree-vectorize", "-fprefetch-loop-arrays")))
  22. #else
  23. #define __BITMAP_OPTS
  24. #endif
  25. ///////////////////////////////////////////////////////////////////////////////
  26. // Conversions to/from SkColor, for get/setPixels, and the create method, which
  27. // is basically like setPixels
  28. typedef void (*FromColorProc)(void* dst, const SkColor src[], int width,
  29. int x, int y);
  30. static void __BITMAP_OPTS FromColor_D32(void* dst, const SkColor src[], int width,
  31. int, int) {
  32. SkPMColor* d = (SkPMColor*)dst;
  33. for (int i = 0; i < width; i++) {
  34. *d++ = SkPreMultiplyColor(*src++);
  35. }
  36. }
  37. static void __BITMAP_OPTS FromColor_D565(void* dst, const SkColor src[], int width,
  38. int x, int y) {
  39. uint16_t* d = (uint16_t*)dst;
  40. DITHER_565_SCAN(y);
  41. for (int stop = x + width; x < stop; x++) {
  42. SkColor c = *src++;
  43. *d++ = SkDitherRGBTo565(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c),
  44. DITHER_VALUE(x));
  45. }
  46. }
  47. static void __BITMAP_OPTS FromColor_D4444(void* dst, const SkColor src[], int width,
  48. int x, int y) {
  49. SkPMColor16* d = (SkPMColor16*)dst;
  50. DITHER_4444_SCAN(y);
  51. for (int stop = x + width; x < stop; x++) {
  52. SkPMColor c = SkPreMultiplyColor(*src++);
  53. *d++ = SkDitherARGB32To4444(c, DITHER_VALUE(x));
  54. // *d++ = SkPixel32ToPixel4444(c);
  55. }
  56. }
  57. // can return NULL
  58. static FromColorProc ChooseFromColorProc(SkBitmap::Config config) {
  59. switch (config) {
  60. case SkBitmap::kARGB_8888_Config:
  61. return FromColor_D32;
  62. case SkBitmap::kARGB_4444_Config:
  63. return FromColor_D4444;
  64. case SkBitmap::kRGB_565_Config:
  65. return FromColor_D565;
  66. default:
  67. break;
  68. }
  69. return NULL;
  70. }
  71. bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors,
  72. int srcOffset, int srcStride,
  73. int x, int y, int width, int height,
  74. const SkBitmap& dstBitmap) {
  75. SkAutoLockPixels alp(dstBitmap);
  76. void* dst = dstBitmap.getPixels();
  77. FromColorProc proc = ChooseFromColorProc(dstBitmap.config());
  78. if (NULL == dst || NULL == proc) {
  79. return false;
  80. }
  81. const jint* array = env->GetIntArrayElements(srcColors, NULL);
  82. const SkColor* src = (const SkColor*)array + srcOffset;
  83. // reset to to actual choice from caller
  84. dst = dstBitmap.getAddr(x, y);
  85. // now copy/convert each scanline
  86. for (int y = 0; y < height; y++) {
  87. proc(dst, src, width, x, y);
  88. src += srcStride;
  89. dst = (char*)dst + dstBitmap.rowBytes();
  90. }
  91. dstBitmap.notifyPixelsChanged();
  92. env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array),
  93. JNI_ABORT);
  94. return true;
  95. }
  96. //////////////////// ToColor procs
  97. typedef void (*ToColorProc)(SkColor dst[], const void* src, int width,
  98. SkColorTable*);
  99. static void __BITMAP_OPTS ToColor_S32_Alpha(SkColor dst[], const void* src, int width,
  100. SkColorTable*) {
  101. SkASSERT(width > 0);
  102. const SkPMColor* s = (const SkPMColor*)src;
  103. do {
  104. *dst++ = SkUnPreMultiply::PMColorToColor(*s++);
  105. } while (--width != 0);
  106. }
  107. static void __BITMAP_OPTS ToColor_S32_Opaque(SkColor dst[], const void* src, int width,
  108. SkColorTable*) {
  109. SkASSERT(width > 0);
  110. const SkPMColor* s = (const SkPMColor*)src;
  111. do {
  112. SkPMColor c = *s++;
  113. *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
  114. SkGetPackedB32(c));
  115. } while (--width != 0);
  116. }
  117. static void __BITMAP_OPTS ToColor_S4444_Alpha(SkColor dst[], const void* src, int width,
  118. SkColorTable*) {
  119. SkASSERT(width > 0);
  120. const SkPMColor16* s = (const SkPMColor16*)src;
  121. do {
  122. *dst++ = SkUnPreMultiply::PMColorToColor(SkPixel4444ToPixel32(*s++));
  123. } while (--width != 0);
  124. }
  125. static void __BITMAP_OPTS ToColor_S4444_Opaque(SkColor dst[], const void* src, int width,
  126. SkColorTable*) {
  127. SkASSERT(width > 0);
  128. const SkPMColor16* s = (const SkPMColor16*)src;
  129. do {
  130. SkPMColor c = SkPixel4444ToPixel32(*s++);
  131. *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
  132. SkGetPackedB32(c));
  133. } while (--width != 0);
  134. }
  135. static void __BITMAP_OPTS ToColor_S565(SkColor dst[], const void* src, int width,
  136. SkColorTable*) {
  137. SkASSERT(width > 0);
  138. const uint16_t* s = (const uint16_t*)src;
  139. do {
  140. uint16_t c = *s++;
  141. *dst++ = SkColorSetRGB(SkPacked16ToR32(c), SkPacked16ToG32(c),
  142. SkPacked16ToB32(c));
  143. } while (--width != 0);
  144. }
  145. static void __BITMAP_OPTS ToColor_SI8_Alpha(SkColor dst[], const void* src, int width,
  146. SkColorTable* ctable) {
  147. SkASSERT(width > 0);
  148. const uint8_t* s = (const uint8_t*)src;
  149. const SkPMColor* colors = ctable->lockColors();
  150. do {
  151. *dst++ = SkUnPreMultiply::PMColorToColor(colors[*s++]);
  152. } while (--width != 0);
  153. ctable->unlockColors(false);
  154. }
  155. static void __BITMAP_OPTS ToColor_SI8_Opaque(SkColor dst[], const void* src, int width,
  156. SkColorTable* ctable) {
  157. SkASSERT(width > 0);
  158. const uint8_t* s = (const uint8_t*)src;
  159. const SkPMColor* colors = ctable->lockColors();
  160. do {
  161. SkPMColor c = colors[*s++];
  162. *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
  163. SkGetPackedB32(c));
  164. } while (--width != 0);
  165. ctable->unlockColors(false);
  166. }
  167. // can return NULL
  168. static ToColorProc ChooseToColorProc(const SkBitmap& src) {
  169. switch (src.config()) {
  170. case SkBitmap::kARGB_8888_Config:
  171. return src.isOpaque() ? ToColor_S32_Opaque : ToColor_S32_Alpha;
  172. case SkBitmap::kARGB_4444_Config:
  173. return src.isOpaque() ? ToColor_S4444_Opaque : ToColor_S4444_Alpha;
  174. case SkBitmap::kRGB_565_Config:
  175. return ToColor_S565;
  176. case SkBitmap::kIndex8_Config:
  177. if (src.getColorTable() == NULL) {
  178. return NULL;
  179. }
  180. return src.isOpaque() ? ToColor_SI8_Opaque : ToColor_SI8_Alpha;
  181. default:
  182. break;
  183. }
  184. return NULL;
  185. }
  186. ///////////////////////////////////////////////////////////////////////////////
  187. ///////////////////////////////////////////////////////////////////////////////
  188. static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
  189. int offset, int stride, int width, int height,
  190. SkBitmap::Config config, jboolean isMutable) {
  191. if (NULL != jColors) {
  192. size_t n = env->GetArrayLength(jColors);
  193. if (n < SkAbs32(stride) * (size_t)height) {
  194. doThrowAIOOBE(env);
  195. return NULL;
  196. }
  197. }
  198. SkBitmap bitmap;
  199. bitmap.setConfig(config, width, height);
  200. jbyteArray buff = GraphicsJNI::allocateJavaPixelRef(env, &bitmap, NULL);
  201. if (NULL == buff) {
  202. return NULL;
  203. }
  204. if (jColors != NULL) {
  205. GraphicsJNI::SetPixels(env, jColors, offset, stride,
  206. 0, 0, width, height, bitmap);
  207. }
  208. return GraphicsJNI::createBitmap(env, new SkBitmap(bitmap), buff, isMutable, NULL, NULL);
  209. }
  210. static jobject Bitmap_copy(JNIEnv* env, jobject, const SkBitmap* src,
  211. SkBitmap::Config dstConfig, jboolean isMutable) {
  212. SkBitmap result;
  213. JavaPixelAllocator allocator(env);
  214. if (!src->copyTo(&result, dstConfig, &allocator)) {
  215. return NULL;
  216. }
  217. return GraphicsJNI::createBitmap(env, new SkBitmap(result), allocator.getStorageObj(), isMutable, NULL, NULL);
  218. }
  219. static void Bitmap_destructor(JNIEnv* env, jobject, SkBitmap* bitmap) {
  220. #ifdef USE_OPENGL_RENDERER
  221. if (android::uirenderer::Caches::hasInstance()) {
  222. android::uirenderer::Caches::getInstance().resourceCache.destructor(bitmap);
  223. return;
  224. }
  225. #endif // USE_OPENGL_RENDERER
  226. delete bitmap;
  227. }
  228. static jboolean Bitmap_recycle(JNIEnv* env, jobject, SkBitmap* bitmap) {
  229. #ifdef USE_OPENGL_RENDERER
  230. if (android::uirenderer::Caches::hasInstance()) {
  231. return android::uirenderer::Caches::getInstance().resourceCache.recycle(bitmap);
  232. }
  233. #endif // USE_OPENGL_RENDERER
  234. bitmap->setPixels(NULL, NULL);
  235. return true;
  236. }
  237. // These must match the int values in Bitmap.java
  238. enum JavaEncodeFormat {
  239. kJPEG_JavaEncodeFormat = 0,
  240. kPNG_JavaEncodeFormat = 1,
  241. kWEBP_JavaEncodeFormat = 2
  242. };
  243. static bool Bitmap_compress(JNIEnv* env, jobject clazz, SkBitmap* bitmap,
  244. int format, int quality,
  245. jobject jstream, jbyteArray jstorage) {
  246. SkImageEncoder::Type fm;
  247. switch (format) {
  248. case kJPEG_JavaEncodeFormat:
  249. fm = SkImageEncoder::kJPEG_Type;
  250. break;
  251. case kPNG_JavaEncodeFormat:
  252. fm = SkImageEncoder::kPNG_Type;
  253. break;
  254. case kWEBP_JavaEncodeFormat:
  255. fm = SkImageEncoder::kWEBP_Type;
  256. break;
  257. default:
  258. return false;
  259. }
  260. bool success = false;
  261. if (NULL != bitmap) {
  262. SkAutoLockPixels alp(*bitmap);
  263. if (NULL == bitmap->getPixels()) {
  264. return false;
  265. }
  266. SkWStream* strm = CreateJavaOutputStreamAdaptor(env, jstream, jstorage);
  267. if (NULL == strm) {
  268. return false;
  269. }
  270. SkImageEncoder* encoder = SkImageEncoder::Create(fm);
  271. if (NULL != encoder) {
  272. success = encoder->encodeStream(strm, *bitmap, quality);
  273. delete encoder;
  274. }
  275. delete strm;
  276. }
  277. return success;
  278. }
  279. static void Bitmap_erase(JNIEnv* env, jobject, SkBitmap* bitmap, jint color) {
  280. bitmap->eraseColor(color);
  281. }
  282. static int Bitmap_width(JNIEnv* env, jobject, SkBitmap* bitmap) {
  283. return bitmap->width();
  284. }
  285. static int Bitmap_height(JNIEnv* env, jobject, SkBitmap* bitmap) {
  286. return bitmap->height();
  287. }
  288. static int Bitmap_rowBytes(JNIEnv* env, jobject, SkBitmap* bitmap) {
  289. return bitmap->rowBytes();
  290. }
  291. static int Bitmap_config(JNIEnv* env, jobject, SkBitmap* bitmap) {
  292. return bitmap->config();
  293. }
  294. static int Bitmap_getGenerationId(JNIEnv* env, jobject, SkBitmap* bitmap) {
  295. return bitmap->getGenerationID();
  296. }
  297. static jboolean Bitmap_hasAlpha(JNIEnv* env, jobject, SkBitmap* bitmap) {
  298. return !bitmap->isOpaque();
  299. }
  300. static void Bitmap_setHasAlpha(JNIEnv* env, jobject, SkBitmap* bitmap,
  301. jboolean hasAlpha) {
  302. bitmap->setIsOpaque(!hasAlpha);
  303. }
  304. static jboolean Bitmap_hasMipMap(JNIEnv* env, jobject, SkBitmap* bitmap) {
  305. return bitmap->hasHardwareMipMap();
  306. }
  307. static void Bitmap_setHasMipMap(JNIEnv* env, jobject, SkBitmap* bitmap,
  308. jboolean hasMipMap) {
  309. bitmap->setHasHardwareMipMap(hasMipMap);
  310. }
  311. ///////////////////////////////////////////////////////////////////////////////
  312. static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
  313. if (parcel == NULL) {
  314. SkDebugf("-------- unparcel parcel is NULL\n");
  315. return NULL;
  316. }
  317. android::Parcel* p = android::parcelForJavaObject(env, parcel);
  318. const bool isMutable = p->readInt32() != 0;
  319. const SkBitmap::Config config = (SkBitmap::Config)p->readInt32();
  320. const int width = p->readInt32();
  321. const int height = p->readInt32();
  322. const int rowBytes = p->readInt32();
  323. const int density = p->readInt32();
  324. if (SkBitmap::kARGB_8888_Config != config &&
  325. SkBitmap::kRGB_565_Config != config &&
  326. SkBitmap::kARGB_4444_Config != config &&
  327. SkBitmap::kIndex8_Config != config &&
  328. SkBitmap::kA8_Config != config) {
  329. SkDebugf("Bitmap_createFromParcel unknown config: %d\n", config);
  330. return NULL;
  331. }
  332. SkBitmap* bitmap = new SkBitmap;
  333. bitmap->setConfig(config, width, height, rowBytes);
  334. SkColorTable* ctable = NULL;
  335. if (config == SkBitmap::kIndex8_Config) {
  336. int count = p->readInt32();
  337. if (count > 0) {
  338. size_t size = count * sizeof(SkPMColor);
  339. const SkPMColor* src = (const SkPMColor*)p->readInplace(size);
  340. ctable = new SkColorTable(src, count);
  341. }
  342. }
  343. jbyteArray buffer = GraphicsJNI::allocateJavaPixelRef(env, bitmap, ctable);
  344. if (NULL == buffer) {
  345. SkSafeUnref(ctable);
  346. delete bitmap;
  347. return NULL;
  348. }
  349. SkSafeUnref(ctable);
  350. size_t size = bitmap->getSize();
  351. android::Parcel::ReadableBlob blob;
  352. android::status_t status = p->readBlob(size, &blob);
  353. if (status) {
  354. doThrowRE(env, "Could not read bitmap from parcel blob.");
  355. delete bitmap;
  356. return NULL;
  357. }
  358. bitmap->lockPixels();
  359. memcpy(bitmap->getPixels(), blob.data(), size);
  360. bitmap->unlockPixels();
  361. blob.release();
  362. return GraphicsJNI::createBitmap(env, bitmap, buffer, isMutable, NULL, NULL, density);
  363. }
  364. static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
  365. const SkBitmap* bitmap,
  366. jboolean isMutable, jint density,
  367. jobject parcel) {
  368. if (parcel == NULL) {
  369. SkDebugf("------- writeToParcel null parcel\n");
  370. return false;
  371. }
  372. android::Parcel* p = android::parcelForJavaObject(env, parcel);
  373. p->writeInt32(isMutable);
  374. p->writeInt32(bitmap->config());
  375. p->writeInt32(bitmap->width());
  376. p->writeInt32(bitmap->height());
  377. p->writeInt32(bitmap->rowBytes());
  378. p->writeInt32(density);
  379. if (bitmap->getConfig() == SkBitmap::kIndex8_Config) {
  380. SkColorTable* ctable = bitmap->getColorTable();
  381. if (ctable != NULL) {
  382. int count = ctable->count();
  383. p->writeInt32(count);
  384. memcpy(p->writeInplace(count * sizeof(SkPMColor)),
  385. ctable->lockColors(), count * sizeof(SkPMColor));
  386. ctable->unlockColors(false);
  387. } else {
  388. p->writeInt32(0); // indicate no ctable
  389. }
  390. }
  391. size_t size = bitmap->getSize();
  392. android::Parcel::WritableBlob blob;
  393. android::status_t status = p->writeBlob(size, &blob);
  394. if (status) {
  395. doThrowRE(env, "Could not write bitmap to parcel blob.");
  396. return false;
  397. }
  398. bitmap->lockPixels();
  399. const void* pSrc = bitmap->getPixels();
  400. if (pSrc == NULL) {
  401. memset(blob.data(), 0, size);
  402. } else {
  403. memcpy(blob.data(), pSrc, size);
  404. }
  405. bitmap->unlockPixels();
  406. blob.release();
  407. return true;
  408. }
  409. static jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,
  410. const SkBitmap* src, const SkPaint* paint,
  411. jintArray offsetXY) {
  412. SkIPoint offset;
  413. SkBitmap* dst = new SkBitmap;
  414. JavaPixelAllocator allocator(env);
  415. src->extractAlpha(dst, paint, &allocator, &offset);
  416. // If Skia can't allocate pixels for destination bitmap, it resets
  417. // it, that is set its pixels buffer to NULL, and zero width and height.
  418. if (dst->getPixels() == NULL && src->getPixels() != NULL) {
  419. delete dst;
  420. doThrowOOME(env, "failed to allocate pixels for alpha");
  421. return NULL;
  422. }
  423. if (offsetXY != 0 && env->GetArrayLength(offsetXY) >= 2) {
  424. int* array = env->GetIntArrayElements(offsetXY, NULL);
  425. array[0] = offset.fX;
  426. array[1] = offset.fY;
  427. env->ReleaseIntArrayElements(offsetXY, array, 0);
  428. }
  429. return GraphicsJNI::createBitmap(env, dst, allocator.getStorageObj(), true, NULL, NULL);
  430. }
  431. ///////////////////////////////////////////////////////////////////////////////
  432. static int Bitmap_getPixel(JNIEnv* env, jobject, const SkBitmap* bitmap,
  433. int x, int y) {
  434. SkAutoLockPixels alp(*bitmap);
  435. ToColorProc proc = ChooseToColorProc(*bitmap);
  436. if (NULL == proc) {
  437. return 0;
  438. }
  439. const void* src = bitmap->getAddr(x, y);
  440. if (NULL == src) {
  441. return 0;
  442. }
  443. SkColor dst[1];
  444. proc(dst, src, 1, bitmap->getColorTable());
  445. return dst[0];
  446. }
  447. static void Bitmap_getPixels(JNIEnv* env, jobject, const SkBitmap* bitmap,
  448. jintArray pixelArray, int offset, int stride,
  449. int x, int y, int width, int height) {
  450. SkAutoLockPixels alp(*bitmap);
  451. ToColorProc proc = ChooseToColorProc(*bitmap);
  452. if (NULL == proc) {
  453. return;
  454. }
  455. const void* src = bitmap->getAddr(x, y);
  456. if (NULL == src) {
  457. return;
  458. }
  459. SkColorTable* ctable = bitmap->getColorTable();
  460. jint* dst = env->GetIntArrayElements(pixelArray, NULL);
  461. SkColor* d = (SkColor*)dst + offset;
  462. while (--height >= 0) {
  463. proc(d, src, width, ctable);
  464. d += stride;
  465. src = (void*)((const char*)src + bitmap->rowBytes());
  466. }
  467. env->ReleaseIntArrayElements(pixelArray, dst, 0);
  468. }
  469. ///////////////////////////////////////////////////////////////////////////////
  470. static void Bitmap_setPixel(JNIEnv* env, jobject, const SkBitmap* bitmap,
  471. int x, int y, SkColor color) {
  472. SkAutoLockPixels alp(*bitmap);
  473. if (NULL == bitmap->getPixels()) {
  474. return;
  475. }
  476. FromColorProc proc = ChooseFromColorProc(bitmap->config());
  477. if (NULL == proc) {
  478. return;
  479. }
  480. proc(bitmap->getAddr(x, y), &color, 1, x, y);
  481. bitmap->notifyPixelsChanged();
  482. }
  483. static void Bitmap_setPixels(JNIEnv* env, jobject, const SkBitmap* bitmap,
  484. jintArray pixelArray, int offset, int stride,
  485. int x, int y, int width, int height) {
  486. GraphicsJNI::SetPixels(env, pixelArray, offset, stride,
  487. x, y, width, height, *bitmap);
  488. }
  489. static void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,
  490. const SkBitmap* bitmap, jobject jbuffer) {
  491. SkAutoLockPixels alp(*bitmap);
  492. const void* src = bitmap->getPixels();
  493. if (NULL != src) {
  494. android::AutoBufferPointer abp(env, jbuffer, JNI_TRUE);
  495. // the java side has already checked that buffer is large enough
  496. memcpy(abp.pointer(), src, bitmap->getSize());
  497. }
  498. }
  499. static void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject,
  500. const SkBitmap* bitmap, jobject jbuffer) {
  501. SkAutoLockPixels alp(*bitmap);
  502. void* dst = bitmap->getPixels();
  503. if (NULL != dst) {
  504. android::AutoBufferPointer abp(env, jbuffer, JNI_FALSE);
  505. // the java side has already checked that buffer is large enough
  506. memcpy(dst, abp.pointer(), bitmap->getSize());
  507. bitmap->notifyPixelsChanged();
  508. }
  509. }
  510. static bool Bitmap_sameAs(JNIEnv* env, jobject, const SkBitmap* bm0,
  511. const SkBitmap* bm1) {
  512. if (bm0->width() != bm1->width() ||
  513. bm0->height() != bm1->height() ||
  514. bm0->config() != bm1->config()) {
  515. return false;
  516. }
  517. SkAutoLockPixels alp0(*bm0);
  518. SkAutoLockPixels alp1(*bm1);
  519. // if we can't load the pixels, return false
  520. if (NULL == bm0->getPixels() || NULL == bm1->getPixels()) {
  521. return false;
  522. }
  523. if (bm0->config() == SkBitmap::kIndex8_Config) {
  524. SkColorTable* ct0 = bm0->getColorTable();
  525. SkColorTable* ct1 = bm1->getColorTable();
  526. if (NULL == ct0 || NULL == ct1) {
  527. return false;
  528. }
  529. if (ct0->count() != ct1->count()) {
  530. return false;
  531. }
  532. SkAutoLockColors alc0(ct0);
  533. SkAutoLockColors alc1(ct1);
  534. const size_t size = ct0->count() * sizeof(SkPMColor);
  535. if (memcmp(alc0.colors(), alc1.colors(), size) != 0) {
  536. return false;
  537. }
  538. }
  539. // now compare each scanline. We can't do the entire buffer at once,
  540. // since we don't care about the pixel values that might extend beyond
  541. // the width (since the scanline might be larger than the logical width)
  542. const int h = bm0->height();
  543. const size_t size = bm0->width() * bm0->bytesPerPixel();
  544. for (int y = 0; y < h; y++) {
  545. if (memcmp(bm0->getAddr(0, y), bm1->getAddr(0, y), size) != 0) {
  546. return false;
  547. }
  548. }
  549. return true;
  550. }
  551. static void Bitmap_prepareToDraw(JNIEnv* env, jobject, SkBitmap* bitmap) {
  552. bitmap->lockPixels();
  553. bitmap->unlockPixels();
  554. }
  555. ///////////////////////////////////////////////////////////////////////////////
  556. #include <android_runtime/AndroidRuntime.h>
  557. static JNINativeMethod gBitmapMethods[] = {
  558. { "nativeCreate", "([IIIIIIZ)Landroid/graphics/Bitmap;",
  559. (void*)Bitmap_creator },
  560. { "nativeCopy", "(IIZ)Landroid/graphics/Bitmap;",
  561. (void*)Bitmap_copy },
  562. { "nativeDestructor", "(I)V", (void*)Bitmap_destructor },
  563. { "nativeRecycle", "(I)Z", (void*)Bitmap_recycle },
  564. { "nativeCompress", "(IIILjava/io/OutputStream;[B)Z",
  565. (void*)Bitmap_compress },
  566. { "nativeErase", "(II)V", (void*)Bitmap_erase },
  567. { "nativeWidth", "(I)I", (void*)Bitmap_width },
  568. { "nativeHeight", "(I)I", (void*)Bitmap_height },
  569. { "nativeRowBytes", "(I)I", (void*)Bitmap_rowBytes },
  570. { "nativeConfig", "(I)I", (void*)Bitmap_config },
  571. { "nativeHasAlpha", "(I)Z", (void*)Bitmap_hasAlpha },
  572. { "nativeSetHasAlpha", "(IZ)V", (void*)Bitmap_setHasAlpha },
  573. { "nativeHasMipMap", "(I)Z", (void*)Bitmap_hasMipMap },
  574. { "nativeSetHasMipMap", "(IZ)V", (void*)Bitmap_setHasMipMap },
  575. { "nativeCreateFromParcel",
  576. "(Landroid/os/Parcel;)Landroid/graphics/Bitmap;",
  577. (void*)Bitmap_createFromParcel },
  578. { "nativeWriteToParcel", "(IZILandroid/os/Parcel;)Z",
  579. (void*)Bitmap_writeToParcel },
  580. { "nativeExtractAlpha", "(II[I)Landroid/graphics/Bitmap;",
  581. (void*)Bitmap_extractAlpha },
  582. { "nativeGenerationId", "(I)I", (void*)Bitmap_getGenerationId },
  583. { "nativeGetPixel", "(III)I", (void*)Bitmap_getPixel },
  584. { "nativeGetPixels", "(I[IIIIIII)V", (void*)Bitmap_getPixels },
  585. { "nativeSetPixel", "(IIII)V", (void*)Bitmap_setPixel },
  586. { "nativeSetPixels", "(I[IIIIIII)V", (void*)Bitmap_setPixels },
  587. { "nativeCopyPixelsToBuffer", "(ILjava/nio/Buffer;)V",
  588. (void*)Bitmap_copyPixelsToBuffer },
  589. { "nativeCopyPixelsFromBuffer", "(ILjava/nio/Buffer;)V",
  590. (void*)Bitmap_copyPixelsFromBuffer },
  591. { "nativeSameAs", "(II)Z", (void*)Bitmap_sameAs },
  592. { "nativePrepareToDraw", "(I)V", (void*)Bitmap_prepareToDraw },
  593. };
  594. #define kClassPathName "android/graphics/Bitmap"
  595. int register_android_graphics_Bitmap(JNIEnv* env)
  596. {
  597. return android::AndroidRuntime::registerNativeMethods(env, kClassPathName,
  598. gBitmapMethods, SK_ARRAY_COUNT(gBitmapMethods));
  599. }