PageRenderTime 73ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

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

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