summaryrefslogtreecommitdiffstats
path: root/core/jni
diff options
context:
space:
mode:
Diffstat (limited to 'core/jni')
-rw-r--r--core/jni/Android.mk4
-rw-r--r--core/jni/AndroidRuntime.cpp93
-rw-r--r--core/jni/android/graphics/Bitmap.cpp94
-rw-r--r--core/jni/android/graphics/BitmapFactory.cpp142
-rw-r--r--core/jni/android/graphics/Camera.cpp4
-rw-r--r--core/jni/android/graphics/Canvas.cpp841
-rw-r--r--core/jni/android/graphics/DrawFilter.cpp52
-rw-r--r--core/jni/android/graphics/Graphics.cpp15
-rw-r--r--core/jni/android/graphics/GraphicsJNI.h3
-rw-r--r--core/jni/android/graphics/MaskFilter.cpp3
-rw-r--r--core/jni/android/graphics/MinikinUtils.cpp17
-rw-r--r--core/jni/android/graphics/MinikinUtils.h1
-rw-r--r--core/jni/android/graphics/NinePatch.cpp4
-rw-r--r--core/jni/android/graphics/Paint.cpp107
-rw-r--r--core/jni/android/graphics/Path.cpp99
-rw-r--r--core/jni/android/graphics/Picture.cpp169
-rw-r--r--core/jni/android/graphics/Picture.h67
-rw-r--r--core/jni/android/graphics/pdf/PdfDocument.cpp29
-rw-r--r--core/jni/android_graphics_Picture.cpp117
-rw-r--r--core/jni/android_hardware_Camera.cpp24
-rw-r--r--core/jni/android_hardware_SensorManager.cpp26
-rw-r--r--core/jni/android_hardware_SoundTrigger.cpp661
-rw-r--r--core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp78
-rw-r--r--core/jni/android_media_AudioFormat.h22
-rw-r--r--core/jni/android_media_AudioSystem.cpp9
-rw-r--r--core/jni/android_media_AudioTrack.cpp27
-rw-r--r--core/jni/android_os_Debug.cpp16
-rw-r--r--core/jni/android_server_FingerprintManager.cpp185
-rw-r--r--core/jni/android_util_Process.cpp10
-rw-r--r--core/jni/android_view_GLES20Canvas.cpp416
-rw-r--r--core/jni/android_view_GLRenderer.cpp203
-rw-r--r--core/jni/android_view_GraphicBuffer.cpp29
-rw-r--r--core/jni/android_view_HardwareLayer.cpp35
-rw-r--r--core/jni/android_view_RenderNode.cpp264
-rw-r--r--core/jni/android_view_Surface.cpp37
-rw-r--r--core/jni/android_view_SurfaceControl.cpp95
-rw-r--r--core/jni/android_view_TextureView.cpp43
-rw-r--r--core/jni/android_view_ThreadedRenderer.cpp124
-rw-r--r--core/jni/com_android_internal_content_NativeLibraryHelper.cpp41
-rw-r--r--core/jni/com_android_internal_os_Zygote.cpp137
40 files changed, 2654 insertions, 1689 deletions
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index f446c3a..cb00062 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -57,7 +57,6 @@ LOCAL_SRC_FILES:= \
android_view_KeyEvent.cpp \
android_view_KeyCharacterMap.cpp \
android_view_GraphicBuffer.cpp \
- android_view_GLRenderer.cpp \
android_view_GLES20Canvas.cpp \
android_view_HardwareLayer.cpp \
android_view_ThreadedRenderer.cpp \
@@ -90,6 +89,7 @@ LOCAL_SRC_FILES:= \
android_util_Process.cpp \
android_util_StringBlock.cpp \
android_util_XmlBlock.cpp \
+ android_graphics_Picture.cpp \
android/graphics/AutoDecodeCancel.cpp \
android/graphics/Bitmap.cpp \
android/graphics/BitmapFactory.cpp \
@@ -141,6 +141,7 @@ LOCAL_SRC_FILES:= \
android_hardware_camera2_DngCreator.cpp \
android_hardware_SensorManager.cpp \
android_hardware_SerialPort.cpp \
+ android_hardware_SoundTrigger.cpp \
android_hardware_UsbDevice.cpp \
android_hardware_UsbDeviceConnection.cpp \
android_hardware_UsbRequest.cpp \
@@ -236,6 +237,7 @@ LOCAL_SHARED_LIBRARIES := \
libpdfium \
libimg_utils \
libnetd_client \
+ libsoundtrigger
ifeq ($(USE_OPENGL_RENDERER),true)
LOCAL_SHARED_LIBRARIES += libhwui
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index e069876..598d6c1 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -29,7 +29,6 @@
#include <SkGraphics.h>
#include <SkImageDecoder.h>
-#include <SkImageRef_GlobalPool.h>
#include "jni.h"
#include "JNIHelp.h"
@@ -83,6 +82,7 @@ extern int register_android_hardware_camera2_legacy_LegacyCameraDevice(JNIEnv *e
extern int register_android_hardware_camera2_DngCreator(JNIEnv *env);
extern int register_android_hardware_SensorManager(JNIEnv *env);
extern int register_android_hardware_SerialPort(JNIEnv *env);
+extern int register_android_hardware_SoundTrigger(JNIEnv *env);
extern int register_android_hardware_UsbDevice(JNIEnv *env);
extern int register_android_hardware_UsbDeviceConnection(JNIEnv *env);
extern int register_android_hardware_UsbRequest(JNIEnv *env);
@@ -130,7 +130,6 @@ extern int register_android_view_RenderNode(JNIEnv* env);
extern int register_android_view_RenderNodeAnimator(JNIEnv* env);
extern int register_android_view_GraphicBuffer(JNIEnv* env);
extern int register_android_view_GLES20Canvas(JNIEnv* env);
-extern int register_android_view_GLRenderer(JNIEnv* env);
extern int register_android_view_HardwareLayer(JNIEnv* env);
extern int register_android_view_ThreadedRenderer(JNIEnv* env);
extern int register_android_view_Surface(JNIEnv* env);
@@ -160,6 +159,7 @@ extern int register_android_net_TrafficStats(JNIEnv* env);
extern int register_android_text_AndroidCharacter(JNIEnv *env);
extern int register_android_text_AndroidBidi(JNIEnv *env);
extern int register_android_opengl_classes(JNIEnv *env);
+extern int register_android_server_fingerprint_FingerprintService(JNIEnv* env);
extern int register_android_server_NetworkManagementSocketTagger(JNIEnv* env);
extern int register_android_server_Watchdog(JNIEnv* env);
extern int register_android_ddm_DdmHandleNativeHeap(JNIEnv *env);
@@ -245,14 +245,6 @@ AndroidRuntime::AndroidRuntime(char* argBlockStart, const size_t argBlockLength)
mArgBlockLength(argBlockLength)
{
SkGraphics::Init();
- // this sets our preference for 16bit images during decode
- // in case the src is opaque and 24bit
- SkImageDecoder::SetDeviceConfig(SkBitmap::kRGB_565_Config);
- // This cache is shared between browser native images, and java "purgeable"
- // bitmaps. This globalpool is for images that do not either use the java
- // heap, or are not backed by ashmem. See BitmapFactory.cpp for the key
- // java call site.
- SkImageRef_GlobalPool::SetRAMBudget(512 * 1024);
// There is also a global font cache, but its budget is specified in code
// see SkFontHost_android.cpp
@@ -499,6 +491,8 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
char profile_duration[sizeof("-Xprofile-duration:") + PROPERTY_VALUE_MAX];
char profile_interval[sizeof("-Xprofile-interval:") + PROPERTY_VALUE_MAX];
char profile_backoff[sizeof("-Xprofile-backoff:") + PROPERTY_VALUE_MAX];
+ char profile_top_k_threshold[sizeof("-Xprofile-top-k-threshold:") + PROPERTY_VALUE_MAX];
+ char profile_top_k_change_threshold[sizeof("-Xprofile-top-k-change-threshold:") + PROPERTY_VALUE_MAX];
char langOption[sizeof("-Duser.language=") + 3];
char regionOption[sizeof("-Duser.region=") + 3];
char lockProfThresholdBuf[sizeof("-Xlockprofthreshold:") + sizeof(propBuf)];
@@ -822,31 +816,65 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
* Set profiler options
*/
if (libart) {
- // Number of seconds during profile runs.
- strcpy(profile_period, "-Xprofile-period:");
- property_get("dalvik.vm.profile.period_secs", profile_period+17, "10");
- opt.optionString = profile_period;
- mOptions.add(opt);
+ // Whether or not the profiler should be enabled.
+ property_get("dalvik.vm.profiler", propBuf, "0");
+ if (propBuf[0] == '1') {
+ opt.optionString = "-Xenable-profiler";
+ mOptions.add(opt);
+ }
- // Length of each profile run (seconds).
- strcpy(profile_duration, "-Xprofile-duration:");
- property_get("dalvik.vm.profile.duration_secs", profile_duration+19, "30");
- opt.optionString = profile_duration;
- mOptions.add(opt);
+ // Whether the profile should start upon app startup or be delayed by some random offset
+ // (in seconds) that is bound between 0 and a fixed value.
+ property_get("dalvik.vm.profile.start-immed", propBuf, "0");
+ if (propBuf[0] == '1') {
+ opt.optionString = "-Xprofile-start-immediately";
+ mOptions.add(opt);
+ }
+ // Number of seconds during profile runs.
+ strcpy(profile_period, "-Xprofile-period:");
+ if (property_get("dalvik.vm.profile.period-secs", profile_period+17, NULL) > 0) {
+ opt.optionString = profile_period;
+ mOptions.add(opt);
+ }
- // Polling interval during profile run (microseconds).
- strcpy(profile_interval, "-Xprofile-interval:");
- property_get("dalvik.vm.profile.interval_us", profile_interval+19, "10000");
- opt.optionString = profile_interval;
- mOptions.add(opt);
+ // Length of each profile run (seconds).
+ strcpy(profile_duration, "-Xprofile-duration:");
+ if (property_get("dalvik.vm.profile.duration-secs", profile_duration+19, NULL) > 0) {
+ opt.optionString = profile_duration;
+ mOptions.add(opt);
+ }
- // Coefficient for period backoff. The the period is multiplied
- // by this value after each profile run.
- strcpy(profile_backoff, "-Xprofile-backoff:");
- property_get("dalvik.vm.profile.backoff_coeff", profile_backoff+18, "2.0");
- opt.optionString = profile_backoff;
- mOptions.add(opt);
+ // Polling interval during profile run (microseconds).
+ strcpy(profile_interval, "-Xprofile-interval:");
+ if (property_get("dalvik.vm.profile.interval-us", profile_interval+19, NULL) > 0) {
+ opt.optionString = profile_interval;
+ mOptions.add(opt);
+ }
+
+ // Coefficient for period backoff. The the period is multiplied
+ // by this value after each profile run.
+ strcpy(profile_backoff, "-Xprofile-backoff:");
+ if (property_get("dalvik.vm.profile.backoff-coeff", profile_backoff+18, NULL) > 0) {
+ opt.optionString = profile_backoff;
+ mOptions.add(opt);
+ }
+
+ // Top K% of samples that are considered relevant when deciding if the app should be recompiled.
+ strcpy(profile_top_k_threshold, "-Xprofile-top-k-threshold:");
+ if (property_get("dalvik.vm.profile.top-k-thr", profile_top_k_threshold+26, NULL) > 0) {
+ opt.optionString = profile_top_k_threshold;
+ mOptions.add(opt);
+ }
+
+ // The threshold after which a change in the structure of the top K% profiled samples becomes significant
+ // and triggers recompilation. A change in profile is considered significant if X% (top-k-change-threshold)
+ // of the top K% (top-k-threshold property) samples has changed.
+ strcpy(profile_top_k_change_threshold, "-Xprofile-top-k-change-threshold:");
+ if (property_get("dalvik.vm.profile.top-k-ch-thr", profile_top_k_change_threshold+33, NULL) > 0) {
+ opt.optionString = profile_top_k_change_threshold;
+ mOptions.add(opt);
+ }
}
initArgs.version = JNI_VERSION_1_4;
@@ -1214,7 +1242,6 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_view_RenderNodeAnimator),
REG_JNI(register_android_view_GraphicBuffer),
REG_JNI(register_android_view_GLES20Canvas),
- REG_JNI(register_android_view_GLRenderer),
REG_JNI(register_android_view_HardwareLayer),
REG_JNI(register_android_view_ThreadedRenderer),
REG_JNI(register_android_view_Surface),
@@ -1290,6 +1317,7 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_hardware_camera2_DngCreator),
REG_JNI(register_android_hardware_SensorManager),
REG_JNI(register_android_hardware_SerialPort),
+ REG_JNI(register_android_hardware_SoundTrigger),
REG_JNI(register_android_hardware_UsbDevice),
REG_JNI(register_android_hardware_UsbDeviceConnection),
REG_JNI(register_android_hardware_UsbRequest),
@@ -1301,6 +1329,7 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_media_ToneGenerator),
REG_JNI(register_android_opengl_classes),
+ REG_JNI(register_android_server_fingerprint_FingerprintService),
REG_JNI(register_android_server_NetworkManagementSocketTagger),
REG_JNI(register_android_server_Watchdog),
REG_JNI(register_android_ddm_DdmHandleNativeHeap),
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 0328517..c139c9d 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -258,16 +258,16 @@ static void ToColor_SI8_Opaque(SkColor dst[], const void* src, int width,
// can return NULL
static ToColorProc ChooseToColorProc(const SkBitmap& src, bool isPremultiplied) {
- switch (src.config()) {
- case SkBitmap::kARGB_8888_Config:
+ switch (src.colorType()) {
+ case kN32_SkColorType:
if (src.isOpaque()) return ToColor_S32_Opaque;
return isPremultiplied ? ToColor_S32_Alpha : ToColor_S32_Raw;
- case SkBitmap::kARGB_4444_Config:
+ case kARGB_4444_SkColorType:
if (src.isOpaque()) return ToColor_S4444_Opaque;
return isPremultiplied ? ToColor_S4444_Alpha : ToColor_S4444_Raw;
- case SkBitmap::kRGB_565_Config:
+ case kRGB_565_SkColorType:
return ToColor_S565;
- case SkBitmap::kIndex8_Config:
+ case kIndex_8_SkColorType:
if (src.getColorTable() == NULL) {
return NULL;
}
@@ -291,7 +291,7 @@ static int getPremulBitmapCreateFlags(bool isMutable) {
static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
jint offset, jint stride, jint width, jint height,
jint configHandle, jboolean isMutable) {
- SkBitmap::Config config = static_cast<SkBitmap::Config>(configHandle);
+ SkColorType colorType = SkBitmapConfigToColorType(static_cast<SkBitmap::Config>(configHandle));
if (NULL != jColors) {
size_t n = env->GetArrayLength(jColors);
if (n < SkAbs32(stride) * (size_t)height) {
@@ -301,12 +301,12 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
}
// ARGB_4444 is a deprecated format, convert automatically to 8888
- if (config == SkBitmap::kARGB_4444_Config) {
- config = SkBitmap::kARGB_8888_Config;
+ if (colorType == kARGB_4444_SkColorType) {
+ colorType = kN32_SkColorType;
}
SkBitmap bitmap;
- bitmap.setConfig(config, width, height);
+ bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType));
jbyteArray buff = GraphicsJNI::allocateJavaPixelRef(env, &bitmap, NULL);
if (NULL == buff) {
@@ -361,24 +361,50 @@ static jboolean Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) {
}
static void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jlong bitmapHandle,
- jint width, jint height, jint configHandle, jint allocSize) {
+ jint width, jint height, jint configHandle, jint allocSize,
+ jboolean requestPremul) {
SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
SkBitmap::Config config = static_cast<SkBitmap::Config>(configHandle);
- if (width * height * SkBitmap::ComputeBytesPerPixel(config) > allocSize) {
+ SkColorType colorType = SkBitmapConfigToColorType(config);
+
+ // ARGB_4444 is a deprecated format, convert automatically to 8888
+ if (colorType == kARGB_4444_SkColorType) {
+ colorType = kN32_SkColorType;
+ }
+
+ if (width * height * SkColorTypeBytesPerPixel(colorType) > allocSize) {
// done in native as there's no way to get BytesPerPixel in Java
doThrowIAE(env, "Bitmap not large enough to support new configuration");
return;
}
SkPixelRef* ref = bitmap->pixelRef();
- SkSafeRef(ref);
- bitmap->setConfig(config, width, height);
+ ref->ref();
+ SkAlphaType alphaType;
+ if (bitmap->colorType() != kRGB_565_SkColorType
+ && bitmap->alphaType() == kOpaque_SkAlphaType) {
+ // If the original bitmap was set to opaque, keep that setting, unless it
+ // was 565, which is required to be opaque.
+ alphaType = kOpaque_SkAlphaType;
+ } else {
+ // Otherwise respect the premultiplied request.
+ alphaType = requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
+ }
+ bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType));
+ // FIXME: Skia thinks of an SkPixelRef as having a constant SkImageInfo (except for
+ // its alphatype), so it would make more sense from Skia's perspective to create a
+ // new SkPixelRef. That said, libhwui uses the pointer to the SkPixelRef as a key
+ // for its cache, so it won't realize this is the same Java Bitmap.
+ SkImageInfo& info = const_cast<SkImageInfo&>(ref->info());
+ // Use the updated from the SkBitmap, which may have corrected an invalid alphatype.
+ // (e.g. 565 non-opaque)
+ info = bitmap->info();
bitmap->setPixelRef(ref);
// notifyPixelsChanged will increment the generation ID even though the actual pixel data
// hasn't been touched. This signals the renderer that the bitmap (including width, height,
- // and config) has changed.
+ // colortype and alphatype) has changed.
ref->notifyPixelsChanged();
- SkSafeUnref(ref);
+ ref->unref();
}
// These must match the int values in Bitmap.java
@@ -489,28 +515,29 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
android::Parcel* p = android::parcelForJavaObject(env, parcel);
- const bool isMutable = p->readInt32() != 0;
- const SkBitmap::Config config = (SkBitmap::Config)p->readInt32();
- const int width = p->readInt32();
- const int height = p->readInt32();
- const int rowBytes = p->readInt32();
- const int density = p->readInt32();
-
- if (SkBitmap::kARGB_8888_Config != config &&
- SkBitmap::kRGB_565_Config != config &&
- SkBitmap::kARGB_4444_Config != config &&
- SkBitmap::kIndex8_Config != config &&
- SkBitmap::kA8_Config != config) {
- SkDebugf("Bitmap_createFromParcel unknown config: %d\n", config);
+ const bool isMutable = p->readInt32() != 0;
+ const SkColorType colorType = (SkColorType)p->readInt32();
+ const SkAlphaType alphaType = (SkAlphaType)p->readInt32();
+ const int width = p->readInt32();
+ const int height = p->readInt32();
+ const int rowBytes = p->readInt32();
+ const int density = p->readInt32();
+
+ if (kN32_SkColorType != colorType &&
+ kRGB_565_SkColorType != colorType &&
+ kARGB_4444_SkColorType != colorType &&
+ kIndex_8_SkColorType != colorType &&
+ kAlpha_8_SkColorType != colorType) {
+ SkDebugf("Bitmap_createFromParcel unknown colortype: %d\n", colorType);
return NULL;
}
SkBitmap* bitmap = new SkBitmap;
- bitmap->setConfig(config, width, height, rowBytes);
+ bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType), rowBytes);
SkColorTable* ctable = NULL;
- if (config == SkBitmap::kIndex8_Config) {
+ if (colorType == kIndex_8_SkColorType) {
int count = p->readInt32();
if (count > 0) {
size_t size = count * sizeof(SkPMColor);
@@ -561,13 +588,14 @@ static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
android::Parcel* p = android::parcelForJavaObject(env, parcel);
p->writeInt32(isMutable);
- p->writeInt32(bitmap->config());
+ p->writeInt32(bitmap->colorType());
+ p->writeInt32(bitmap->alphaType());
p->writeInt32(bitmap->width());
p->writeInt32(bitmap->height());
p->writeInt32(bitmap->rowBytes());
p->writeInt32(density);
- if (bitmap->config() == SkBitmap::kIndex8_Config) {
+ if (bitmap->colorType() == kIndex_8_SkColorType) {
SkColorTable* ctable = bitmap->getColorTable();
if (ctable != NULL) {
int count = ctable->count();
@@ -799,7 +827,7 @@ static JNINativeMethod gBitmapMethods[] = {
(void*)Bitmap_copy },
{ "nativeDestructor", "(J)V", (void*)Bitmap_destructor },
{ "nativeRecycle", "(J)Z", (void*)Bitmap_recycle },
- { "nativeReconfigure", "(JIIII)V", (void*)Bitmap_reconfigure },
+ { "nativeReconfigure", "(JIIIIZ)V", (void*)Bitmap_reconfigure },
{ "nativeCompress", "(JIILjava/io/OutputStream;[B)Z",
(void*)Bitmap_compress },
{ "nativeErase", "(JI)V", (void*)Bitmap_erase },
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 7aa241a..86ed677 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -2,11 +2,8 @@
#include "BitmapFactory.h"
#include "NinePatchPeeker.h"
-#include "SkData.h"
#include "SkFrontBufferedStream.h"
#include "SkImageDecoder.h"
-#include "SkImageRef_ashmem.h"
-#include "SkImageRef_GlobalPool.h"
#include "SkMath.h"
#include "SkPixelRef.h"
#include "SkStream.h"
@@ -32,8 +29,6 @@ jfieldID gOptions_configFieldID;
jfieldID gOptions_premultipliedFieldID;
jfieldID gOptions_mutableFieldID;
jfieldID gOptions_ditherFieldID;
-jfieldID gOptions_purgeableFieldID;
-jfieldID gOptions_shareableFieldID;
jfieldID gOptions_preferQualityOverSpeedFieldID;
jfieldID gOptions_scaledFieldID;
jfieldID gOptions_densityFieldID;
@@ -90,14 +85,6 @@ jstring getMimeTypeString(JNIEnv* env, SkImageDecoder::Format format) {
return jstr;
}
-static bool optionsPurgeable(JNIEnv* env, jobject options) {
- return options != NULL && env->GetBooleanField(options, gOptions_purgeableFieldID);
-}
-
-static bool optionsShareable(JNIEnv* env, jobject options) {
- return options != NULL && env->GetBooleanField(options, gOptions_shareableFieldID);
-}
-
static bool optionsJustBounds(JNIEnv* env, jobject options) {
return options != NULL && env->GetBooleanField(options, gOptions_justBoundsFieldID);
}
@@ -125,28 +112,6 @@ static void scaleNinePatchChunk(android::Res_png_9patch* chunk, float scale) {
}
}
-static SkPixelRef* installPixelRef(SkBitmap* bitmap, SkStreamRewindable* stream,
- int sampleSize, bool ditherImage) {
-
- SkImageInfo bitmapInfo;
- if (!bitmap->asImageInfo(&bitmapInfo)) {
- ALOGW("bitmap has unknown configuration so no memory has been allocated");
- return NULL;
- }
-
- SkImageRef* pr;
- // only use ashmem for large images, since mmaps come at a price
- if (bitmap->getSize() >= 32 * 1024) {
- pr = new SkImageRef_ashmem(bitmapInfo, stream, sampleSize);
- } else {
- pr = new SkImageRef_GlobalPool(bitmapInfo, stream, sampleSize);
- }
- pr->setDitherImage(ditherImage);
- bitmap->setPixelRef(pr)->unref();
- pr->isOpaque(bitmap);
- return pr;
-}
-
static SkColorType colorTypeForScaledOutput(SkColorType colorType) {
switch (colorType) {
case kUnknown_SkColorType:
@@ -230,21 +195,17 @@ private:
const unsigned int mSize;
};
-// since we "may" create a purgeable imageref, we require the stream be ref'able
-// i.e. dynamically allocated, since its lifetime may exceed the current stack
-// frame.
static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding,
- jobject options, bool allowPurgeable, bool forcePurgeable = false) {
+ jobject options) {
int sampleSize = 1;
- SkImageDecoder::Mode mode = SkImageDecoder::kDecodePixels_Mode;
+ SkImageDecoder::Mode decodeMode = SkImageDecoder::kDecodePixels_Mode;
SkBitmap::Config prefConfig = SkBitmap::kARGB_8888_Config;
bool doDither = true;
bool isMutable = false;
float scale = 1.0f;
- bool isPurgeable = forcePurgeable || (allowPurgeable && optionsPurgeable(env, options));
bool preferQualityOverSpeed = false;
bool requireUnpremultiplied = false;
@@ -253,7 +214,7 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
if (options != NULL) {
sampleSize = env->GetIntField(options, gOptions_sampleSizeFieldID);
if (optionsJustBounds(env, options)) {
- mode = SkImageDecoder::kDecodeBounds_Mode;
+ decodeMode = SkImageDecoder::kDecodeBounds_Mode;
}
// initialize these, in case we fail later on
@@ -281,7 +242,6 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
}
const bool willScale = scale != 1.0f;
- isPurgeable &= !willScale;
SkImageDecoder* decoder = SkImageDecoder::Factory(stream);
if (decoder == NULL) {
@@ -312,8 +272,6 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
NinePatchPeeker peeker(decoder);
decoder->setPeeker(&peeker);
- SkImageDecoder::Mode decodeMode = isPurgeable ? SkImageDecoder::kDecodeBounds_Mode : mode;
-
JavaPixelAllocator javaAllocator(env);
RecyclingPixelAllocator recyclingAllocator(outputBitmap->pixelRef(), existingBufferSize);
ScaleCheckingAllocator scaleCheckingAllocator(scale, existingBufferSize);
@@ -354,7 +312,7 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
int scaledWidth = decodingBitmap.width();
int scaledHeight = decodingBitmap.height();
- if (willScale && mode != SkImageDecoder::kDecodeBounds_Mode) {
+ if (willScale && decodeMode != SkImageDecoder::kDecodeBounds_Mode) {
scaledWidth = int(scaledWidth * scale + 0.5f);
scaledHeight = int(scaledHeight * scale + 0.5f);
}
@@ -368,7 +326,7 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
}
// if we're in justBounds mode, return now (skip the java bitmap)
- if (mode == SkImageDecoder::kDecodeBounds_Mode) {
+ if (decodeMode == SkImageDecoder::kDecodeBounds_Mode) {
return NULL;
}
@@ -428,7 +386,7 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
// FIXME: If the alphaType is kUnpremul and the image has alpha, the
// colors may not be correct, since Skia does not yet support drawing
// to/from unpremultiplied bitmaps.
- outputBitmap->setConfig(SkImageInfo::Make(scaledWidth, scaledHeight,
+ outputBitmap->setInfo(SkImageInfo::Make(scaledWidth, scaledHeight,
colorType, decodingBitmap.alphaType()));
if (!outputBitmap->allocPixels(outputAllocator, NULL)) {
return nullObjectReturn("allocation failed for scaled bitmap");
@@ -460,21 +418,15 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
}
}
- SkPixelRef* pr;
- if (isPurgeable) {
- pr = installPixelRef(outputBitmap, stream, sampleSize, doDither);
- } else {
- // if we get here, we're in kDecodePixels_Mode and will therefore
- // already have a pixelref installed.
- pr = outputBitmap->pixelRef();
- }
- if (pr == NULL) {
+ // if we get here, we're in kDecodePixels_Mode and will therefore
+ // already have a pixelref installed.
+ if (outputBitmap->pixelRef() == NULL) {
return nullObjectReturn("Got null SkPixelRef");
}
if (!isMutable && javaBitmap == NULL) {
// promise we will never change our pixels (great for sharing and pictures)
- pr->setImmutable();
+ outputBitmap->setImmutable();
}
// detach bitmap from its autodeleter, since we want to own it now
@@ -513,8 +465,7 @@ static jobject nativeDecodeStream(JNIEnv* env, jobject clazz, jobject is, jbyteA
SkAutoTUnref<SkStreamRewindable> bufferedStream(
SkFrontBufferedStream::Create(stream, BYTES_TO_BUFFER));
SkASSERT(bufferedStream.get() != NULL);
- // for now we don't allow purgeable with java inputstreams
- bitmap = doDecode(env, bufferedStream, padding, options, false, false);
+ bitmap = doDecode(env, bufferedStream, padding, options);
}
return bitmap;
}
@@ -543,76 +494,33 @@ static jobject nativeDecodeFileDescriptor(JNIEnv* env, jobject clazz, jobject fi
SkAutoTUnref<SkFILEStream> fileStream(new SkFILEStream(file,
SkFILEStream::kCallerRetains_Ownership));
- SkAutoTUnref<SkStreamRewindable> stream;
-
- // Retain the old behavior of allowing purgeable if both purgeable and
- // shareable are set to true.
- bool isPurgeable = optionsPurgeable(env, bitmapFactoryOptions)
- && optionsShareable(env, bitmapFactoryOptions);
- if (isPurgeable) {
- // Copy the stream, so the image can be decoded multiple times without
- // continuing to modify the original file descriptor.
- // Copy beginning from the current position.
- const size_t fileSize = fileStream->getLength() - fileStream->getPosition();
- void* buffer = sk_malloc_flags(fileSize, 0);
- if (buffer == NULL) {
- return nullObjectReturn("Could not make a copy for ashmem");
- }
-
- SkAutoTUnref<SkData> data(SkData::NewFromMalloc(buffer, fileSize));
+ // Use a buffered stream. Although an SkFILEStream can be rewound, this
+ // ensures that SkImageDecoder::Factory never rewinds beyond the
+ // current position of the file descriptor.
+ SkAutoTUnref<SkStreamRewindable> stream(SkFrontBufferedStream::Create(fileStream,
+ BYTES_TO_BUFFER));
- if (fileStream->read(buffer, fileSize) != fileSize) {
- return nullObjectReturn("Could not read the file.");
- }
-
- stream.reset(new SkMemoryStream(data));
- } else {
- // Use a buffered stream. Although an SkFILEStream can be rewound, this
- // ensures that SkImageDecoder::Factory never rewinds beyond the
- // current position of the file descriptor.
- stream.reset(SkFrontBufferedStream::Create(fileStream, BYTES_TO_BUFFER));
- }
-
- return doDecode(env, stream, padding, bitmapFactoryOptions, isPurgeable);
+ return doDecode(env, stream, padding, bitmapFactoryOptions);
}
static jobject nativeDecodeAsset(JNIEnv* env, jobject clazz, jlong native_asset,
jobject padding, jobject options) {
- SkStreamRewindable* stream;
Asset* asset = reinterpret_cast<Asset*>(native_asset);
- bool forcePurgeable = optionsPurgeable(env, options);
- if (forcePurgeable) {
- // if we could "ref/reopen" the asset, we may not need to copy it here
- // and we could assume optionsShareable, since assets are always RO
- stream = CopyAssetToStream(asset);
- if (stream == NULL) {
- return NULL;
- }
- } else {
- // since we know we'll be done with the asset when we return, we can
- // just use a simple wrapper
- stream = new AssetStreamAdaptor(asset,
- AssetStreamAdaptor::kNo_OwnAsset,
- AssetStreamAdaptor::kNo_HasMemoryBase);
- }
- SkAutoUnref aur(stream);
- return doDecode(env, stream, padding, options, forcePurgeable, forcePurgeable);
+ // since we know we'll be done with the asset when we return, we can
+ // just use a simple wrapper
+ SkAutoTUnref<SkStreamRewindable> stream(new AssetStreamAdaptor(asset,
+ AssetStreamAdaptor::kNo_OwnAsset, AssetStreamAdaptor::kNo_HasMemoryBase));
+ return doDecode(env, stream, padding, options);
}
static jobject nativeDecodeByteArray(JNIEnv* env, jobject, jbyteArray byteArray,
jint offset, jint length, jobject options) {
- /* If optionsShareable() we could decide to just wrap the java array and
- share it, but that means adding a globalref to the java array object
- and managing its lifetime. For now we just always copy the array's data
- if optionsPurgeable(), unless we're just decoding bounds.
- */
- bool purgeable = optionsPurgeable(env, options) && !optionsJustBounds(env, options);
AutoJavaByteArray ar(env, byteArray);
- SkMemoryStream* stream = new SkMemoryStream(ar.ptr() + offset, length, purgeable);
+ SkMemoryStream* stream = new SkMemoryStream(ar.ptr() + offset, length, false);
SkAutoUnref aur(stream);
- return doDecode(env, stream, NULL, options, purgeable);
+ return doDecode(env, stream, NULL, options);
}
static void nativeRequestCancel(JNIEnv*, jobject joptions) {
@@ -676,8 +584,6 @@ int register_android_graphics_BitmapFactory(JNIEnv* env) {
gOptions_premultipliedFieldID = getFieldIDCheck(env, options_class, "inPremultiplied", "Z");
gOptions_mutableFieldID = getFieldIDCheck(env, options_class, "inMutable", "Z");
gOptions_ditherFieldID = getFieldIDCheck(env, options_class, "inDither", "Z");
- gOptions_purgeableFieldID = getFieldIDCheck(env, options_class, "inPurgeable", "Z");
- gOptions_shareableFieldID = getFieldIDCheck(env, options_class, "inInputShareable", "Z");
gOptions_preferQualityOverSpeedFieldID = getFieldIDCheck(env, options_class,
"inPreferQualityOverSpeed", "Z");
gOptions_scaledFieldID = getFieldIDCheck(env, options_class, "inScaled", "Z");
diff --git a/core/jni/android/graphics/Camera.cpp b/core/jni/android/graphics/Camera.cpp
index ef57e3d..d17f46c 100644
--- a/core/jni/android/graphics/Camera.cpp
+++ b/core/jni/android/graphics/Camera.cpp
@@ -3,6 +3,8 @@
#include "SkCamera.h"
+#include "GraphicsJNI.h"
+
static jfieldID gNativeInstanceFieldID;
static void Camera_constructor(JNIEnv* env, jobject obj) {
@@ -93,7 +95,7 @@ static void Camera_getMatrix(JNIEnv* env, jobject obj, jlong matrixHandle) {
}
static void Camera_applyToCanvas(JNIEnv* env, jobject obj, jlong canvasHandle) {
- SkCanvas* native_canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* native_canvas = GraphicsJNI::getNativeCanvas(canvasHandle);
jlong viewHandle = env->GetLongField(obj, gNativeInstanceFieldID);
Sk3DView* v = reinterpret_cast<Sk3DView*>(viewHandle);
v->applyToCanvas((SkCanvas*)native_canvas);
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 432a615..9e09280 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -19,12 +19,14 @@
#include <android_runtime/AndroidRuntime.h>
#include "SkCanvas.h"
+#include "SkClipStack.h"
#include "SkDevice.h"
+#include "SkDeque.h"
#include "SkDrawFilter.h"
#include "SkGraphics.h"
-#include "SkImageRef_GlobalPool.h"
#include "SkPorterDuff.h"
#include "SkShader.h"
+#include "SkTArray.h"
#include "SkTemplates.h"
#ifdef USE_MINIKIN
@@ -42,21 +44,6 @@
#include <utils/Log.h>
-static uint32_t get_thread_msec() {
-#if defined(HAVE_POSIX_CLOCKS)
- struct timespec tm;
-
- clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tm);
-
- return tm.tv_sec * 1000LL + tm.tv_nsec / 1000000;
-#else
- struct timeval tv;
-
- gettimeofday(&tv, NULL);
- return tv.tv_sec * 1000LL + tv.tv_usec / 1000;
-#endif
-}
-
namespace android {
class ClipCopier : public SkCanvas::ClipVisitor {
@@ -77,6 +64,155 @@ private:
SkCanvas* m_dstCanvas;
};
+// Holds an SkCanvas reference plus additional native data.
+class NativeCanvasWrapper {
+private:
+ struct SaveRec {
+ int saveCount;
+ SkCanvas::SaveFlags saveFlags;
+ };
+
+public:
+ NativeCanvasWrapper(SkCanvas* canvas)
+ : mCanvas(canvas)
+ , mSaveStack(NULL) {
+ SkASSERT(canvas);
+ }
+
+ ~NativeCanvasWrapper() {
+ delete mSaveStack;
+ }
+
+ SkCanvas* getCanvas() const {
+ return mCanvas.get();
+ }
+
+ void setCanvas(SkCanvas* canvas) {
+ SkASSERT(canvas);
+ mCanvas.reset(canvas);
+
+ delete mSaveStack;
+ mSaveStack = NULL;
+ }
+
+ int save(SkCanvas::SaveFlags flags) {
+ int count = mCanvas->save();
+ recordPartialSave(flags);
+ return count;
+ }
+
+ int saveLayer(const SkRect* bounds, const SkPaint* paint,
+ SkCanvas::SaveFlags flags) {
+ int count = mCanvas->saveLayer(bounds, paint,
+ static_cast<SkCanvas::SaveFlags>(flags | SkCanvas::kMatrixClip_SaveFlag));
+ recordPartialSave(flags);
+ return count;
+ }
+
+ int saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
+ SkCanvas::SaveFlags flags) {
+ int count = mCanvas->saveLayerAlpha(bounds, alpha,
+ static_cast<SkCanvas::SaveFlags>(flags | SkCanvas::kMatrixClip_SaveFlag));
+ recordPartialSave(flags);
+ return count;
+ }
+
+ void restore() {
+ const SaveRec* rec = (NULL == mSaveStack)
+ ? NULL
+ : static_cast<SaveRec*>(mSaveStack->back());
+ int currentSaveCount = mCanvas->getSaveCount() - 1;
+ SkASSERT(NULL == rec || currentSaveCount >= rec->saveCount);
+
+ if (NULL == rec || rec->saveCount != currentSaveCount) {
+ // Fast path - no record for this frame.
+ mCanvas->restore();
+ return;
+ }
+
+ bool preserveMatrix = !(rec->saveFlags & SkCanvas::kMatrix_SaveFlag);
+ bool preserveClip = !(rec->saveFlags & SkCanvas::kClip_SaveFlag);
+
+ SkMatrix savedMatrix;
+ if (preserveMatrix) {
+ savedMatrix = mCanvas->getTotalMatrix();
+ }
+
+ SkTArray<SkClipStack::Element> savedClips;
+ if (preserveClip) {
+ saveClipsForFrame(savedClips, currentSaveCount);
+ }
+
+ mCanvas->restore();
+
+ if (preserveMatrix) {
+ mCanvas->setMatrix(savedMatrix);
+ }
+
+ if (preserveClip && !savedClips.empty()) {
+ applyClips(savedClips);
+ }
+
+ mSaveStack->pop_back();
+ }
+
+private:
+ void recordPartialSave(SkCanvas::SaveFlags flags) {
+ // A partial save is a save operation which doesn't capture the full canvas state.
+ // (either kMatrix_SaveFlags or kClip_SaveFlag is missing).
+
+ // Mask-out non canvas state bits.
+ flags = static_cast<SkCanvas::SaveFlags>(flags & SkCanvas::kMatrixClip_SaveFlag);
+
+ if (SkCanvas::kMatrixClip_SaveFlag == flags) {
+ // not a partial save.
+ return;
+ }
+
+ if (NULL == mSaveStack) {
+ mSaveStack = new SkDeque(sizeof(struct SaveRec), 8);
+ }
+
+ SaveRec* rec = static_cast<SaveRec*>(mSaveStack->push_back());
+ // Store the save counter in the SkClipStack domain.
+ // (0-based, equal to the number of save ops on the stack).
+ rec->saveCount = mCanvas->getSaveCount() - 1;
+ rec->saveFlags = flags;
+ }
+
+ void saveClipsForFrame(SkTArray<SkClipStack::Element>& clips,
+ int frameSaveCount) {
+ SkClipStack::Iter clipIterator(*mCanvas->getClipStack(),
+ SkClipStack::Iter::kTop_IterStart);
+ while (const SkClipStack::Element* elem = clipIterator.next()) {
+ if (elem->getSaveCount() < frameSaveCount) {
+ // done with the current frame.
+ break;
+ }
+ SkASSERT(elem->getSaveCount() == frameSaveCount);
+ clips.push_back(*elem);
+ }
+ }
+
+ void applyClips(const SkTArray<SkClipStack::Element>& clips) {
+ ClipCopier clipCopier(mCanvas);
+
+ // The clip stack stores clips in device space.
+ SkMatrix origMatrix = mCanvas->getTotalMatrix();
+ mCanvas->resetMatrix();
+
+ // We pushed the clips in reverse order.
+ for (int i = clips.count() - 1; i >= 0; --i) {
+ clips[i].replay(&clipCopier);
+ }
+
+ mCanvas->setMatrix(origMatrix);
+ }
+
+ SkAutoTUnref<SkCanvas> mCanvas;
+ SkDeque* mSaveStack; // lazily allocated, tracks partial saves.
+};
+
// Returns true if the SkCanvas's clip is non-empty.
static jboolean hasNonEmptyClip(const SkCanvas& canvas) {
bool emptyClip = canvas.isClipEmpty();
@@ -85,28 +221,35 @@ static jboolean hasNonEmptyClip(const SkCanvas& canvas) {
class SkCanvasGlue {
public:
+ // Get the native wrapper for a given handle.
+ static inline NativeCanvasWrapper* getNativeWrapper(jlong nativeHandle) {
+ SkASSERT(nativeHandle);
+ return reinterpret_cast<NativeCanvasWrapper*>(nativeHandle);
+ }
- static void finalizer(JNIEnv* env, jobject clazz, jlong canvasHandle) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
- canvas->unref();
+ // Get the SkCanvas for a given native handle.
+ static inline SkCanvas* getNativeCanvas(jlong nativeHandle) {
+ NativeCanvasWrapper* wrapper = getNativeWrapper(nativeHandle);
+ SkCanvas* canvas = wrapper->getCanvas();
+ SkASSERT(canvas);
+
+ return canvas;
}
- static jlong initRaster(JNIEnv* env, jobject, jlong bitmapHandle) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ // Construct an SkCanvas from the bitmap.
+ static SkCanvas* createCanvas(SkBitmap* bitmap) {
if (bitmap) {
- return reinterpret_cast<jlong>(new SkCanvas(*bitmap));
- } else {
- // Create an empty bitmap device to prevent callers from crashing
- // if they attempt to draw into this canvas.
- SkBitmap emptyBitmap;
- return reinterpret_cast<jlong>(new SkCanvas(emptyBitmap));
+ return SkNEW_ARGS(SkCanvas, (*bitmap));
}
+
+ // Create an empty bitmap device to prevent callers from crashing
+ // if they attempt to draw into this canvas.
+ SkBitmap emptyBitmap;
+ return new SkCanvas(emptyBitmap);
}
- static void copyCanvasState(JNIEnv* env, jobject clazz,
- jlong srcCanvasHandle, jlong dstCanvasHandle) {
- SkCanvas* srcCanvas = reinterpret_cast<SkCanvas*>(srcCanvasHandle);
- SkCanvas* dstCanvas = reinterpret_cast<SkCanvas*>(dstCanvasHandle);
+ // Copy the canvas matrix & clip state.
+ static void copyCanvasState(SkCanvas* srcCanvas, SkCanvas* dstCanvas) {
if (srcCanvas && dstCanvas) {
dstCanvas->setMatrix(srcCanvas->getTotalMatrix());
if (NULL != srcCanvas->getDevice() && NULL != dstCanvas->getDevice()) {
@@ -116,10 +259,44 @@ public:
}
}
+ // Native JNI handlers
+ static void finalizer(JNIEnv* env, jobject clazz, jlong nativeHandle) {
+ NativeCanvasWrapper* wrapper = reinterpret_cast<NativeCanvasWrapper*>(nativeHandle);
+ delete wrapper;
+ }
+
+ // Native wrapper constructor used by Canvas(Bitmap)
+ static jlong initRaster(JNIEnv* env, jobject, jlong bitmapHandle) {
+ // No check - 0 is a valid bitmapHandle.
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ SkCanvas* canvas = createCanvas(bitmap);
+
+ return reinterpret_cast<jlong>(new NativeCanvasWrapper(canvas));
+ }
+
+ // Native wrapper constructor used by Canvas(native_canvas)
+ static jlong initCanvas(JNIEnv* env, jobject, jlong canvasHandle) {
+ SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ return reinterpret_cast<jlong>(new NativeCanvasWrapper(canvas));
+ }
+
+ // Set the given bitmap as the new draw target (wrapped in a new SkCanvas),
+ // optionally copying canvas matrix & clip state.
+ static void setBitmap(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
+ jboolean copyState) {
+ NativeCanvasWrapper* wrapper = reinterpret_cast<NativeCanvasWrapper*>(canvasHandle);
+ SkCanvas* newCanvas = createCanvas(reinterpret_cast<SkBitmap*>(bitmapHandle));
+ NPE_CHECK_RETURN_VOID(env, newCanvas);
+
+ if (copyState == JNI_TRUE) {
+ copyCanvasState(wrapper->getCanvas(), newCanvas);
+ }
+
+ // setCanvas() unrefs the old canvas.
+ wrapper->setCanvas(newCanvas);
+ }
static void freeCaches(JNIEnv* env, jobject) {
- // these are called in no particular order
- SkImageRef_GlobalPool::SetRAMUsed(0);
SkGraphics::PurgeFontCache();
}
@@ -127,146 +304,107 @@ public:
TextLayoutEngine::getInstance().purgeCaches();
}
- static jboolean isOpaque(JNIEnv* env, jobject jcanvas) {
- NPE_CHECK_RETURN_ZERO(env, jcanvas);
- SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
+ static jboolean isOpaque(JNIEnv*, jobject, jlong canvasHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
bool result = canvas->getDevice()->accessBitmap(false).isOpaque();
return result ? JNI_TRUE : JNI_FALSE;
}
- static jint getWidth(JNIEnv* env, jobject jcanvas) {
- NPE_CHECK_RETURN_ZERO(env, jcanvas);
- SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
+ static jint getWidth(JNIEnv*, jobject, jlong canvasHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
int width = canvas->getDevice()->accessBitmap(false).width();
return static_cast<jint>(width);
}
- static jint getHeight(JNIEnv* env, jobject jcanvas) {
- NPE_CHECK_RETURN_ZERO(env, jcanvas);
- SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
+ static jint getHeight(JNIEnv*, jobject, jlong canvasHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
int height = canvas->getDevice()->accessBitmap(false).height();
return static_cast<jint>(height);
}
- static jint saveAll(JNIEnv* env, jobject jcanvas) {
- NPE_CHECK_RETURN_ZERO(env, jcanvas);
- int result = GraphicsJNI::getNativeCanvas(env, jcanvas)->save();
- return static_cast<jint>(result);
- }
-
- static jint save(JNIEnv* env, jobject jcanvas, jint flagsHandle) {
+ static jint save(JNIEnv*, jobject, jlong canvasHandle, jint flagsHandle) {
+ NativeCanvasWrapper* wrapper = getNativeWrapper(canvasHandle);
SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
- NPE_CHECK_RETURN_ZERO(env, jcanvas);
- int result = GraphicsJNI::getNativeCanvas(env, jcanvas)->save(flags);
- return static_cast<jint>(result);
+ return static_cast<jint>(wrapper->save(flags));
}
- static jint saveLayer(JNIEnv* env, jobject, jlong canvasHandle, jobject bounds,
- jlong paintHandle, jint flags) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- SkRect* bounds_ = NULL;
- SkRect storage;
- if (bounds != NULL) {
- GraphicsJNI::jrectf_to_rect(env, bounds, &storage);
- bounds_ = &storage;
- }
- return canvas->saveLayer(bounds_, paint, static_cast<SkCanvas::SaveFlags>(flags));
- }
-
- static jint saveLayer4F(JNIEnv* env, jobject, jlong canvasHandle,
- jfloat l, jfloat t, jfloat r, jfloat b,
- jlong paintHandle, jint flags) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ static jint saveLayer(JNIEnv* env, jobject, jlong canvasHandle,
+ jfloat l, jfloat t, jfloat r, jfloat b,
+ jlong paintHandle, jint flagsHandle) {
+ NativeCanvasWrapper* wrapper = getNativeWrapper(canvasHandle);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
SkRect bounds;
bounds.set(l, t, r, b);
- int result = canvas->saveLayer(&bounds, paint,
- static_cast<SkCanvas::SaveFlags>(flags));
- return static_cast<jint>(result);
+ return static_cast<jint>(wrapper->saveLayer(&bounds, paint, flags));
}
static jint saveLayerAlpha(JNIEnv* env, jobject, jlong canvasHandle,
- jobject bounds, jint alpha, jint flags) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
- SkRect* bounds_ = NULL;
- SkRect storage;
- if (bounds != NULL) {
- GraphicsJNI::jrectf_to_rect(env, bounds, &storage);
- bounds_ = &storage;
- }
- int result = canvas->saveLayerAlpha(bounds_, alpha,
- static_cast<SkCanvas::SaveFlags>(flags));
- return static_cast<jint>(result);
- }
-
- static jint saveLayerAlpha4F(JNIEnv* env, jobject, jlong canvasHandle,
- jfloat l, jfloat t, jfloat r, jfloat b,
- jint alpha, jint flags) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ jfloat l, jfloat t, jfloat r, jfloat b,
+ jint alpha, jint flagsHandle) {
+ NativeCanvasWrapper* wrapper = getNativeWrapper(canvasHandle);
+ SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
SkRect bounds;
bounds.set(l, t, r, b);
- int result = canvas->saveLayerAlpha(&bounds, alpha,
- static_cast<SkCanvas::SaveFlags>(flags));
- return static_cast<jint>(result);
+ return static_cast<jint>(wrapper->saveLayerAlpha(&bounds, alpha, flags));
}
- static void restore(JNIEnv* env, jobject jcanvas) {
- NPE_CHECK_RETURN_VOID(env, jcanvas);
- SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
- if (canvas->getSaveCount() <= 1) { // cannot restore anymore
+ static void restore(JNIEnv* env, jobject, jlong canvasHandle) {
+ NativeCanvasWrapper* wrapper = getNativeWrapper(canvasHandle);
+ if (wrapper->getCanvas()->getSaveCount() <= 1) { // cannot restore anymore
doThrowISE(env, "Underflow in restore");
return;
}
- canvas->restore();
+ wrapper->restore();
}
- static jint getSaveCount(JNIEnv* env, jobject jcanvas) {
- NPE_CHECK_RETURN_ZERO(env, jcanvas);
- int result = GraphicsJNI::getNativeCanvas(env, jcanvas)->getSaveCount();
- return static_cast<jint>(result);
+ static jint getSaveCount(JNIEnv*, jobject, jlong canvasHandle) {
+ return static_cast<jint>(getNativeCanvas(canvasHandle)->getSaveCount());
}
- static void restoreToCount(JNIEnv* env, jobject jcanvas, jint restoreCount) {
- NPE_CHECK_RETURN_VOID(env, jcanvas);
- SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
+ static void restoreToCount(JNIEnv* env, jobject, jlong canvasHandle,
+ jint restoreCount) {
+ NativeCanvasWrapper* wrapper = getNativeWrapper(canvasHandle);
if (restoreCount < 1) {
doThrowIAE(env, "Underflow in restoreToCount");
return;
}
- canvas->restoreToCount(restoreCount);
+
+ while (wrapper->getCanvas()->getSaveCount() > restoreCount) {
+ wrapper->restore();
+ }
}
- static void translate(JNIEnv* env, jobject jcanvas, jfloat dx, jfloat dy) {
- NPE_CHECK_RETURN_VOID(env, jcanvas);
- (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->translate(dx, dy);
+ static void translate(JNIEnv*, jobject, jlong canvasHandle,
+ jfloat dx, jfloat dy) {
+ getNativeCanvas(canvasHandle)->translate(dx, dy);
}
- static void scale__FF(JNIEnv* env, jobject jcanvas, jfloat sx, jfloat sy) {
- NPE_CHECK_RETURN_VOID(env, jcanvas);
- (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->scale(sx, sy);
+ static void scale__FF(JNIEnv*, jobject, jlong canvasHandle,
+ jfloat sx, jfloat sy) {
+ getNativeCanvas(canvasHandle)->scale(sx, sy);
}
- static void rotate__F(JNIEnv* env, jobject jcanvas, jfloat degrees) {
- NPE_CHECK_RETURN_VOID(env, jcanvas);
- (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->rotate(degrees);
+ static void rotate__F(JNIEnv*, jobject, jlong canvasHandle,
+ jfloat degrees) {
+ getNativeCanvas(canvasHandle)->rotate(degrees);
}
- static void skew__FF(JNIEnv* env, jobject jcanvas, jfloat sx, jfloat sy) {
- NPE_CHECK_RETURN_VOID(env, jcanvas);
- (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->skew(sx, sy);
+ static void skew__FF(JNIEnv*, jobject, jlong canvasHandle,
+ jfloat sx, jfloat sy) {
+ getNativeCanvas(canvasHandle)->skew(sx, sy);
}
static void concat(JNIEnv* env, jobject, jlong canvasHandle,
jlong matrixHandle) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
canvas->concat(*matrix);
}
static void setMatrix(JNIEnv* env, jobject, jlong canvasHandle,
jlong matrixHandle) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
if (NULL == matrix) {
canvas->resetMatrix();
@@ -275,59 +413,19 @@ public:
}
}
- static jboolean clipRect_FFFF(JNIEnv* env, jobject jcanvas, jfloat left,
- jfloat top, jfloat right, jfloat bottom) {
- NPE_CHECK_RETURN_ZERO(env, jcanvas);
+ static jboolean clipRect(JNIEnv*, jobject, jlong canvasHandle,
+ jfloat left, jfloat top, jfloat right,
+ jfloat bottom, jint op) {
SkRect r;
r.set(left, top, right, bottom);
- SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
- c->clipRect(r);
+ SkCanvas* c = getNativeCanvas(canvasHandle);
+ c->clipRect(r, static_cast<SkRegion::Op>(op));
return hasNonEmptyClip(*c);
}
- static jboolean clipRect_IIII(JNIEnv* env, jobject jcanvas, jint left,
- jint top, jint right, jint bottom) {
- NPE_CHECK_RETURN_ZERO(env, jcanvas);
- SkRect r;
- r.set(SkIntToScalar(left), SkIntToScalar(top),
- SkIntToScalar(right), SkIntToScalar(bottom));
- SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
- c->clipRect(r);
- return hasNonEmptyClip(*c);
- }
-
- static jboolean clipRect_RectF(JNIEnv* env, jobject jcanvas, jobject rectf) {
- NPE_CHECK_RETURN_ZERO(env, jcanvas);
- NPE_CHECK_RETURN_ZERO(env, rectf);
- SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
- SkRect tmp;
- c->clipRect(*GraphicsJNI::jrectf_to_rect(env, rectf, &tmp));
- return hasNonEmptyClip(*c);
- }
-
- static jboolean clipRect_Rect(JNIEnv* env, jobject jcanvas, jobject rect) {
- NPE_CHECK_RETURN_ZERO(env, jcanvas);
- NPE_CHECK_RETURN_ZERO(env, rect);
- SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
- SkRect tmp;
- c->clipRect(*GraphicsJNI::jrect_to_rect(env, rect, &tmp));
- return hasNonEmptyClip(*c);
-
- }
-
- static jboolean clipRect(JNIEnv* env, jobject, jlong canvasHandle,
- jfloat left, jfloat top, jfloat right, jfloat bottom,
- jint op) {
- SkRect rect;
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
- rect.set(left, top, right, bottom);
- canvas->clipRect(rect, static_cast<SkRegion::Op>(op));
- return hasNonEmptyClip(*canvas);
- }
-
static jboolean clipPath(JNIEnv* env, jobject, jlong canvasHandle,
jlong pathHandle, jint op) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
canvas->clipPath(*reinterpret_cast<SkPath*>(pathHandle),
static_cast<SkRegion::Op>(op));
return hasNonEmptyClip(*canvas);
@@ -335,30 +433,30 @@ public:
static jboolean clipRegion(JNIEnv* env, jobject, jlong canvasHandle,
jlong deviceRgnHandle, jint op) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
SkRegion* deviceRgn = reinterpret_cast<SkRegion*>(deviceRgnHandle);
- canvas->clipRegion(*deviceRgn, static_cast<SkRegion::Op>(op));
+ SkPath rgnPath;
+ if (deviceRgn->getBoundaryPath(&rgnPath)) {
+ // The region is specified in device space.
+ SkMatrix savedMatrix = canvas->getTotalMatrix();
+ canvas->resetMatrix();
+ canvas->clipPath(rgnPath, static_cast<SkRegion::Op>(op));
+ canvas->setMatrix(savedMatrix);
+ } else {
+ canvas->clipRect(SkRect::MakeEmpty(), static_cast<SkRegion::Op>(op));
+ }
return hasNonEmptyClip(*canvas);
}
static void setDrawFilter(JNIEnv* env, jobject, jlong canvasHandle,
jlong filterHandle) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
canvas->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle));
}
- static jboolean quickReject__RectF(JNIEnv* env, jobject, jlong canvasHandle,
- jobject rect) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
- SkRect rect_;
- GraphicsJNI::jrectf_to_rect(env, rect, &rect_);
- bool result = canvas->quickReject(rect_);
- return result ? JNI_TRUE : JNI_FALSE;
- }
-
static jboolean quickReject__Path(JNIEnv* env, jobject, jlong canvasHandle,
jlong pathHandle) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
bool result = canvas->quickReject(*reinterpret_cast<SkPath*>(pathHandle));
return result ? JNI_TRUE : JNI_FALSE;
}
@@ -366,7 +464,7 @@ public:
static jboolean quickReject__FFFF(JNIEnv* env, jobject, jlong canvasHandle,
jfloat left, jfloat top, jfloat right,
jfloat bottom) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
SkRect r;
r.set(left, top, right, bottom);
bool result = canvas->quickReject(r);
@@ -375,45 +473,43 @@ public:
static void drawRGB(JNIEnv* env, jobject, jlong canvasHandle,
jint r, jint g, jint b) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
canvas->drawARGB(0xFF, r, g, b);
}
static void drawARGB(JNIEnv* env, jobject, jlong canvasHandle,
jint a, jint r, jint g, jint b) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
canvas->drawARGB(a, r, g, b);
}
static void drawColor__I(JNIEnv* env, jobject, jlong canvasHandle,
jint color) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
canvas->drawColor(color);
}
static void drawColor__II(JNIEnv* env, jobject, jlong canvasHandle,
jint color, jint modeHandle) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
SkPorterDuff::Mode mode = static_cast<SkPorterDuff::Mode>(modeHandle);
canvas->drawColor(color, SkPorterDuff::ToXfermodeMode(mode));
}
static void drawPaint(JNIEnv* env, jobject, jlong canvasHandle,
jlong paintHandle) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
canvas->drawPaint(*paint);
}
- static void doPoints(JNIEnv* env, jobject jcanvas, jfloatArray jptsArray,
- jint offset, jint count, jobject jpaint,
- jint modeHandle) {
- NPE_CHECK_RETURN_VOID(env, jcanvas);
+ static void doPoints(JNIEnv* env, jlong canvasHandle,
+ jfloatArray jptsArray, jint offset, jint count,
+ jlong paintHandle, jint modeHandle) {
NPE_CHECK_RETURN_VOID(env, jptsArray);
- NPE_CHECK_RETURN_VOID(env, jpaint);
SkCanvas::PointMode mode = static_cast<SkCanvas::PointMode>(modeHandle);
- SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
- const SkPaint& paint = *GraphicsJNI::getNativePaint(env, jpaint);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
AutoJavaFloatArray autoPts(env, jptsArray);
float* floats = autoPts.ptr();
@@ -433,86 +529,74 @@ public:
pts[i].set(src[0], src[1]);
src += 2;
}
- canvas->drawPoints(mode, count, pts, paint);
+ canvas->drawPoints(mode, count, pts, *paint);
}
- static void drawPoints(JNIEnv* env, jobject jcanvas, jfloatArray jptsArray,
- jint offset, jint count, jobject jpaint) {
- doPoints(env, jcanvas, jptsArray, offset, count, jpaint,
+ static void drawPoints(JNIEnv* env, jobject, jlong canvasHandle,
+ jfloatArray jptsArray, jint offset,
+ jint count, jlong paintHandle) {
+ doPoints(env, canvasHandle, jptsArray, offset, count, paintHandle,
SkCanvas::kPoints_PointMode);
}
- static void drawLines(JNIEnv* env, jobject jcanvas, jfloatArray jptsArray,
- jint offset, jint count, jobject jpaint) {
- doPoints(env, jcanvas, jptsArray, offset, count, jpaint,
+ static void drawLines(JNIEnv* env, jobject, jlong canvasHandle,
+ jfloatArray jptsArray, jint offset, jint count,
+ jlong paintHandle) {
+ doPoints(env, canvasHandle, jptsArray, offset, count, paintHandle,
SkCanvas::kLines_PointMode);
}
- static void drawPoint(JNIEnv* env, jobject jcanvas, jfloat x, jfloat y,
- jobject jpaint) {
- NPE_CHECK_RETURN_VOID(env, jcanvas);
- NPE_CHECK_RETURN_VOID(env, jpaint);
- SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
- const SkPaint& paint = *GraphicsJNI::getNativePaint(env, jpaint);
-
- canvas->drawPoint(x, y, paint);
+ static void drawPoint(JNIEnv*, jobject, jlong canvasHandle, jfloat x, jfloat y,
+ jlong paintHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ canvas->drawPoint(x, y, *paint);
}
static void drawLine__FFFFPaint(JNIEnv* env, jobject, jlong canvasHandle,
jfloat startX, jfloat startY, jfloat stopX,
jfloat stopY, jlong paintHandle) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
canvas->drawLine(startX, startY, stopX, stopY, *paint);
}
- static void drawRect__RectFPaint(JNIEnv* env, jobject, jlong canvasHandle,
- jobject rect, jlong paintHandle) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- SkRect rect_;
- GraphicsJNI::jrectf_to_rect(env, rect, &rect_);
- canvas->drawRect(rect_, *paint);
- }
-
static void drawRect__FFFFPaint(JNIEnv* env, jobject, jlong canvasHandle,
jfloat left, jfloat top, jfloat right,
jfloat bottom, jlong paintHandle) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
canvas->drawRectCoords(left, top, right, bottom, *paint);
}
- static void drawOval(JNIEnv* env, jobject, jlong canvasHandle, jobject joval,
- jlong paintHandle) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ static void drawOval(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
+ jfloat right, jfloat bottom, jlong paintHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- SkRect oval;
- GraphicsJNI::jrectf_to_rect(env, joval, &oval);
+ SkRect oval = SkRect::MakeLTRB(left, top, right, bottom);
canvas->drawOval(oval, *paint);
}
static void drawCircle(JNIEnv* env, jobject, jlong canvasHandle, jfloat cx,
jfloat cy, jfloat radius, jlong paintHandle) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
canvas->drawCircle(cx, cy, radius, *paint);
}
- static void drawArc(JNIEnv* env, jobject, jlong canvasHandle, jobject joval,
- jfloat startAngle, jfloat sweepAngle,
- jboolean useCenter, jlong paintHandle) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ static void drawArc(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
+ jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle, jboolean useCenter,
+ jlong paintHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- SkRect oval;
- GraphicsJNI::jrectf_to_rect(env, joval, &oval);
+ SkRect oval = SkRect::MakeLTRB(left, top, right, bottom);
canvas->drawArc(oval, startAngle, sweepAngle, useCenter, *paint);
}
static void drawRoundRect(JNIEnv* env, jobject, jlong canvasHandle,
jfloat left, jfloat top, jfloat right, jfloat bottom, jfloat rx, jfloat ry,
jlong paintHandle) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
canvas->drawRoundRect(rect, rx, ry, *paint);
@@ -520,7 +604,7 @@ public:
static void drawPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
jlong paintHandle) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
canvas->drawPath(*path, *paint);
@@ -531,7 +615,7 @@ public:
jfloat left, jfloat top,
jlong paintHandle, jint canvasDensity,
jint screenDensity, jint bitmapDensity) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
@@ -591,7 +675,7 @@ public:
jlong bitmapHandle, jobject srcIRect,
jobject dstRectF, jlong paintHandle,
jint screenDensity, jint bitmapDensity) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
SkRect dst;
@@ -604,7 +688,7 @@ public:
jlong bitmapHandle, jobject srcIRect,
jobject dstRect, jlong paintHandle,
jint screenDensity, jint bitmapDensity) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
SkRect dst;
@@ -616,14 +700,14 @@ public:
static void drawBitmapArray(JNIEnv* env, jobject, jlong canvasHandle,
jintArray jcolors, jint offset, jint stride,
jfloat x, jfloat y, jint width, jint height,
- jboolean hasAlpha, jlong paintHandle)
- {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ jboolean hasAlpha, jlong paintHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ SkImageInfo info = SkImageInfo::Make(width, height,
+ hasAlpha ? kN32_SkColorType : kRGB_565_SkColorType,
+ kPremul_SkAlphaType);
SkBitmap bitmap;
- bitmap.setConfig(hasAlpha ? SkBitmap::kARGB_8888_Config :
- SkBitmap::kRGB_565_Config, width, height);
- if (!bitmap.allocPixels()) {
+ if (!bitmap.allocPixels(info)) {
return;
}
@@ -638,7 +722,7 @@ public:
static void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle,
jlong bitmapHandle, jlong matrixHandle,
jlong paintHandle) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
@@ -649,7 +733,7 @@ public:
jlong bitmapHandle, jint meshWidth, jint meshHeight,
jfloatArray jverts, jint vertIndex, jintArray jcolors,
jint colorIndex, jlong paintHandle) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
@@ -759,7 +843,7 @@ public:
jintArray jcolors, jint colorIndex,
jshortArray jindices, jint indexIndex,
jint indexCount, jlong paintHandle) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
SkCanvas::VertexMode mode = static_cast<SkCanvas::VertexMode>(modeHandle);
const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
@@ -797,26 +881,26 @@ public:
static void drawText___CIIFFIPaintTypeface(JNIEnv* env, jobject, jlong canvasHandle,
jcharArray text, jint index, jint count,
- jfloat x, jfloat y, jint flags,
+ jfloat x, jfloat y, jint bidiFlags,
jlong paintHandle, jlong typefaceHandle) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
jchar* textArray = env->GetCharArrayElements(text, NULL);
- drawTextWithGlyphs(canvas, textArray + index, 0, count, x, y, flags, paint, typeface);
+ drawTextWithGlyphs(canvas, textArray + index, 0, count, x, y, bidiFlags, paint, typeface);
env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
}
static void drawText__StringIIFFIPaintTypeface(JNIEnv* env, jobject,
jlong canvasHandle, jstring text,
jint start, jint end,
- jfloat x, jfloat y, jint flags,
+ jfloat x, jfloat y, jint bidiFlags,
jlong paintHandle, jlong typefaceHandle) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
const jchar* textArray = env->GetStringChars(text, NULL);
- drawTextWithGlyphs(canvas, textArray, start, end, x, y, flags, paint, typeface);
+ drawTextWithGlyphs(canvas, textArray, start, end, x, y, bidiFlags, paint, typeface);
env->ReleaseStringChars(text, textArray);
}
@@ -866,24 +950,25 @@ public:
static void drawTextWithGlyphs(SkCanvas* canvas, const jchar* textArray,
int start, int end,
- jfloat x, jfloat y, int flags, SkPaint* paint, TypefaceImpl* typeface) {
+ jfloat x, jfloat y, int bidiFlags, SkPaint* paint, TypefaceImpl* typeface) {
jint count = end - start;
- drawTextWithGlyphs(canvas, textArray + start, 0, count, count, x, y, flags, paint, typeface);
+ drawTextWithGlyphs(canvas, textArray + start, 0, count, count, x, y, bidiFlags, paint,
+ typeface);
}
static void drawTextWithGlyphs(SkCanvas* canvas, const jchar* textArray,
int start, int count, int contextCount,
- jfloat x, jfloat y, int flags, SkPaint* paint, TypefaceImpl* typeface) {
+ jfloat x, jfloat y, int bidiFlags, SkPaint* paint, TypefaceImpl* typeface) {
#ifdef USE_MINIKIN
Layout layout;
- std::string css = MinikinUtils::setLayoutProperties(&layout, paint, flags, typeface);
+ std::string css = MinikinUtils::setLayoutProperties(&layout, paint, bidiFlags, typeface);
layout.doLayout(textArray, start, count, contextCount, css);
drawGlyphsToSkia(canvas, paint, layout, x, y);
#else
sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
- textArray, start, count, contextCount, flags);
+ textArray, start, count, contextCount, bidiFlags);
if (value == NULL) {
return;
}
@@ -894,7 +979,8 @@ public:
x -= value->getTotalAdvance();
}
paint->setTextAlign(SkPaint::kLeft_Align);
- doDrawGlyphsPos(canvas, value->getGlyphs(), value->getPos(), 0, value->getGlyphsCount(), x, y, flags, paint);
+ doDrawGlyphsPos(canvas, value->getGlyphs(), value->getPos(), 0, value->getGlyphsCount(),
+ x, y, paint);
doDrawTextDecorations(canvas, x, y, value->getTotalAdvance(), paint);
paint->setTextAlign(align);
#endif
@@ -905,42 +991,37 @@ public:
#define kStdUnderline_Offset (1.0f / 9.0f)
#define kStdUnderline_Thickness (1.0f / 18.0f)
-static void doDrawTextDecorations(SkCanvas* canvas, jfloat x, jfloat y, jfloat length, SkPaint* paint) {
- uint32_t flags;
- SkDrawFilter* drawFilter = canvas->getDrawFilter();
- if (drawFilter) {
- SkPaint paintCopy(*paint);
- drawFilter->filter(&paintCopy, SkDrawFilter::kText_Type);
- flags = paintCopy.getFlags();
- } else {
- flags = paint->getFlags();
- }
- if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
- SkScalar left = x;
- SkScalar right = x + length;
- float textSize = paint->getTextSize();
- float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f);
- if (flags & SkPaint::kUnderlineText_Flag) {
- SkScalar top = y + textSize * kStdUnderline_Offset - 0.5f * strokeWidth;
- SkScalar bottom = y + textSize * kStdUnderline_Offset + 0.5f * strokeWidth;
- canvas->drawRectCoords(left, top, right, bottom, *paint);
+ static void doDrawTextDecorations(SkCanvas* canvas, jfloat x, jfloat y, jfloat length,
+ SkPaint* paint) {
+ uint32_t flags;
+ SkDrawFilter* drawFilter = canvas->getDrawFilter();
+ if (drawFilter) {
+ SkPaint paintCopy(*paint);
+ drawFilter->filter(&paintCopy, SkDrawFilter::kText_Type);
+ flags = paintCopy.getFlags();
+ } else {
+ flags = paint->getFlags();
}
- if (flags & SkPaint::kStrikeThruText_Flag) {
- SkScalar top = y + textSize * kStdStrikeThru_Offset - 0.5f * strokeWidth;
- SkScalar bottom = y + textSize * kStdStrikeThru_Offset + 0.5f * strokeWidth;
- canvas->drawRectCoords(left, top, right, bottom, *paint);
+ if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
+ SkScalar left = x;
+ SkScalar right = x + length;
+ float textSize = paint->getTextSize();
+ float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f);
+ if (flags & SkPaint::kUnderlineText_Flag) {
+ SkScalar top = y + textSize * kStdUnderline_Offset - 0.5f * strokeWidth;
+ SkScalar bottom = y + textSize * kStdUnderline_Offset + 0.5f * strokeWidth;
+ canvas->drawRectCoords(left, top, right, bottom, *paint);
+ }
+ if (flags & SkPaint::kStrikeThruText_Flag) {
+ SkScalar top = y + textSize * kStdStrikeThru_Offset - 0.5f * strokeWidth;
+ SkScalar bottom = y + textSize * kStdStrikeThru_Offset + 0.5f * strokeWidth;
+ canvas->drawRectCoords(left, top, right, bottom, *paint);
+ }
}
}
-}
-
- static void doDrawGlyphs(SkCanvas* canvas, const jchar* glyphArray, int index, int count,
- jfloat x, jfloat y, int flags, SkPaint* paint) {
- // Beware: this needs Glyph encoding (already done on the Paint constructor)
- canvas->drawText(glyphArray + index * 2, count * 2, x, y, *paint);
- }
static void doDrawGlyphsPos(SkCanvas* canvas, const jchar* glyphArray, const jfloat* posArray,
- int index, int count, jfloat x, jfloat y, int flags, SkPaint* paint) {
+ int index, int count, jfloat x, jfloat y, SkPaint* paint) {
SkPoint* posPtr = new SkPoint[count];
for (int indx = 0; indx < count; indx++) {
posPtr[indx].fX = x + posArray[indx * 2];
@@ -950,40 +1031,42 @@ static void doDrawTextDecorations(SkCanvas* canvas, jfloat x, jfloat y, jfloat l
delete[] posPtr;
}
- static void drawTextRun___CIIIIFFIPaintTypeface(
- JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, jint index,
- jint count, jint contextIndex, jint contextCount,
- jfloat x, jfloat y, jint dirFlags, jlong paintHandle, jlong typefaceHandle) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ static void drawTextRun___CIIIIFFZPaintTypeface(
+ JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, jint index,
+ jint count, jint contextIndex, jint contextCount,
+ jfloat x, jfloat y, jboolean isRtl, jlong paintHandle, jlong typefaceHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+ int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
jchar* chars = env->GetCharArrayElements(text, NULL);
drawTextWithGlyphs(canvas, chars + contextIndex, index - contextIndex,
- count, contextCount, x, y, dirFlags, paint, typeface);
+ count, contextCount, x, y, bidiFlags, paint, typeface);
env->ReleaseCharArrayElements(text, chars, JNI_ABORT);
}
- static void drawTextRun__StringIIIIFFIPaintTypeface(
- JNIEnv* env, jobject obj, jlong canvasHandle, jstring text, jint start,
- jint end, jint contextStart, jint contextEnd,
- jfloat x, jfloat y, jint dirFlags, jlong paintHandle, jlong typefaceHandle) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ static void drawTextRun__StringIIIIFFZPaintTypeface(
+ JNIEnv* env, jobject obj, jlong canvasHandle, jstring text, jint start,
+ jint end, jint contextStart, jint contextEnd,
+ jfloat x, jfloat y, jboolean isRtl, jlong paintHandle, jlong typefaceHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+ int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
jint count = end - start;
jint contextCount = contextEnd - contextStart;
const jchar* chars = env->GetStringChars(text, NULL);
drawTextWithGlyphs(canvas, chars + contextStart, start - contextStart,
- count, contextCount, x, y, dirFlags, paint, typeface);
+ count, contextCount, x, y, bidiFlags, paint, typeface);
env->ReleaseStringChars(text, chars);
}
static void drawPosText___CII_FPaint(JNIEnv* env, jobject, jlong canvasHandle,
jcharArray text, jint index, jint count,
jfloatArray pos, jlong paintHandle) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
jchar* textArray = text ? env->GetCharArrayElements(text, NULL) : NULL;
jsize textCount = text ? env->GetArrayLength(text) : NULL;
@@ -1014,7 +1097,7 @@ static void doDrawTextDecorations(SkCanvas* canvas, jfloat x, jfloat y, jfloat l
jlong canvasHandle, jstring text,
jfloatArray pos,
jlong paintHandle) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
const void* text_ = text ? env->GetStringChars(text, NULL) : NULL;
int byteLength = text ? env->GetStringLength(text) : 0;
@@ -1041,29 +1124,82 @@ static void doDrawTextDecorations(SkCanvas* canvas, jfloat x, jfloat y, jfloat l
delete[] posPtr;
}
+#ifdef USE_MINIKIN
+ class DrawTextOnPathFunctor {
+ public:
+ DrawTextOnPathFunctor(const Layout& layout, SkCanvas* canvas, float hOffset,
+ float vOffset, SkPaint* paint, SkPath* path)
+ : layout(layout), canvas(canvas), hOffset(hOffset), vOffset(vOffset),
+ paint(paint), path(path) {
+ }
+ void operator()(size_t start, size_t end) {
+ uint16_t glyphs[1];
+ for (size_t i = start; i < end; i++) {
+ glyphs[0] = layout.getGlyphId(i);
+ float x = hOffset + layout.getX(i);
+ float y = vOffset + layout.getY(i);
+ canvas->drawTextOnPathHV(glyphs, sizeof(glyphs), *path, x, y, *paint);
+ }
+ }
+ private:
+ const Layout& layout;
+ SkCanvas* canvas;
+ float hOffset;
+ float vOffset;
+ SkPaint* paint;
+ SkPath* path;
+ };
+#endif
+
+ static void doDrawTextOnPath(SkPaint* paint, const jchar* text, int count, int bidiFlags,
+ float hOffset, float vOffset, SkPath* path, SkCanvas* canvas, TypefaceImpl* typeface) {
+#ifdef USE_MINIKIN
+ Layout layout;
+ std::string css = MinikinUtils::setLayoutProperties(&layout, paint, bidiFlags, typeface);
+ layout.doLayout(text, 0, count, count, css);
+ hOffset += MinikinUtils::hOffsetForTextAlign(paint, layout, *path);
+ // Set align to left for drawing, as we don't want individual
+ // glyphs centered or right-aligned; the offset above takes
+ // care of all alignment.
+ SkPaint::Align align = paint->getTextAlign();
+ paint->setTextAlign(SkPaint::kLeft_Align);
+
+ DrawTextOnPathFunctor f(layout, canvas, hOffset, vOffset, paint, path);
+ MinikinUtils::forFontRun(layout, paint, f);
+ paint->setTextAlign(align);
+#else
+ TextLayout::drawTextOnPath(paint, text, count, bidiFlags, hOffset, vOffset, path, canvas);
+#endif
+ }
+
static void drawTextOnPath___CIIPathFFPaint(JNIEnv* env, jobject,
jlong canvasHandle, jcharArray text, jint index, jint count,
- jlong pathHandle, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintHandle) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ jlong pathHandle, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintHandle,
+ jlong typefaceHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
jchar* textArray = env->GetCharArrayElements(text, NULL);
- TextLayout::drawTextOnPath(paint, textArray + index, count, bidiFlags, hOffset, vOffset,
- path, canvas);
+ doDrawTextOnPath(paint, textArray + index, count, bidiFlags, hOffset, vOffset,
+ path, canvas, typeface);
env->ReleaseCharArrayElements(text, textArray, 0);
}
static void drawTextOnPath__StringPathFFPaint(JNIEnv* env, jobject,
jlong canvasHandle, jstring text, jlong pathHandle,
- jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintHandle) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintHandle,
+ jlong typefaceHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+
const jchar* text_ = env->GetStringChars(text, NULL);
int count = env->GetStringLength(text);
- TextLayout::drawTextOnPath(paint, text_, count, bidiFlags, hOffset, vOffset,
- path, canvas);
+ doDrawTextOnPath(paint, text_, count, bidiFlags, hOffset, vOffset,
+ path, canvas, typeface);
env->ReleaseStringChars(text, text_);
}
@@ -1096,7 +1232,7 @@ static void doDrawTextDecorations(SkCanvas* canvas, jfloat x, jfloat y, jfloat l
static jboolean getClipBounds(JNIEnv* env, jobject, jlong canvasHandle,
jobject bounds) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
SkRect r;
SkIRect ir;
bool result = getHardClipBounds(canvas, &r);
@@ -1112,7 +1248,7 @@ static void doDrawTextDecorations(SkCanvas* canvas, jfloat x, jfloat y, jfloat l
static void getCTM(JNIEnv* env, jobject, jlong canvasHandle,
jlong matrixHandle) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
*matrix = canvas->getTotalMatrix();
}
@@ -1120,35 +1256,24 @@ static void doDrawTextDecorations(SkCanvas* canvas, jfloat x, jfloat y, jfloat l
static JNINativeMethod gCanvasMethods[] = {
{"finalizer", "(J)V", (void*) SkCanvasGlue::finalizer},
- {"initRaster","(J)J", (void*) SkCanvasGlue::initRaster},
- {"copyNativeCanvasState","(JJ)V", (void*) SkCanvasGlue::copyCanvasState},
- {"isOpaque","()Z", (void*) SkCanvasGlue::isOpaque},
- {"getWidth","()I", (void*) SkCanvasGlue::getWidth},
- {"getHeight","()I", (void*) SkCanvasGlue::getHeight},
- {"save","()I", (void*) SkCanvasGlue::saveAll},
- {"save","(I)I", (void*) SkCanvasGlue::save},
- {"native_saveLayer","(JLandroid/graphics/RectF;JI)I",
- (void*) SkCanvasGlue::saveLayer},
- {"native_saveLayer","(JFFFFJI)I", (void*) SkCanvasGlue::saveLayer4F},
- {"native_saveLayerAlpha","(JLandroid/graphics/RectF;II)I",
- (void*) SkCanvasGlue::saveLayerAlpha},
- {"native_saveLayerAlpha","(JFFFFII)I",
- (void*) SkCanvasGlue::saveLayerAlpha4F},
- {"restore","()V", (void*) SkCanvasGlue::restore},
- {"getSaveCount","()I", (void*) SkCanvasGlue::getSaveCount},
- {"restoreToCount","(I)V", (void*) SkCanvasGlue::restoreToCount},
- {"translate","(FF)V", (void*) SkCanvasGlue::translate},
- {"scale","(FF)V", (void*) SkCanvasGlue::scale__FF},
- {"rotate","(F)V", (void*) SkCanvasGlue::rotate__F},
- {"skew","(FF)V", (void*) SkCanvasGlue::skew__FF},
+ {"initRaster", "(J)J", (void*) SkCanvasGlue::initRaster},
+ {"initCanvas", "(J)J", (void*) SkCanvasGlue::initCanvas},
+ {"native_setBitmap", "(JJZ)V", (void*) SkCanvasGlue::setBitmap},
+ {"native_isOpaque","(J)Z", (void*) SkCanvasGlue::isOpaque},
+ {"native_getWidth","(J)I", (void*) SkCanvasGlue::getWidth},
+ {"native_getHeight","(J)I", (void*) SkCanvasGlue::getHeight},
+ {"native_save","(JI)I", (void*) SkCanvasGlue::save},
+ {"native_saveLayer","(JFFFFJI)I", (void*) SkCanvasGlue::saveLayer},
+ {"native_saveLayerAlpha","(JFFFFII)I", (void*) SkCanvasGlue::saveLayerAlpha},
+ {"native_restore","(J)V", (void*) SkCanvasGlue::restore},
+ {"native_getSaveCount","(J)I", (void*) SkCanvasGlue::getSaveCount},
+ {"native_restoreToCount","(JI)V", (void*) SkCanvasGlue::restoreToCount},
+ {"native_translate","(JFF)V", (void*) SkCanvasGlue::translate},
+ {"native_scale","(JFF)V", (void*) SkCanvasGlue::scale__FF},
+ {"native_rotate","(JF)V", (void*) SkCanvasGlue::rotate__F},
+ {"native_skew","(JFF)V", (void*) SkCanvasGlue::skew__FF},
{"native_concat","(JJ)V", (void*) SkCanvasGlue::concat},
{"native_setMatrix","(JJ)V", (void*) SkCanvasGlue::setMatrix},
- {"clipRect","(FFFF)Z", (void*) SkCanvasGlue::clipRect_FFFF},
- {"clipRect","(IIII)Z", (void*) SkCanvasGlue::clipRect_IIII},
- {"clipRect","(Landroid/graphics/RectF;)Z",
- (void*) SkCanvasGlue::clipRect_RectF},
- {"clipRect","(Landroid/graphics/Rect;)Z",
- (void*) SkCanvasGlue::clipRect_Rect},
{"native_clipRect","(JFFFFI)Z", (void*) SkCanvasGlue::clipRect},
{"native_clipPath","(JJI)Z", (void*) SkCanvasGlue::clipPath},
{"native_clipRegion","(JJI)Z", (void*) SkCanvasGlue::clipRegion},
@@ -1156,8 +1281,6 @@ static JNINativeMethod gCanvasMethods[] = {
{"native_getClipBounds","(JLandroid/graphics/Rect;)Z",
(void*) SkCanvasGlue::getClipBounds},
{"native_getCTM", "(JJ)V", (void*)SkCanvasGlue::getCTM},
- {"native_quickReject","(JLandroid/graphics/RectF;)Z",
- (void*) SkCanvasGlue::quickReject__RectF},
{"native_quickReject","(JJ)Z", (void*) SkCanvasGlue::quickReject__Path},
{"native_quickReject","(JFFFF)Z", (void*)SkCanvasGlue::quickReject__FFFF},
{"native_drawRGB","(JIII)V", (void*) SkCanvasGlue::drawRGB},
@@ -1165,21 +1288,14 @@ static JNINativeMethod gCanvasMethods[] = {
{"native_drawColor","(JI)V", (void*) SkCanvasGlue::drawColor__I},
{"native_drawColor","(JII)V", (void*) SkCanvasGlue::drawColor__II},
{"native_drawPaint","(JJ)V", (void*) SkCanvasGlue::drawPaint},
- {"drawPoint", "(FFLandroid/graphics/Paint;)V",
- (void*) SkCanvasGlue::drawPoint},
- {"drawPoints", "([FIILandroid/graphics/Paint;)V",
- (void*) SkCanvasGlue::drawPoints},
- {"drawLines", "([FIILandroid/graphics/Paint;)V",
- (void*) SkCanvasGlue::drawLines},
+ {"native_drawPoint", "(JFFJ)V", (void*) SkCanvasGlue::drawPoint},
+ {"native_drawPoints", "(J[FIIJ)V", (void*) SkCanvasGlue::drawPoints},
+ {"native_drawLines", "(J[FIIJ)V", (void*) SkCanvasGlue::drawLines},
{"native_drawLine","(JFFFFJ)V", (void*) SkCanvasGlue::drawLine__FFFFPaint},
- {"native_drawRect","(JLandroid/graphics/RectF;J)V",
- (void*) SkCanvasGlue::drawRect__RectFPaint},
{"native_drawRect","(JFFFFJ)V", (void*) SkCanvasGlue::drawRect__FFFFPaint},
- {"native_drawOval","(JLandroid/graphics/RectF;J)V",
- (void*) SkCanvasGlue::drawOval},
+ {"native_drawOval","(JFFFFJ)V", (void*) SkCanvasGlue::drawOval},
{"native_drawCircle","(JFFFJ)V", (void*) SkCanvasGlue::drawCircle},
- {"native_drawArc","(JLandroid/graphics/RectF;FFZJ)V",
- (void*) SkCanvasGlue::drawArc},
+ {"native_drawArc","(JFFFFFFZJ)V", (void*) SkCanvasGlue::drawArc},
{"native_drawRoundRect","(JFFFFFFJ)V",
(void*) SkCanvasGlue::drawRoundRect},
{"native_drawPath","(JJJ)V", (void*) SkCanvasGlue::drawPath},
@@ -1201,17 +1317,13 @@ static JNINativeMethod gCanvasMethods[] = {
(void*) SkCanvasGlue::drawText___CIIFFIPaintTypeface},
{"native_drawText","(JLjava/lang/String;IIFFIJJ)V",
(void*) SkCanvasGlue::drawText__StringIIFFIPaintTypeface},
- {"native_drawTextRun","(J[CIIIIFFIJJ)V",
- (void*) SkCanvasGlue::drawTextRun___CIIIIFFIPaintTypeface},
- {"native_drawTextRun","(JLjava/lang/String;IIIIFFIJJ)V",
- (void*) SkCanvasGlue::drawTextRun__StringIIIIFFIPaintTypeface},
- {"native_drawPosText","(J[CII[FJ)V",
- (void*) SkCanvasGlue::drawPosText___CII_FPaint},
- {"native_drawPosText","(JLjava/lang/String;[FJ)V",
- (void*) SkCanvasGlue::drawPosText__String_FPaint},
- {"native_drawTextOnPath","(J[CIIJFFIJ)V",
+ {"native_drawTextRun","(J[CIIIIFFZJJ)V",
+ (void*) SkCanvasGlue::drawTextRun___CIIIIFFZPaintTypeface},
+ {"native_drawTextRun","(JLjava/lang/String;IIIIFFZJJ)V",
+ (void*) SkCanvasGlue::drawTextRun__StringIIIIFFZPaintTypeface},
+ {"native_drawTextOnPath","(J[CIIJFFIJJ)V",
(void*) SkCanvasGlue::drawTextOnPath___CIIPathFFPaint},
- {"native_drawTextOnPath","(JLjava/lang/String;JFFIJ)V",
+ {"native_drawTextOnPath","(JLjava/lang/String;JFFIJJ)V",
(void*) SkCanvasGlue::drawTextOnPath__StringPathFFPaint},
{"freeCaches", "()V", (void*) SkCanvasGlue::freeCaches},
@@ -1236,4 +1348,11 @@ int register_android_graphics_Canvas(JNIEnv* env) {
return result;
}
+} // namespace android
+
+// GraphicsJNI helper for external clients.
+// We keep the implementation here to avoid exposing NativeCanvasWrapper
+// externally.
+SkCanvas* GraphicsJNI::getNativeCanvas(jlong nativeHandle) {
+ return android::SkCanvasGlue::getNativeCanvas(nativeHandle);
}
diff --git a/core/jni/android/graphics/DrawFilter.cpp b/core/jni/android/graphics/DrawFilter.cpp
index fbfa2ec..3275875 100644
--- a/core/jni/android/graphics/DrawFilter.cpp
+++ b/core/jni/android/graphics/DrawFilter.cpp
@@ -30,6 +30,35 @@
namespace android {
+// Custom version of SkPaintFlagsDrawFilter that also calls setFilterLevel.
+class CompatFlagsDrawFilter : public SkPaintFlagsDrawFilter {
+public:
+ CompatFlagsDrawFilter(uint32_t clearFlags, uint32_t setFlags,
+ SkPaint::FilterLevel desiredLevel)
+ : SkPaintFlagsDrawFilter(clearFlags, setFlags)
+ , fDesiredLevel(desiredLevel) {
+ }
+
+ virtual bool filter(SkPaint* paint, Type type) {
+ SkPaintFlagsDrawFilter::filter(paint, type);
+ paint->setFilterLevel(fDesiredLevel);
+ return true;
+ }
+
+private:
+ const SkPaint::FilterLevel fDesiredLevel;
+};
+
+// Returns whether flags contains FILTER_BITMAP_FLAG. If flags does, remove it.
+static inline bool hadFiltering(jint& flags) {
+ // Equivalent to the Java Paint's FILTER_BITMAP_FLAG.
+ static const uint32_t sFilterBitmapFlag = 0x02;
+
+ const bool result = (flags & sFilterBitmapFlag) != 0;
+ flags &= ~sFilterBitmapFlag;
+ return result;
+}
+
class SkDrawFilterGlue {
public:
@@ -40,12 +69,25 @@ public:
static jlong CreatePaintFlagsDF(JNIEnv* env, jobject clazz,
jint clearFlags, jint setFlags) {
- // trim off any out-of-range bits
- clearFlags &= SkPaint::kAllFlags;
- setFlags &= SkPaint::kAllFlags;
-
if (clearFlags | setFlags) {
- SkDrawFilter* filter = new SkPaintFlagsDrawFilter(clearFlags, setFlags);
+ // Mask both groups of flags to remove FILTER_BITMAP_FLAG, which no
+ // longer has a Skia equivalent flag (instead it corresponds to
+ // calling setFilterLevel), and keep track of which group(s), if
+ // any, had the flag set.
+ const bool turnFilteringOn = hadFiltering(setFlags);
+ const bool turnFilteringOff = hadFiltering(clearFlags);
+
+ SkDrawFilter* filter;
+ if (turnFilteringOn) {
+ // Turning filtering on overrides turning it off.
+ filter = new CompatFlagsDrawFilter(clearFlags, setFlags,
+ SkPaint::kLow_FilterLevel);
+ } else if (turnFilteringOff) {
+ filter = new CompatFlagsDrawFilter(clearFlags, setFlags,
+ SkPaint::kNone_FilterLevel);
+ } else {
+ filter = new SkPaintFlagsDrawFilter(clearFlags, setFlags);
+ }
return reinterpret_cast<jlong>(filter);
} else {
return NULL;
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index dce185d..2bd7a28 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -320,7 +320,7 @@ SkCanvas* GraphicsJNI::getNativeCanvas(JNIEnv* env, jobject canvas) {
SkASSERT(canvas);
SkASSERT(env->IsInstanceOf(canvas, gCanvas_class));
jlong canvasHandle = env->GetLongField(canvas, gCanvas_nativeInstanceID);
- SkCanvas* c = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* c = getNativeCanvas(canvasHandle);
SkASSERT(c);
return c;
}
@@ -345,17 +345,6 @@ android::TypefaceImpl* GraphicsJNI::getNativeTypeface(JNIEnv* env, jobject paint
return p;
}
-SkPicture* GraphicsJNI::getNativePicture(JNIEnv* env, jobject picture)
-{
- SkASSERT(env);
- SkASSERT(picture);
- SkASSERT(env->IsInstanceOf(picture, gPicture_class));
- jlong pictureHandle = env->GetLongField(picture, gPicture_nativeInstanceID);
- SkPicture* p = reinterpret_cast<SkPicture*>(pictureHandle);
- SkASSERT(p);
- return p;
-}
-
SkRegion* GraphicsJNI::getNativeRegion(JNIEnv* env, jobject region)
{
SkASSERT(env);
@@ -698,7 +687,7 @@ int register_android_graphics_Graphics(JNIEnv* env)
"nativeInt", "I");
gCanvas_class = make_globalref(env, "android/graphics/Canvas");
- gCanvas_nativeInstanceID = getFieldIDCheck(env, gCanvas_class, "mNativeCanvas", "J");
+ gCanvas_nativeInstanceID = getFieldIDCheck(env, gCanvas_class, "mNativeCanvasWrapper", "J");
gPaint_class = make_globalref(env, "android/graphics/Paint");
gPaint_nativeInstanceID = getFieldIDCheck(env, gPaint_class, "mNativePaint", "J");
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index db7b6d9..ad174f7 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -14,7 +14,6 @@
class SkBitmapRegionDecoder;
class SkCanvas;
class SkPaint;
-class SkPicture;
class GraphicsJNI {
public:
@@ -45,11 +44,11 @@ public:
static SkPoint* jpointf_to_point(JNIEnv*, jobject jpointf, SkPoint* point);
static void point_to_jpointf(const SkPoint& point, JNIEnv*, jobject jpointf);
+ static SkCanvas* getNativeCanvas(jlong nativeHandle);
static SkCanvas* getNativeCanvas(JNIEnv*, jobject canvas);
static SkPaint* getNativePaint(JNIEnv*, jobject paint);
static android::TypefaceImpl* getNativeTypeface(JNIEnv*, jobject paint);
static SkBitmap* getNativeBitmap(JNIEnv*, jobject bitmap);
- static SkPicture* getNativePicture(JNIEnv*, jobject picture);
static SkRegion* getNativeRegion(JNIEnv*, jobject region);
// Given the 'native' long held by the Rasterizer.java object, return a
diff --git a/core/jni/android/graphics/MaskFilter.cpp b/core/jni/android/graphics/MaskFilter.cpp
index 2113330..b394905 100644
--- a/core/jni/android/graphics/MaskFilter.cpp
+++ b/core/jni/android/graphics/MaskFilter.cpp
@@ -21,8 +21,7 @@ public:
static jlong createBlur(JNIEnv* env, jobject, jfloat radius, jint blurStyle) {
SkScalar sigma = SkBlurMask::ConvertRadiusToSigma(radius);
- SkMaskFilter* filter = SkBlurMaskFilter::Create(
- (SkBlurMaskFilter::BlurStyle)blurStyle, sigma);
+ SkMaskFilter* filter = SkBlurMaskFilter::Create((SkBlurStyle)blurStyle, sigma);
ThrowIAE_IfNull(env, filter);
return reinterpret_cast<jlong>(filter);
}
diff --git a/core/jni/android/graphics/MinikinUtils.cpp b/core/jni/android/graphics/MinikinUtils.cpp
index a9360ea..fc92d53 100644
--- a/core/jni/android/graphics/MinikinUtils.cpp
+++ b/core/jni/android/graphics/MinikinUtils.cpp
@@ -19,6 +19,7 @@
#include <string>
#include "SkPaint.h"
+#include "SkPathMeasure.h"
#include "minikin/Layout.h"
#include "TypefaceImpl.h"
#include "MinikinSkia.h"
@@ -76,4 +77,20 @@ float MinikinUtils::xOffsetForTextAlign(SkPaint* paint, const Layout& layout) {
return 0;
}
+float MinikinUtils::hOffsetForTextAlign(SkPaint* paint, const Layout& layout, const SkPath& path) {
+ float align = 0;
+ switch (paint->getTextAlign()) {
+ case SkPaint::kCenter_Align:
+ align = -0.5f;
+ break;
+ case SkPaint::kRight_Align:
+ align = -1;
+ break;
+ default:
+ return 0;
+ }
+ SkPathMeasure measure(path, false);
+ return align * (layout.getAdvance() - measure.getLength());
+}
+
}
diff --git a/core/jni/android/graphics/MinikinUtils.h b/core/jni/android/graphics/MinikinUtils.h
index a96c6b1..b2662a1 100644
--- a/core/jni/android/graphics/MinikinUtils.h
+++ b/core/jni/android/graphics/MinikinUtils.h
@@ -36,6 +36,7 @@ public:
static float xOffsetForTextAlign(SkPaint* paint, const Layout& layout);
+ static float hOffsetForTextAlign(SkPaint* paint, const Layout& layout, const SkPath& path);
// f is a functor of type void f(size_t start, size_t end);
template <typename F>
static void forFontRun(const Layout& layout, SkPaint* paint, F& f) {
diff --git a/core/jni/android/graphics/NinePatch.cpp b/core/jni/android/graphics/NinePatch.cpp
index 855d267..ab5bdb0 100644
--- a/core/jni/android/graphics/NinePatch.cpp
+++ b/core/jni/android/graphics/NinePatch.cpp
@@ -119,7 +119,7 @@ public:
static void drawF(JNIEnv* env, jobject, jlong canvasHandle, jobject boundsRectF,
jlong bitmapHandle, jlong chunkHandle, jlong paintHandle,
jint destDensity, jint srcDensity) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = GraphicsJNI::getNativeCanvas(canvasHandle);
const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
Res_png_9patch* chunk = reinterpret_cast<Res_png_9patch*>(chunkHandle);
const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
@@ -138,7 +138,7 @@ public:
static void drawI(JNIEnv* env, jobject, jlong canvasHandle, jobject boundsRect,
jlong bitmapHandle, jlong chunkHandle, jlong paintHandle,
jint destDensity, jint srcDensity) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ SkCanvas* canvas = GraphicsJNI::getNativeCanvas(canvasHandle);
const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
Res_png_9patch* chunk = reinterpret_cast<Res_png_9patch*>(chunkHandle);
const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 8b11d31..dc30814 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -37,6 +37,7 @@
#include "TextLayout.h"
#ifdef USE_MINIKIN
+#include <minikin/GraphemeBreak.h>
#include <minikin/Layout.h>
#include "MinikinSkia.h"
#include "MinikinUtils.h"
@@ -707,7 +708,7 @@ public:
}
static jfloat doTextRunAdvances(JNIEnv *env, SkPaint *paint, TypefaceImpl* typeface, const jchar *text,
- jint start, jint count, jint contextCount, jint flags,
+ jint start, jint count, jint contextCount, jboolean isRtl,
jfloatArray advances, jint advancesIndex) {
NPE_CHECK_RETURN_ZERO(env, paint);
NPE_CHECK_RETURN_ZERO(env, text);
@@ -729,14 +730,16 @@ public:
jfloat* advancesArray = new jfloat[count];
jfloat totalAdvance = 0;
+ int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
+
#ifdef USE_MINIKIN
Layout layout;
- std::string css = MinikinUtils::setLayoutProperties(&layout, paint, flags, typeface);
+ std::string css = MinikinUtils::setLayoutProperties(&layout, paint, bidiFlags, typeface);
layout.doLayout(text, start, count, contextCount, css);
layout.getAdvances(advancesArray);
totalAdvance = layout.getAdvance();
#else
- TextLayout::getTextRunAdvances(paint, text, start, count, contextCount, flags,
+ TextLayout::getTextRunAdvances(paint, text, start, count, contextCount, bidiFlags,
advancesArray, &totalAdvance);
#endif
@@ -747,28 +750,28 @@ public:
return totalAdvance;
}
- static jfloat getTextRunAdvances___CIIIII_FI(JNIEnv* env, jobject clazz, jlong paintHandle,
+ static jfloat getTextRunAdvances___CIIIIZ_FI(JNIEnv* env, jobject clazz, jlong paintHandle,
jlong typefaceHandle,
jcharArray text, jint index, jint count, jint contextIndex, jint contextCount,
- jint flags, jfloatArray advances, jint advancesIndex) {
+ jboolean isRtl, jfloatArray advances, jint advancesIndex) {
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
jchar* textArray = env->GetCharArrayElements(text, NULL);
jfloat result = doTextRunAdvances(env, paint, typeface, textArray + contextIndex,
- index - contextIndex, count, contextCount, flags, advances, advancesIndex);
+ index - contextIndex, count, contextCount, isRtl, advances, advancesIndex);
env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
return result;
}
- static jfloat getTextRunAdvances__StringIIIII_FI(JNIEnv* env, jobject clazz, jlong paintHandle,
+ static jfloat getTextRunAdvances__StringIIIIZ_FI(JNIEnv* env, jobject clazz, jlong paintHandle,
jlong typefaceHandle,
- jstring text, jint start, jint end, jint contextStart, jint contextEnd, jint flags,
+ jstring text, jint start, jint end, jint contextStart, jint contextEnd, jboolean isRtl,
jfloatArray advances, jint advancesIndex) {
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
const jchar* textArray = env->GetStringChars(text, NULL);
jfloat result = doTextRunAdvances(env, paint, typeface, textArray + contextStart,
- start - contextStart, end - start, contextEnd - contextStart, flags,
+ start - contextStart, end - start, contextEnd - contextStart, isRtl,
advances, advancesIndex);
env->ReleaseStringChars(text, textArray);
return result;
@@ -776,6 +779,11 @@ public:
static jint doTextRunCursor(JNIEnv *env, SkPaint* paint, const jchar *text, jint start,
jint count, jint flags, jint offset, jint opt) {
+#ifdef USE_MINIKIN
+ GraphemeBreak::MoveOpt moveOpt = GraphemeBreak::MoveOpt(opt);
+ size_t result = GraphemeBreak::getTextRunCursor(text, start, count, offset, moveOpt);
+ return static_cast<jint>(result);
+#else
jfloat scalarArray[count];
TextLayout::getTextRunAdvances(paint, text, start, count, start + count, flags,
@@ -816,24 +824,25 @@ public:
}
return pos;
+#endif
}
static jint getTextRunCursor___C(JNIEnv* env, jobject clazz, jlong paintHandle, jcharArray text,
- jint contextStart, jint contextCount, jint flags, jint offset, jint cursorOpt) {
+ jint contextStart, jint contextCount, jint dir, jint offset, jint cursorOpt) {
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
jchar* textArray = env->GetCharArrayElements(text, NULL);
- jint result = doTextRunCursor(env, paint, textArray, contextStart, contextCount, flags,
+ jint result = doTextRunCursor(env, paint, textArray, contextStart, contextCount, dir,
offset, cursorOpt);
env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
return result;
}
static jint getTextRunCursor__String(JNIEnv* env, jobject clazz, jlong paintHandle, jstring text,
- jint contextStart, jint contextEnd, jint flags, jint offset, jint cursorOpt) {
+ jint contextStart, jint contextEnd, jint dir, jint offset, jint cursorOpt) {
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
const jchar* textArray = env->GetStringChars(text, NULL);
jint result = doTextRunCursor(env, paint, textArray, contextStart,
- contextEnd - contextStart, flags, offset, cursorOpt);
+ contextEnd - contextStart, dir, offset, cursorOpt);
env->ReleaseStringChars(text, textArray);
return result;
}
@@ -934,32 +943,62 @@ public:
return paint->getLooper() && paint->getLooper()->asABlurShadow(NULL);
}
- static int breakText(JNIEnv* env, SkPaint& paint, const jchar text[],
+ static int breakText(JNIEnv* env, const SkPaint& paint, TypefaceImpl* typeface, const jchar text[],
int count, float maxWidth, jint bidiFlags, jfloatArray jmeasured,
- SkPaint::TextBufferDirection tbd) {
+ SkPaint::TextBufferDirection textBufferDirection) {
+ size_t measuredCount = 0;
+ float measured = 0;
+
+#ifdef USE_MINIKIN
+ Layout layout;
+ std::string css = MinikinUtils::setLayoutProperties(&layout, &paint, bidiFlags, typeface);
+ layout.doLayout(text, 0, count, count, css);
+ float* advances = new float[count];
+ layout.getAdvances(advances);
+ const bool forwardScan = (textBufferDirection == SkPaint::kForward_TextBufferDirection);
+ for (int i = 0; i < count; i++) {
+ // traverse in the given direction
+ int index = forwardScan ? i : (count - i - 1);
+ float width = advances[index];
+ if (measured + width > maxWidth) {
+ break;
+ }
+ // properly handle clusters when scanning backwards
+ if (forwardScan || width != 0.0f) {
+ measuredCount = i + 1;
+ }
+ measured += width;
+ }
+ delete[] advances;
+#else
sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(&paint,
text, 0, count, count, bidiFlags);
if (value == NULL) {
return 0;
}
- SkScalar measured;
- size_t bytes = paint.breakText(value->getGlyphs(), value->getGlyphsCount() << 1,
- maxWidth, &measured, tbd);
+ SkScalar m;
+ size_t bytes = paint.breakText(value->getGlyphs(), value->getGlyphsCount() << 1,
+ maxWidth, &m, textBufferDirection);
SkASSERT((bytes & 1) == 0);
+ measuredCount = bytes >> 1;
+ measured = SkScalarToFloat(m);
+#endif
if (jmeasured && env->GetArrayLength(jmeasured) > 0) {
AutoJavaFloatArray autoMeasured(env, jmeasured, 1);
jfloat* array = autoMeasured.ptr();
- array[0] = SkScalarToFloat(measured);
+ array[0] = measured;
}
- return bytes >> 1;
+ return measuredCount;
}
- static jint breakTextC(JNIEnv* env, jobject jpaint, jcharArray jtext,
+ static jint breakTextC(JNIEnv* env, jobject clazz, jlong paintHandle, jlong typefaceHandle, jcharArray jtext,
jint index, jint count, jfloat maxWidth, jint bidiFlags, jfloatArray jmeasuredWidth) {
- NPE_CHECK_RETURN_ZERO(env, jpaint);
NPE_CHECK_RETURN_ZERO(env, jtext);
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+
SkPaint::TextBufferDirection tbd;
if (count < 0) {
tbd = SkPaint::kBackward_TextBufferDirection;
@@ -974,28 +1013,28 @@ public:
return 0;
}
- SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
const jchar* text = env->GetCharArrayElements(jtext, NULL);
- count = breakText(env, *paint, text + index, count, maxWidth,
+ count = breakText(env, *paint, typeface, text + index, count, maxWidth,
bidiFlags, jmeasuredWidth, tbd);
env->ReleaseCharArrayElements(jtext, const_cast<jchar*>(text),
JNI_ABORT);
return count;
}
- static jint breakTextS(JNIEnv* env, jobject jpaint, jstring jtext,
+ static jint breakTextS(JNIEnv* env, jobject clazz, jlong paintHandle, jlong typefaceHandle, jstring jtext,
jboolean forwards, jfloat maxWidth, jint bidiFlags, jfloatArray jmeasuredWidth) {
- NPE_CHECK_RETURN_ZERO(env, jpaint);
NPE_CHECK_RETURN_ZERO(env, jtext);
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+
SkPaint::TextBufferDirection tbd = forwards ?
SkPaint::kForward_TextBufferDirection :
SkPaint::kBackward_TextBufferDirection;
- SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
int count = env->GetStringLength(jtext);
const jchar* text = env->GetStringChars(jtext, NULL);
- count = breakText(env, *paint, text, count, maxWidth, bidiFlags, jmeasuredWidth, tbd);
+ count = breakText(env, *paint, typeface, text, count, maxWidth, bidiFlags, jmeasuredWidth, tbd);
env->ReleaseStringChars(jtext, text);
return count;
}
@@ -1106,14 +1145,14 @@ static JNINativeMethod methods[] = {
{"native_measureText","([CIII)F", (void*) SkPaintGlue::measureText_CIII},
{"native_measureText","(Ljava/lang/String;I)F", (void*) SkPaintGlue::measureText_StringI},
{"native_measureText","(Ljava/lang/String;III)F", (void*) SkPaintGlue::measureText_StringIII},
- {"native_breakText","([CIIFI[F)I", (void*) SkPaintGlue::breakTextC},
- {"native_breakText","(Ljava/lang/String;ZFI[F)I", (void*) SkPaintGlue::breakTextS},
+ {"native_breakText","(JJ[CIIFI[F)I", (void*) SkPaintGlue::breakTextC},
+ {"native_breakText","(JJLjava/lang/String;ZFI[F)I", (void*) SkPaintGlue::breakTextS},
{"native_getTextWidths","(JJ[CIII[F)I", (void*) SkPaintGlue::getTextWidths___CIII_F},
{"native_getTextWidths","(JJLjava/lang/String;III[F)I", (void*) SkPaintGlue::getTextWidths__StringIII_F},
- {"native_getTextRunAdvances","(JJ[CIIIII[FI)F",
- (void*) SkPaintGlue::getTextRunAdvances___CIIIII_FI},
- {"native_getTextRunAdvances","(JJLjava/lang/String;IIIII[FI)F",
- (void*) SkPaintGlue::getTextRunAdvances__StringIIIII_FI},
+ {"native_getTextRunAdvances","(JJ[CIIIIZ[FI)F",
+ (void*) SkPaintGlue::getTextRunAdvances___CIIIIZ_FI},
+ {"native_getTextRunAdvances","(JJLjava/lang/String;IIIIZ[FI)F",
+ (void*) SkPaintGlue::getTextRunAdvances__StringIIIIZ_FI},
{"native_getTextGlyphs","(JLjava/lang/String;IIIII[C)I",
diff --git a/core/jni/android/graphics/Path.cpp b/core/jni/android/graphics/Path.cpp
index 420a17f..6ef1d2c 100644
--- a/core/jni/android/graphics/Path.cpp
+++ b/core/jni/android/graphics/Path.cpp
@@ -2,22 +2,22 @@
**
** Copyright 2006, The Android Open Source Project
**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
**
-** http://www.apache.org/licenses/LICENSE-2.0
+** http://www.apache.org/licenses/LICENSE-2.0
**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
** limitations under the License.
*/
// This file was generated from the C++ include file: SkPath.h
// Any changes made to this file will be discarded by the build.
-// To change this file, either edit the include, or device/tools/gluemaker/main.cpp,
+// To change this file, either edit the include, or device/tools/gluemaker/main.cpp,
// or one of the auxilary file specifications in device/tools/gluemaker.
#include "jni.h"
@@ -92,7 +92,7 @@ public:
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
return obj->isEmpty();
}
-
+
static jboolean isRect(JNIEnv* env, jobject clazz, jlong objHandle, jobject jrect) {
SkRect rect;
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
@@ -100,65 +100,66 @@ public:
GraphicsJNI::rect_to_jrectf(rect, env, jrect);
return result;
}
-
+
static void computeBounds(JNIEnv* env, jobject clazz, jlong objHandle, jobject jbounds) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
const SkRect& bounds = obj->getBounds();
GraphicsJNI::rect_to_jrectf(bounds, env, jbounds);
}
-
+
static void incReserve(JNIEnv* env, jobject clazz, jlong objHandle, jint extraPtCount) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
obj->incReserve(extraPtCount);
}
-
+
static void moveTo__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x, jfloat y) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
obj->moveTo(x, y);
}
-
+
static void rMoveTo(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
obj->rMoveTo(dx, dy);
}
-
+
static void lineTo__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x, jfloat y) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
obj->lineTo(x, y);
}
-
+
static void rLineTo(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
obj->rLineTo(dx, dy);
}
-
+
static void quadTo__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x1, jfloat y1, jfloat x2, jfloat y2) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
obj->quadTo(x1, y1, x2, y2);
}
-
+
static void rQuadTo(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx1, jfloat dy1, jfloat dx2, jfloat dy2) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
obj->rQuadTo(dx1, dy1, dx2, dy2);
}
-
+
static void cubicTo__FFFFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x1, jfloat y1, jfloat x2, jfloat y2, jfloat x3, jfloat y3) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
obj->cubicTo(x1, y1, x2, y2, x3, y3);
}
-
+
static void rCubicTo(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x1, jfloat y1, jfloat x2, jfloat y2, jfloat x3, jfloat y3) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
obj->rCubicTo(x1, y1, x2, y2, x3, y3);
}
-
- static void arcTo(JNIEnv* env, jobject clazz, jlong objHandle, jobject oval, jfloat startAngle, jfloat sweepAngle, jboolean forceMoveTo) {
+
+ static void arcTo(JNIEnv* env, jobject clazz, jlong objHandle, jfloat left, jfloat top,
+ jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle,
+ jboolean forceMoveTo) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
- SkRect oval_;
- GraphicsJNI::jrectf_to_rect(env, oval, &oval_);
- obj->arcTo(oval_, startAngle, sweepAngle, forceMoveTo);
+ SkRect oval = SkRect::MakeLTRB(left, top, right, bottom);
+ obj->arcTo(oval, startAngle, sweepAngle, forceMoveTo);
}
-
+
static void close(JNIEnv* env, jobject clazz, jlong objHandle) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
obj->close();
@@ -185,28 +186,26 @@ public:
obj->addCircle(x, y, radius, dir);
}
- static void addArc(JNIEnv* env, jobject clazz, jlong objHandle, jobject oval, jfloat startAngle, jfloat sweepAngle) {
- SkRect oval_;
+ static void addArc(JNIEnv* env, jobject clazz, jlong objHandle, jfloat left, jfloat top,
+ jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle) {
+ SkRect oval = SkRect::MakeLTRB(left, top, right, bottom);
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
- GraphicsJNI::jrectf_to_rect(env, oval, &oval_);
- obj->addArc(oval_, startAngle, sweepAngle);
+ obj->addArc(oval, startAngle, sweepAngle);
}
- static void addRoundRectXY(JNIEnv* env, jobject clazz, jlong objHandle, jobject jrect,
- jfloat rx, jfloat ry, jint dirHandle) {
- SkRect rect;
+ static void addRoundRectXY(JNIEnv* env, jobject clazz, jlong objHandle, jfloat left, jfloat top,
+ jfloat right, jfloat bottom, jfloat rx, jfloat ry, jint dirHandle) {
+ SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle);
- GraphicsJNI::jrectf_to_rect(env, jrect, &rect);
obj->addRoundRect(rect, rx, ry, dir);
}
-
- static void addRoundRect8(JNIEnv* env, jobject, jlong objHandle, jobject jrect,
- jfloatArray array, jint dirHandle) {
- SkRect rect;
+
+ static void addRoundRect8(JNIEnv* env, jobject, jlong objHandle, jfloat left, jfloat top,
+ jfloat right, jfloat bottom, jfloatArray array, jint dirHandle) {
+ SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle);
- GraphicsJNI::jrectf_to_rect(env, jrect, &rect);
AutoJavaFloatArray afa(env, array, 8);
#ifdef SK_SCALAR_IS_FLOAT
const float* src = afa.ptr();
@@ -215,32 +214,32 @@ public:
#endif
obj->addRoundRect(rect, src, dir);
}
-
+
static void addPath__PathFF(JNIEnv* env, jobject clazz, jlong objHandle, jlong srcHandle, jfloat dx, jfloat dy) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
SkPath* src = reinterpret_cast<SkPath*>(srcHandle);
obj->addPath(*src, dx, dy);
}
-
+
static void addPath__Path(JNIEnv* env, jobject clazz, jlong objHandle, jlong srcHandle) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
SkPath* src = reinterpret_cast<SkPath*>(srcHandle);
obj->addPath(*src);
}
-
+
static void addPath__PathMatrix(JNIEnv* env, jobject clazz, jlong objHandle, jlong srcHandle, jlong matrixHandle) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
SkPath* src = reinterpret_cast<SkPath*>(srcHandle);
SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
obj->addPath(*src, *matrix);
}
-
+
static void offset__FFPath(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy, jlong dstHandle) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
SkPath* dst = reinterpret_cast<SkPath*>(dstHandle);
obj->offset(dx, dy, dst);
}
-
+
static void offset__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
obj->offset(dx, dy);
@@ -250,14 +249,14 @@ public:
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
obj->setLastPt(dx, dy);
}
-
+
static void transform__MatrixPath(JNIEnv* env, jobject clazz, jlong objHandle, jlong matrixHandle, jlong dstHandle) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
SkPath* dst = reinterpret_cast<SkPath*>(dstHandle);
obj->transform(*matrix, dst);
}
-
+
static void transform__Matrix(JNIEnv* env, jobject clazz, jlong objHandle, jlong matrixHandle) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
@@ -487,14 +486,14 @@ static JNINativeMethod methods[] = {
{"native_rQuadTo","(JFFFF)V", (void*) SkPathGlue::rQuadTo},
{"native_cubicTo","(JFFFFFF)V", (void*) SkPathGlue::cubicTo__FFFFFF},
{"native_rCubicTo","(JFFFFFF)V", (void*) SkPathGlue::rCubicTo},
- {"native_arcTo","(JLandroid/graphics/RectF;FFZ)V", (void*) SkPathGlue::arcTo},
+ {"native_arcTo","(JFFFFFFZ)V", (void*) SkPathGlue::arcTo},
{"native_close","(J)V", (void*) SkPathGlue::close},
{"native_addRect","(JFFFFI)V", (void*) SkPathGlue::addRect},
{"native_addOval","(JFFFFI)V", (void*) SkPathGlue::addOval},
{"native_addCircle","(JFFFI)V", (void*) SkPathGlue::addCircle},
- {"native_addArc","(JLandroid/graphics/RectF;FF)V", (void*) SkPathGlue::addArc},
- {"native_addRoundRect","(JLandroid/graphics/RectF;FFI)V", (void*) SkPathGlue::addRoundRectXY},
- {"native_addRoundRect","(JLandroid/graphics/RectF;[FI)V", (void*) SkPathGlue::addRoundRect8},
+ {"native_addArc","(JFFFFFF)V", (void*) SkPathGlue::addArc},
+ {"native_addRoundRect","(JFFFFFFI)V", (void*) SkPathGlue::addRoundRectXY},
+ {"native_addRoundRect","(JFFFF[FI)V", (void*) SkPathGlue::addRoundRect8},
{"native_addPath","(JJFF)V", (void*) SkPathGlue::addPath__PathFF},
{"native_addPath","(JJ)V", (void*) SkPathGlue::addPath__Path},
{"native_addPath","(JJJ)V", (void*) SkPathGlue::addPath__PathMatrix},
diff --git a/core/jni/android/graphics/Picture.cpp b/core/jni/android/graphics/Picture.cpp
index bac8ef7..bc0c25f 100644
--- a/core/jni/android/graphics/Picture.cpp
+++ b/core/jni/android/graphics/Picture.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,125 +14,104 @@
* limitations under the License.
*/
-#include "jni.h"
-#include "GraphicsJNI.h"
-#include <android_runtime/AndroidRuntime.h>
+#include "Picture.h"
#include "SkCanvas.h"
-#include "SkPicture.h"
#include "SkStream.h"
-#include "SkTemplates.h"
-#include "CreateJavaOutputStreamAdaptor.h"
namespace android {
-class SkPictureGlue {
-public:
- static jlong newPicture(JNIEnv* env, jobject, jlong srcHandle) {
- const SkPicture* src = reinterpret_cast<SkPicture*>(srcHandle);
- if (src) {
- return reinterpret_cast<jlong>(new SkPicture(*src));
- } else {
- return reinterpret_cast<jlong>(new SkPicture);
+Picture::Picture(const Picture* src) {
+ if (NULL != src) {
+ mWidth = src->width();
+ mHeight = src->height();
+ if (NULL != src->mPicture.get()) {
+ mPicture.reset(SkRef(src->mPicture.get()));
+ } if (NULL != src->mRecorder.get()) {
+ mPicture.reset(src->makePartialCopy());
}
+ } else {
+ mWidth = 0;
+ mHeight = 0;
}
+}
- static jlong deserialize(JNIEnv* env, jobject, jobject jstream,
- jbyteArray jstorage) {
- SkPicture* picture = NULL;
- SkStream* strm = CreateJavaInputStreamAdaptor(env, jstream, jstorage);
- if (strm) {
- picture = SkPicture::CreateFromStream(strm);
- delete strm;
- }
- return reinterpret_cast<jlong>(picture);
- }
+SkCanvas* Picture::beginRecording(int width, int height) {
+ mPicture.reset(NULL);
+ mRecorder.reset(new SkPictureRecorder);
+ mWidth = width;
+ mHeight = height;
+ return mRecorder->beginRecording(width, height, NULL, 0);
+}
- static void killPicture(JNIEnv* env, jobject, jlong pictureHandle) {
- SkPicture* picture = reinterpret_cast<SkPicture*>(pictureHandle);
- SkASSERT(picture);
- picture->unref();
+void Picture::endRecording() {
+ if (NULL != mRecorder.get()) {
+ mPicture.reset(mRecorder->endRecording());
+ mRecorder.reset(NULL);
}
+}
- static void draw(JNIEnv* env, jobject, jlong canvasHandle,
- jlong pictureHandle) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
- SkPicture* picture = reinterpret_cast<SkPicture*>(pictureHandle);
- SkASSERT(canvas);
- SkASSERT(picture);
- picture->draw(canvas);
+int Picture::width() const {
+ if (NULL != mPicture.get()) {
+ SkASSERT(mPicture->width() == mWidth);
+ SkASSERT(mPicture->height() == mHeight);
}
- static jboolean serialize(JNIEnv* env, jobject, jlong pictureHandle,
- jobject jstream, jbyteArray jstorage) {
- SkPicture* picture = reinterpret_cast<SkPicture*>(pictureHandle);
- SkWStream* strm = CreateJavaOutputStreamAdaptor(env, jstream, jstorage);
-
- if (NULL != strm) {
- picture->serialize(strm);
- delete strm;
- return JNI_TRUE;
- }
- return JNI_FALSE;
- }
+ return mWidth;
+}
- static jint getWidth(JNIEnv* env, jobject jpic) {
- NPE_CHECK_RETURN_ZERO(env, jpic);
- int width = GraphicsJNI::getNativePicture(env, jpic)->width();
- return static_cast<jint>(width);
+int Picture::height() const {
+ if (NULL != mPicture.get()) {
+ SkASSERT(mPicture->width() == mWidth);
+ SkASSERT(mPicture->height() == mHeight);
}
- static jint getHeight(JNIEnv* env, jobject jpic) {
- NPE_CHECK_RETURN_ZERO(env, jpic);
- int height = GraphicsJNI::getNativePicture(env, jpic)->height();
- return static_cast<jint>(height);
- }
+ return mHeight;
+}
- static jlong beginRecording(JNIEnv* env, jobject, jlong pictHandle,
- jint w, jint h) {
- SkPicture* pict = reinterpret_cast<SkPicture*>(pictHandle);
- // beginRecording does not ref its return value, it just returns it.
- SkCanvas* canvas = pict->beginRecording(w, h);
- // the java side will wrap this guy in a Canvas.java, which will call
- // unref in its finalizer, so we have to ref it here, so that both that
- // Canvas.java and our picture can both be owners
- canvas->ref();
- return reinterpret_cast<jlong>(canvas);
- }
+Picture* Picture::CreateFromStream(SkStream* stream) {
+ Picture* newPict = new Picture;
- static void endRecording(JNIEnv* env, jobject, jlong pictHandle) {
- SkPicture* pict = reinterpret_cast<SkPicture*>(pictHandle);
- pict->endRecording();
+ newPict->mPicture.reset(SkPicture::CreateFromStream(stream));
+ if (NULL != newPict->mPicture.get()) {
+ newPict->mWidth = newPict->mPicture->width();
+ newPict->mHeight = newPict->mPicture->height();
}
-};
-
-static JNINativeMethod gPictureMethods[] = {
- {"getWidth", "()I", (void*) SkPictureGlue::getWidth},
- {"getHeight", "()I", (void*) SkPictureGlue::getHeight},
- {"nativeConstructor", "(J)J", (void*) SkPictureGlue::newPicture},
- {"nativeCreateFromStream", "(Ljava/io/InputStream;[B)J", (void*)SkPictureGlue::deserialize},
- {"nativeBeginRecording", "(JII)J", (void*) SkPictureGlue::beginRecording},
- {"nativeEndRecording", "(J)V", (void*) SkPictureGlue::endRecording},
- {"nativeDraw", "(JJ)V", (void*) SkPictureGlue::draw},
- {"nativeWriteToStream", "(JLjava/io/OutputStream;[B)Z", (void*)SkPictureGlue::serialize},
- {"nativeDestructor","(J)V", (void*) SkPictureGlue::killPicture}
-};
-#include <android_runtime/AndroidRuntime.h>
+ return newPict;
+}
-#define REG(env, name, array) \
- result = android::AndroidRuntime::registerNativeMethods(env, name, array, \
- SK_ARRAY_COUNT(array)); \
- if (result < 0) return result
+void Picture::serialize(SkWStream* stream) const {
+ if (NULL != mRecorder.get()) {
+ SkAutoTDelete<SkPicture> tempPict(this->makePartialCopy());
+ tempPict->serialize(stream);
+ } else if (NULL != mPicture.get()) {
+ mPicture->serialize(stream);
+ } else {
+ SkPicture empty;
+ empty.serialize(stream);
+ }
+}
-int register_android_graphics_Picture(JNIEnv* env) {
- int result;
+void Picture::draw(SkCanvas* canvas) {
+ if (NULL != mRecorder.get()) {
+ this->endRecording();
+ SkASSERT(NULL != mPicture.get());
+ }
+ if (NULL != mPicture.get()) {
+ // TODO: remove this const_cast once pictures are immutable
+ const_cast<SkPicture*>(mPicture.get())->draw(canvas);
+ }
+}
- REG(env, "android/graphics/Picture", gPictureMethods);
+SkPicture* Picture::makePartialCopy() const {
+ SkASSERT(NULL != mRecorder.get());
- return result;
-}
+ SkPictureRecorder reRecorder;
+ SkCanvas* canvas = reRecorder.beginRecording(mWidth, mHeight, NULL, 0);
+ mRecorder->partialReplay(canvas);
+ return reRecorder.endRecording();
}
-
+}; // namespace android
diff --git a/core/jni/android/graphics/Picture.h b/core/jni/android/graphics/Picture.h
new file mode 100644
index 0000000..abb0403
--- /dev/null
+++ b/core/jni/android/graphics/Picture.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_GRAPHICS_PICTURE_H
+#define ANDROID_GRAPHICS_PICTURE_H
+
+#include "SkPicture.h"
+#include "SkPictureRecorder.h"
+#include "SkRefCnt.h"
+#include "SkTemplates.h"
+
+class SkCanvas;
+class SkPicture;
+class SkPictureRecorder;
+class SkStream;
+class SkWStream;
+
+namespace android {
+
+// Skia's SkPicture class has been split into an SkPictureRecorder
+// and an SkPicture. AndroidPicture recreates the functionality
+// of the old SkPicture interface by flip-flopping between the two
+// new classes.
+class Picture {
+public:
+ explicit Picture(const Picture* src = NULL);
+
+ SkCanvas* beginRecording(int width, int height);
+
+ void endRecording();
+
+ int width() const;
+
+ int height() const;
+
+ static Picture* CreateFromStream(SkStream* stream);
+
+ void serialize(SkWStream* stream) const;
+
+ void draw(SkCanvas* canvas);
+
+private:
+ int mWidth;
+ int mHeight;
+ SkAutoTUnref<const SkPicture> mPicture;
+ SkAutoTDelete<SkPictureRecorder> mRecorder;
+
+ // Make a copy of a picture that is in the midst of being recorded. The
+ // resulting picture will have balanced saves and restores.
+ SkPicture* makePartialCopy() const;
+};
+
+}; // namespace android
+#endif // ANDROID_GRAPHICS_PICTURE_H
diff --git a/core/jni/android/graphics/pdf/PdfDocument.cpp b/core/jni/android/graphics/pdf/PdfDocument.cpp
index d54aaa8..3812c27 100644
--- a/core/jni/android/graphics/pdf/PdfDocument.cpp
+++ b/core/jni/android/graphics/pdf/PdfDocument.cpp
@@ -24,6 +24,7 @@
#include "SkCanvas.h"
#include "SkDocument.h"
#include "SkPicture.h"
+#include "SkPictureRecorder.h"
#include "SkStream.h"
#include "SkRect.h"
@@ -32,15 +33,22 @@ namespace android {
struct PageRecord {
PageRecord(int width, int height, const SkRect& contentRect)
- : mPicture(new SkPicture()), mWidth(width), mHeight(height) {
+ : mPictureRecorder(new SkPictureRecorder())
+ , mPicture(NULL)
+ , mWidth(width)
+ , mHeight(height) {
mContentRect = contentRect;
}
~PageRecord() {
- mPicture->unref();
+ delete mPictureRecorder;
+ if (NULL != mPicture) {
+ mPicture->unref();
+ }
}
- SkPicture* const mPicture;
+ SkPictureRecorder* mPictureRecorder;
+ SkPicture* mPicture;
const int mWidth;
const int mHeight;
SkRect mContentRect;
@@ -62,8 +70,8 @@ public:
mPages.push_back(page);
mCurrentPage = page;
- SkCanvas* canvas = page->mPicture->beginRecording(
- contentRect.width(), contentRect.height(), 0);
+ SkCanvas* canvas = page->mPictureRecorder->beginRecording(
+ contentRect.width(), contentRect.height(), NULL, 0);
// We pass this canvas to Java where it is used to construct
// a Java Canvas object which dereferences the pointer when it
@@ -75,7 +83,11 @@ public:
void finishPage() {
assert(mCurrentPage != NULL);
- mCurrentPage->mPicture->endRecording();
+ assert(mCurrentPage->mPictureRecorder != NULL);
+ assert(mCurrentPage->mPicture == NULL);
+ mCurrentPage->mPicture = mCurrentPage->mPictureRecorder->endRecording();
+ delete mCurrentPage->mPictureRecorder;
+ mCurrentPage->mPictureRecorder = NULL;
mCurrentPage = NULL;
}
@@ -89,7 +101,7 @@ public:
canvas->clipRect(page->mContentRect);
canvas->translate(page->mContentRect.left(), page->mContentRect.top());
- canvas->drawPicture(*page->mPicture);
+ canvas->drawPicture(page->mPicture);
document->endPage();
}
@@ -97,11 +109,10 @@ public:
}
void close() {
+ assert(NULL == mCurrentPage);
for (unsigned i = 0; i < mPages.size(); i++) {
delete mPages[i];
}
- delete mCurrentPage;
- mCurrentPage = NULL;
}
private:
diff --git a/core/jni/android_graphics_Picture.cpp b/core/jni/android_graphics_Picture.cpp
new file mode 100644
index 0000000..f827907
--- /dev/null
+++ b/core/jni/android_graphics_Picture.cpp
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "jni.h"
+#include "GraphicsJNI.h"
+#include <android_runtime/AndroidRuntime.h>
+
+#include "Picture.h"
+
+#include "SkCanvas.h"
+#include "SkStream.h"
+#include "SkTemplates.h"
+#include "CreateJavaOutputStreamAdaptor.h"
+
+namespace android {
+
+static jlong android_graphics_Picture_newPicture(JNIEnv* env, jobject, jlong srcHandle) {
+ const Picture* src = reinterpret_cast<Picture*>(srcHandle);
+ return reinterpret_cast<jlong>(new Picture(src));
+}
+
+static jlong android_graphics_Picture_deserialize(JNIEnv* env, jobject, jobject jstream,
+ jbyteArray jstorage) {
+ Picture* picture = NULL;
+ SkStream* strm = CreateJavaInputStreamAdaptor(env, jstream, jstorage);
+ if (strm) {
+ picture = Picture::CreateFromStream(strm);
+ delete strm;
+ }
+ return reinterpret_cast<jlong>(picture);
+}
+
+static void android_graphics_Picture_killPicture(JNIEnv* env, jobject, jlong pictureHandle) {
+ Picture* picture = reinterpret_cast<Picture*>(pictureHandle);
+ SkASSERT(picture);
+ delete picture;
+}
+
+static void android_graphics_Picture_draw(JNIEnv* env, jobject, jlong canvasHandle,
+ jlong pictureHandle) {
+ SkCanvas* canvas = GraphicsJNI::getNativeCanvas(canvasHandle);
+ Picture* picture = reinterpret_cast<Picture*>(pictureHandle);
+ SkASSERT(canvas);
+ SkASSERT(picture);
+ picture->draw(canvas);
+}
+
+static jboolean android_graphics_Picture_serialize(JNIEnv* env, jobject, jlong pictureHandle,
+ jobject jstream, jbyteArray jstorage) {
+ Picture* picture = reinterpret_cast<Picture*>(pictureHandle);
+ SkWStream* strm = CreateJavaOutputStreamAdaptor(env, jstream, jstorage);
+
+ if (NULL != strm) {
+ picture->serialize(strm);
+ delete strm;
+ return JNI_TRUE;
+ }
+ return JNI_FALSE;
+}
+
+static jint android_graphics_Picture_getWidth(JNIEnv* env, jobject, jlong pictureHandle) {
+ Picture* pict = reinterpret_cast<Picture*>(pictureHandle);
+ return static_cast<jint>(pict->width());
+}
+
+static jint android_graphics_Picture_getHeight(JNIEnv* env, jobject, jlong pictureHandle) {
+ Picture* pict = reinterpret_cast<Picture*>(pictureHandle);
+ return static_cast<jint>(pict->height());
+}
+
+static jlong android_graphics_Picture_beginRecording(JNIEnv* env, jobject, jlong pictHandle,
+ jint w, jint h) {
+ Picture* pict = reinterpret_cast<Picture*>(pictHandle);
+ // beginRecording does not ref its return value, it just returns it.
+ SkCanvas* canvas = pict->beginRecording(w, h);
+ // the java side will wrap this guy in a Canvas.java, which will call
+ // unref in its finalizer, so we have to ref it here, so that both that
+ // Canvas.java and our picture can both be owners
+ canvas->ref();
+ return reinterpret_cast<jlong>(canvas);
+}
+
+static void android_graphics_Picture_endRecording(JNIEnv* env, jobject, jlong pictHandle) {
+ Picture* pict = reinterpret_cast<Picture*>(pictHandle);
+ pict->endRecording();
+}
+
+static JNINativeMethod gMethods[] = {
+ {"nativeGetWidth", "(J)I", (void*) android_graphics_Picture_getWidth},
+ {"nativeGetHeight", "(J)I", (void*) android_graphics_Picture_getHeight},
+ {"nativeConstructor", "(J)J", (void*) android_graphics_Picture_newPicture},
+ {"nativeCreateFromStream", "(Ljava/io/InputStream;[B)J", (void*)android_graphics_Picture_deserialize},
+ {"nativeBeginRecording", "(JII)J", (void*) android_graphics_Picture_beginRecording},
+ {"nativeEndRecording", "(J)V", (void*) android_graphics_Picture_endRecording},
+ {"nativeDraw", "(JJ)V", (void*) android_graphics_Picture_draw},
+ {"nativeWriteToStream", "(JLjava/io/OutputStream;[B)Z", (void*)android_graphics_Picture_serialize},
+ {"nativeDestructor","(J)V", (void*) android_graphics_Picture_killPicture}
+};
+
+int register_android_graphics_Picture(JNIEnv* env) {
+ return AndroidRuntime::registerNativeMethods(env, "android/graphics/Picture", gMethods, NELEM(gMethods));
+}
+
+}; // namespace android
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 3a53331..f8bab24 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -36,6 +36,11 @@
using namespace android;
+enum {
+ // Keep up to date with Camera.java
+ CAMERA_HAL_API_VERSION_NORMAL_CONNECT = -2,
+};
+
struct fields_t {
jfieldID context;
jfieldID facing;
@@ -466,7 +471,7 @@ static void android_hardware_Camera_getCameraInfo(JNIEnv *env, jobject thiz,
// connect to camera service
static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
- jobject weak_this, jint cameraId, jstring clientPackageName)
+ jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName)
{
// Convert jstring to String16
const char16_t *rawClientName = env->GetStringChars(clientPackageName, NULL);
@@ -474,8 +479,18 @@ static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
String16 clientName(rawClientName, rawClientNameLen);
env->ReleaseStringChars(clientPackageName, rawClientName);
- sp<Camera> camera = Camera::connect(cameraId, clientName,
- Camera::USE_CALLING_UID);
+ sp<Camera> camera;
+ if (halVersion == CAMERA_HAL_API_VERSION_NORMAL_CONNECT) {
+ // Default path: hal version is don't care, do normal camera connect.
+ camera = Camera::connect(cameraId, clientName,
+ Camera::USE_CALLING_UID);
+ } else {
+ jint status = Camera::connectLegacy(cameraId, halVersion, clientName,
+ Camera::USE_CALLING_UID, camera);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ }
if (camera == NULL) {
return -EACCES;
@@ -510,7 +525,6 @@ static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
// finalizer is invoked later.
static void android_hardware_Camera_release(JNIEnv *env, jobject thiz)
{
- // TODO: Change to ALOGV
ALOGV("release camera");
JNICameraContext* context = NULL;
sp<Camera> camera;
@@ -891,7 +905,7 @@ static JNINativeMethod camMethods[] = {
"(ILandroid/hardware/Camera$CameraInfo;)V",
(void*)android_hardware_Camera_getCameraInfo },
{ "native_setup",
- "(Ljava/lang/Object;ILjava/lang/String;)I",
+ "(Ljava/lang/Object;IILjava/lang/String;)I",
(void*)android_hardware_Camera_native_setup },
{ "native_release",
"()V",
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index fcf8f83..c588942 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -51,6 +51,8 @@ struct SensorOffsets
jfieldID fifoMaxEventCount;
jfieldID stringType;
jfieldID requiredPermission;
+ jfieldID maxDelay;
+ jfieldID flags;
} gSensorOffsets;
@@ -78,6 +80,8 @@ nativeClassInit (JNIEnv *_env, jclass _this)
sensorOffsets.stringType = _env->GetFieldID(sensorClass, "mStringType", "Ljava/lang/String;");
sensorOffsets.requiredPermission = _env->GetFieldID(sensorClass, "mRequiredPermission",
"Ljava/lang/String;");
+ sensorOffsets.maxDelay = _env->GetFieldID(sensorClass, "mMaxDelay", "I");
+ sensorOffsets.flags = _env->GetFieldID(sensorClass, "mFlags", "I");
}
static jint
@@ -112,6 +116,8 @@ nativeGetNextSensor(JNIEnv *env, jclass clazz, jobject sensor, jint next)
env->SetObjectField(sensor, sensorOffsets.stringType, stringType);
env->SetObjectField(sensor, sensorOffsets.requiredPermission,
requiredPermission);
+ env->SetIntField(sensor, sensorOffsets.maxDelay, list->getMaxDelay());
+ env->SetIntField(sensor, sensorOffsets.flags, list->getFlags());
next++;
return size_t(next) < count ? next : 0;
}
@@ -160,7 +166,8 @@ private:
ASensorEvent buffer[16];
while ((n = q->read(buffer, 16)) > 0) {
for (int i=0 ; i<n ; i++) {
- if (buffer[i].type == SENSOR_TYPE_STEP_COUNTER) {
+ if (buffer[i].type == SENSOR_TYPE_STEP_COUNTER ||
+ buffer[i].type == SENSOR_TYPE_WAKE_UP_STEP_COUNTER) {
// step-counter returns a uint64, but the java API only deals with floats
float value = float(buffer[i].u64.step_counter);
env->SetFloatArrayRegion(mScratch, 0, 1, &value);
@@ -175,11 +182,26 @@ private:
gBaseEventQueueClassInfo.dispatchFlushCompleteEvent,
buffer[i].meta_data.sensor);
} else {
+ int8_t status;
+ switch (buffer[i].type) {
+ case SENSOR_TYPE_ORIENTATION:
+ case SENSOR_TYPE_MAGNETIC_FIELD:
+ case SENSOR_TYPE_ACCELEROMETER:
+ case SENSOR_TYPE_GYROSCOPE:
+ status = buffer[i].vector.status;
+ break;
+ case SENSOR_TYPE_HEART_RATE:
+ status = buffer[i].heart_rate.status;
+ break;
+ default:
+ status = SENSOR_STATUS_ACCURACY_HIGH;
+ break;
+ }
env->CallVoidMethod(mReceiverObject,
gBaseEventQueueClassInfo.dispatchSensorEvent,
buffer[i].sensor,
mScratch,
- buffer[i].vector.status,
+ status,
buffer[i].timestamp);
}
if (env->ExceptionCheck()) {
diff --git a/core/jni/android_hardware_SoundTrigger.cpp b/core/jni/android_hardware_SoundTrigger.cpp
new file mode 100644
index 0000000..69e991d
--- /dev/null
+++ b/core/jni/android_hardware_SoundTrigger.cpp
@@ -0,0 +1,661 @@
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "SoundTrigger-JNI"
+#include <utils/Log.h>
+
+#include "jni.h"
+#include "JNIHelp.h"
+#include "android_runtime/AndroidRuntime.h"
+#include <system/sound_trigger.h>
+#include <soundtrigger/SoundTriggerCallback.h>
+#include <soundtrigger/SoundTrigger.h>
+#include <utils/RefBase.h>
+#include <utils/Vector.h>
+#include <binder/IMemory.h>
+#include <binder/MemoryDealer.h>
+
+using namespace android;
+
+static jclass gArrayListClass;
+static struct {
+ jmethodID add;
+} gArrayListMethods;
+
+static const char* const kSoundTriggerClassPathName = "android/hardware/soundtrigger/SoundTrigger";
+static jclass gSoundTriggerClass;
+
+static const char* const kModuleClassPathName = "android/hardware/soundtrigger/SoundTriggerModule";
+static jclass gModuleClass;
+static struct {
+ jfieldID mNativeContext;
+ jfieldID mId;
+} gModuleFields;
+static jmethodID gPostEventFromNative;
+
+static const char* const kModulePropertiesClassPathName =
+ "android/hardware/soundtrigger/SoundTrigger$ModuleProperties";
+static jclass gModulePropertiesClass;
+static jmethodID gModulePropertiesCstor;
+
+static const char* const kSoundModelClassPathName =
+ "android/hardware/soundtrigger/SoundTrigger$SoundModel";
+static jclass gSoundModelClass;
+static struct {
+ jfieldID data;
+} gSoundModelFields;
+
+static const char* const kKeyPhraseClassPathName =
+ "android/hardware/soundtrigger/SoundTrigger$KeyPhrase";
+static jclass gKeyPhraseClass;
+static struct {
+ jfieldID recognitionModes;
+ jfieldID locale;
+ jfieldID text;
+ jfieldID numUsers;
+} gKeyPhraseFields;
+
+static const char* const kKeyPhraseSoundModelClassPathName =
+ "android/hardware/soundtrigger/SoundTrigger$KeyPhraseSoundModel";
+static jclass gKeyPhraseSoundModelClass;
+static struct {
+ jfieldID keyPhrases;
+} gKeyPhraseSoundModelFields;
+
+
+static const char* const kRecognitionEventClassPathName =
+ "android/hardware/soundtrigger/SoundTrigger$RecognitionEvent";
+static jclass gRecognitionEventClass;
+static jmethodID gRecognitionEventCstor;
+
+static const char* const kKeyPhraseRecognitionEventClassPathName =
+ "android/hardware/soundtrigger/SoundTrigger$KeyPhraseRecognitionEvent";
+static jclass gKeyPhraseRecognitionEventClass;
+static jmethodID gKeyPhraseRecognitionEventCstor;
+
+static const char* const kKeyPhraseRecognitionExtraClassPathName =
+ "android/hardware/soundtrigger/SoundTrigger$KeyPhraseRecognitionExtra";
+static jclass gKeyPhraseRecognitionExtraClass;
+static jmethodID gKeyPhraseRecognitionExtraCstor;
+
+static Mutex gLock;
+
+enum {
+ SOUNDTRIGGER_STATUS_OK = 0,
+ SOUNDTRIGGER_STATUS_ERROR = INT_MIN,
+ SOUNDTRIGGER_PERMISSION_DENIED = -1,
+ SOUNDTRIGGER_STATUS_NO_INIT = -19,
+ SOUNDTRIGGER_STATUS_BAD_VALUE = -22,
+ SOUNDTRIGGER_STATUS_DEAD_OBJECT = -32,
+ SOUNDTRIGGER_INVALID_OPERATION = -38,
+};
+
+enum {
+ SOUNDTRIGGER_EVENT_RECOGNITION = 1,
+ SOUNDTRIGGER_EVENT_SERVICE_DIED = 2,
+};
+
+// ----------------------------------------------------------------------------
+// ref-counted object for callbacks
+class JNISoundTriggerCallback: public SoundTriggerCallback
+{
+public:
+ JNISoundTriggerCallback(JNIEnv* env, jobject thiz, jobject weak_thiz);
+ ~JNISoundTriggerCallback();
+
+ virtual void onRecognitionEvent(struct sound_trigger_recognition_event *event);
+ virtual void onServiceDied();
+
+private:
+ jclass mClass; // Reference to SoundTrigger class
+ jobject mObject; // Weak ref to SoundTrigger Java object to call on
+};
+
+JNISoundTriggerCallback::JNISoundTriggerCallback(JNIEnv* env, jobject thiz, jobject weak_thiz)
+{
+
+ // Hold onto the SoundTriggerModule class for use in calling the static method
+ // that posts events to the application thread.
+ jclass clazz = env->GetObjectClass(thiz);
+ if (clazz == NULL) {
+ ALOGE("Can't find class %s", kModuleClassPathName);
+ return;
+ }
+ mClass = (jclass)env->NewGlobalRef(clazz);
+
+ // We use a weak reference so the SoundTriggerModule object can be garbage collected.
+ // The reference is only used as a proxy for callbacks.
+ mObject = env->NewGlobalRef(weak_thiz);
+}
+
+JNISoundTriggerCallback::~JNISoundTriggerCallback()
+{
+ // remove global references
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+ env->DeleteGlobalRef(mObject);
+ env->DeleteGlobalRef(mClass);
+}
+
+void JNISoundTriggerCallback::onRecognitionEvent(struct sound_trigger_recognition_event *event)
+{
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+
+ jobject jEvent;
+
+ jbyteArray jData = NULL;
+ if (event->data_size) {
+ jData = env->NewByteArray(event->data_size);
+ jbyte *nData = env->GetByteArrayElements(jData, NULL);
+ memcpy(nData, (char *)event + event->data_offset, event->data_size);
+ env->ReleaseByteArrayElements(jData, nData, 0);
+ }
+
+ if (event->type == SOUND_MODEL_TYPE_KEYPHRASE) {
+ struct sound_trigger_phrase_recognition_event *phraseEvent =
+ (struct sound_trigger_phrase_recognition_event *)event;
+
+ jobjectArray jExtras = env->NewObjectArray(phraseEvent->num_phrases,
+ gKeyPhraseRecognitionExtraClass, NULL);
+ if (jExtras == NULL) {
+ return;
+ }
+
+ for (size_t i = 0; i < phraseEvent->num_phrases; i++) {
+ jintArray jConfidenceLevels = env->NewIntArray(phraseEvent->phrase_extras[i].num_users);
+ if (jConfidenceLevels == NULL) {
+ return;
+ }
+ jint *nConfidenceLevels = env->GetIntArrayElements(jConfidenceLevels, NULL);
+ memcpy(nConfidenceLevels,
+ phraseEvent->phrase_extras[i].confidence_levels,
+ phraseEvent->phrase_extras[i].num_users * sizeof(int));
+ env->ReleaseIntArrayElements(jConfidenceLevels, nConfidenceLevels, 0);
+ jobject jNewExtra = env->NewObject(gKeyPhraseRecognitionExtraClass,
+ gKeyPhraseRecognitionExtraCstor,
+ jConfidenceLevels,
+ phraseEvent->phrase_extras[i].recognition_modes);
+
+ if (jNewExtra == NULL) {
+ return;
+ }
+ env->SetObjectArrayElement(jExtras, i, jNewExtra);
+
+ }
+ jEvent = env->NewObject(gKeyPhraseRecognitionEventClass, gKeyPhraseRecognitionEventCstor,
+ event->status, event->model, event->capture_available,
+ event->capture_session, event->capture_delay_ms, jData,
+ phraseEvent->key_phrase_in_capture, jExtras);
+ } else {
+ jEvent = env->NewObject(gRecognitionEventClass, gRecognitionEventCstor,
+ event->status, event->model, event->capture_available,
+ event->capture_session, event->capture_delay_ms, jData);
+ }
+
+
+ env->CallStaticVoidMethod(mClass, gPostEventFromNative, mObject,
+ SOUNDTRIGGER_EVENT_RECOGNITION, 0, 0, jEvent);
+ if (env->ExceptionCheck()) {
+ ALOGW("An exception occurred while notifying an event.");
+ env->ExceptionClear();
+ }
+}
+
+void JNISoundTriggerCallback::onServiceDied()
+{
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+
+ env->CallStaticVoidMethod(mClass, gPostEventFromNative, mObject,
+ SOUNDTRIGGER_EVENT_SERVICE_DIED, 0, 0, NULL);
+ if (env->ExceptionCheck()) {
+ ALOGW("An exception occurred while notifying an event.");
+ env->ExceptionClear();
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+static sp<SoundTrigger> getSoundTrigger(JNIEnv* env, jobject thiz)
+{
+ Mutex::Autolock l(gLock);
+ SoundTrigger* const st = (SoundTrigger*)env->GetLongField(thiz,
+ gModuleFields.mNativeContext);
+ return sp<SoundTrigger>(st);
+}
+
+static sp<SoundTrigger> setSoundTrigger(JNIEnv* env, jobject thiz, const sp<SoundTrigger>& module)
+{
+ Mutex::Autolock l(gLock);
+ sp<SoundTrigger> old = (SoundTrigger*)env->GetLongField(thiz,
+ gModuleFields.mNativeContext);
+ if (module.get()) {
+ module->incStrong((void*)setSoundTrigger);
+ }
+ if (old != 0) {
+ old->decStrong((void*)setSoundTrigger);
+ }
+ env->SetLongField(thiz, gModuleFields.mNativeContext, (jlong)module.get());
+ return old;
+}
+
+
+static jint
+android_hardware_SoundTrigger_listModules(JNIEnv *env, jobject clazz,
+ jobject jModules)
+{
+ ALOGV("listModules");
+
+ if (jModules == NULL) {
+ ALOGE("listModules NULL AudioPatch ArrayList");
+ return SOUNDTRIGGER_STATUS_BAD_VALUE;
+ }
+ if (!env->IsInstanceOf(jModules, gArrayListClass)) {
+ ALOGE("listModules not an arraylist");
+ return SOUNDTRIGGER_STATUS_BAD_VALUE;
+ }
+
+ unsigned int numModules = 0;
+ struct sound_trigger_module_descriptor *nModules = NULL;
+
+ status_t status = SoundTrigger::listModules(nModules, &numModules);
+ if (status != NO_ERROR || numModules == 0) {
+ return (jint)status;
+ }
+
+ nModules = (struct sound_trigger_module_descriptor *)
+ calloc(numModules, sizeof(struct sound_trigger_module_descriptor));
+
+ status = SoundTrigger::listModules(nModules, &numModules);
+ ALOGV("listModules SoundTrigger::listModules status %d numModules %d", status, numModules);
+
+ if (status != NO_ERROR) {
+ numModules = 0;
+ }
+
+ for (size_t i = 0; i < numModules; i++) {
+ char str[SOUND_TRIGGER_MAX_STRING_LEN];
+
+ jstring implementor = env->NewStringUTF(nModules[i].properties.implementor);
+ jstring description = env->NewStringUTF(nModules[i].properties.description);
+ SoundTrigger::guidToString(&nModules[i].properties.uuid,
+ str,
+ SOUND_TRIGGER_MAX_STRING_LEN);
+ jstring uuid = env->NewStringUTF(str);
+
+ ALOGV("listModules module %d id %d description %s maxSoundModels %d",
+ i, nModules[i].handle, nModules[i].properties.description,
+ nModules[i].properties.max_sound_models);
+
+ jobject newModuleDesc = env->NewObject(gModulePropertiesClass, gModulePropertiesCstor,
+ nModules[i].handle,
+ implementor, description, uuid,
+ nModules[i].properties.version,
+ nModules[i].properties.max_sound_models,
+ nModules[i].properties.max_key_phrases,
+ nModules[i].properties.max_users,
+ nModules[i].properties.recognition_modes,
+ nModules[i].properties.capture_transition,
+ nModules[i].properties.max_buffer_ms,
+ nModules[i].properties.concurrent_capture,
+ nModules[i].properties.power_consumption_mw);
+
+ env->DeleteLocalRef(implementor);
+ env->DeleteLocalRef(description);
+ env->DeleteLocalRef(uuid);
+ if (newModuleDesc == NULL) {
+ status = SOUNDTRIGGER_STATUS_ERROR;
+ goto exit;
+ }
+ env->CallBooleanMethod(jModules, gArrayListMethods.add, newModuleDesc);
+ }
+
+exit:
+ free(nModules);
+ return (jint) status;
+}
+
+static void
+android_hardware_SoundTrigger_setup(JNIEnv *env, jobject thiz, jobject weak_this)
+{
+ ALOGV("setup");
+
+ sp<JNISoundTriggerCallback> callback = new JNISoundTriggerCallback(env, thiz, weak_this);
+
+ sound_trigger_module_handle_t handle =
+ (sound_trigger_module_handle_t)env->GetIntField(thiz, gModuleFields.mId);
+
+ sp<SoundTrigger> module = SoundTrigger::attach(handle, callback);
+ if (module == 0) {
+ return;
+ }
+
+ setSoundTrigger(env, thiz, module);
+}
+
+static void
+android_hardware_SoundTrigger_detach(JNIEnv *env, jobject thiz)
+{
+ ALOGV("detach");
+ sp<SoundTrigger> module = setSoundTrigger(env, thiz, 0);
+ ALOGV("detach module %p", module.get());
+ if (module != 0) {
+ ALOGV("detach module->detach()");
+ module->detach();
+ }
+}
+
+static void
+android_hardware_SoundTrigger_finalize(JNIEnv *env, jobject thiz)
+{
+ ALOGV("finalize");
+ sp<SoundTrigger> module = getSoundTrigger(env, thiz);
+ if (module != 0) {
+ ALOGW("SoundTrigger finalized without being detached");
+ }
+ android_hardware_SoundTrigger_detach(env, thiz);
+}
+
+static jint
+android_hardware_SoundTrigger_loadSoundModel(JNIEnv *env, jobject thiz,
+ jobject jSoundModel, jintArray jHandle)
+{
+ jint status = SOUNDTRIGGER_STATUS_OK;
+ char *nData = NULL;
+ struct sound_trigger_sound_model *nSoundModel;
+ jbyteArray jData;
+ sp<MemoryDealer> memoryDealer;
+ sp<IMemory> memory;
+ size_t size;
+ sound_model_handle_t handle;
+
+ ALOGV("loadSoundModel");
+ sp<SoundTrigger> module = getSoundTrigger(env, thiz);
+ if (module == NULL) {
+ return SOUNDTRIGGER_STATUS_ERROR;
+ }
+ if (jHandle == NULL) {
+ return SOUNDTRIGGER_STATUS_BAD_VALUE;
+ }
+ jsize jHandleLen = env->GetArrayLength(jHandle);
+ if (jHandleLen == 0) {
+ return SOUNDTRIGGER_STATUS_BAD_VALUE;
+ }
+ jint *nHandle = env->GetIntArrayElements(jHandle, NULL);
+ if (nHandle == NULL) {
+ return SOUNDTRIGGER_STATUS_ERROR;
+ }
+ if (!env->IsInstanceOf(jSoundModel, gSoundModelClass)) {
+ status = SOUNDTRIGGER_STATUS_BAD_VALUE;
+ goto exit;
+ }
+ size_t offset;
+ sound_trigger_sound_model_type_t type;
+ if (env->IsInstanceOf(jSoundModel, gKeyPhraseSoundModelClass)) {
+ offset = sizeof(struct sound_trigger_phrase_sound_model);
+ type = SOUND_MODEL_TYPE_KEYPHRASE;
+ } else {
+ offset = sizeof(struct sound_trigger_sound_model);
+ type = SOUND_MODEL_TYPE_UNKNOWN;
+ }
+ jData = (jbyteArray)env->GetObjectField(jSoundModel, gSoundModelFields.data);
+ if (jData == NULL) {
+ status = SOUNDTRIGGER_STATUS_BAD_VALUE;
+ goto exit;
+ }
+ size = env->GetArrayLength(jData);
+
+ nData = (char *)env->GetByteArrayElements(jData, NULL);
+ if (jData == NULL) {
+ status = SOUNDTRIGGER_STATUS_ERROR;
+ goto exit;
+ }
+
+ memoryDealer = new MemoryDealer(offset + size, "SoundTrigge-JNI::LoadModel");
+ if (memoryDealer == 0) {
+ status = SOUNDTRIGGER_STATUS_ERROR;
+ goto exit;
+ }
+ memory = memoryDealer->allocate(offset + size);
+ if (memory == 0 || memory->pointer() == NULL) {
+ status = SOUNDTRIGGER_STATUS_ERROR;
+ goto exit;
+ }
+
+ nSoundModel = (struct sound_trigger_sound_model *)memory->pointer();
+
+ nSoundModel->type = type;
+ nSoundModel->data_size = size;
+ nSoundModel->data_offset = offset;
+ memcpy((char *)nSoundModel + offset, nData, size);
+ if (type == SOUND_MODEL_TYPE_KEYPHRASE) {
+ struct sound_trigger_phrase_sound_model *phraseModel =
+ (struct sound_trigger_phrase_sound_model *)nSoundModel;
+
+ jobjectArray jPhrases =
+ (jobjectArray)env->GetObjectField(jSoundModel, gKeyPhraseSoundModelFields.keyPhrases);
+ if (jPhrases == NULL) {
+ status = SOUNDTRIGGER_STATUS_BAD_VALUE;
+ goto exit;
+ }
+
+ size_t numPhrases = env->GetArrayLength(jPhrases);
+ phraseModel->num_phrases = numPhrases;
+ ALOGV("loadSoundModel numPhrases %d", numPhrases);
+ for (size_t i = 0; i < numPhrases; i++) {
+ jobject jPhrase = env->GetObjectArrayElement(jPhrases, i);
+ phraseModel->phrases[i].recognition_mode =
+ env->GetIntField(jPhrase,gKeyPhraseFields.recognitionModes);
+ phraseModel->phrases[i].num_users =
+ env->GetIntField(jPhrase, gKeyPhraseFields.numUsers);
+ jstring jLocale = (jstring)env->GetObjectField(jPhrase, gKeyPhraseFields.locale);
+ const char *nLocale = env->GetStringUTFChars(jLocale, NULL);
+ strncpy(phraseModel->phrases[i].locale,
+ nLocale,
+ SOUND_TRIGGER_MAX_LOCALE_LEN);
+ jstring jText = (jstring)env->GetObjectField(jPhrase, gKeyPhraseFields.text);
+ const char *nText = env->GetStringUTFChars(jText, NULL);
+ strncpy(phraseModel->phrases[i].text,
+ nText,
+ SOUND_TRIGGER_MAX_STRING_LEN);
+
+ env->ReleaseStringUTFChars(jLocale, nLocale);
+ env->DeleteLocalRef(jLocale);
+ env->ReleaseStringUTFChars(jText, nText);
+ env->DeleteLocalRef(jText);
+ ALOGV("loadSoundModel phrases %d text %s locale %s",
+ i, phraseModel->phrases[i].text, phraseModel->phrases[i].locale);
+ }
+ env->DeleteLocalRef(jPhrases);
+ }
+ status = module->loadSoundModel(memory, &handle);
+ ALOGV("loadSoundModel status %d handle %d", status, handle);
+
+exit:
+ if (nHandle != NULL) {
+ nHandle[0] = (jint)handle;
+ env->ReleaseIntArrayElements(jHandle, nHandle, NULL);
+ }
+ if (nData != NULL) {
+ env->ReleaseByteArrayElements(jData, (jbyte *)nData, NULL);
+ }
+ return status;
+}
+
+static jint
+android_hardware_SoundTrigger_unloadSoundModel(JNIEnv *env, jobject thiz,
+ jint jHandle)
+{
+ jint status = SOUNDTRIGGER_STATUS_OK;
+ ALOGV("unloadSoundModel");
+ sp<SoundTrigger> module = getSoundTrigger(env, thiz);
+ if (module == NULL) {
+ return SOUNDTRIGGER_STATUS_ERROR;
+ }
+ status = module->unloadSoundModel((sound_model_handle_t)jHandle);
+
+ return status;
+}
+
+static jint
+android_hardware_SoundTrigger_startRecognition(JNIEnv *env, jobject thiz,
+ jint jHandle, jbyteArray jData)
+{
+ jint status = SOUNDTRIGGER_STATUS_OK;
+ ALOGV("startRecognition");
+ sp<SoundTrigger> module = getSoundTrigger(env, thiz);
+ if (module == NULL) {
+ return SOUNDTRIGGER_STATUS_ERROR;
+ }
+ jsize dataSize = 0;
+ char *nData = NULL;
+ sp<IMemory> memory;
+ if (jData != NULL) {
+ dataSize = env->GetArrayLength(jData);
+ if (dataSize == 0) {
+ return SOUNDTRIGGER_STATUS_BAD_VALUE;
+ }
+ nData = (char *)env->GetByteArrayElements(jData, NULL);
+ if (nData == NULL) {
+ return SOUNDTRIGGER_STATUS_ERROR;
+ }
+ sp<MemoryDealer> memoryDealer =
+ new MemoryDealer(dataSize, "SoundTrigge-JNI::StartRecognition");
+ if (memoryDealer == 0) {
+ return SOUNDTRIGGER_STATUS_ERROR;
+ }
+ memory = memoryDealer->allocate(dataSize);
+ if (memory == 0 || memory->pointer() == NULL) {
+ return SOUNDTRIGGER_STATUS_ERROR;
+ }
+ memcpy(memory->pointer(), nData, dataSize);
+ }
+
+ status = module->startRecognition(jHandle, memory);
+ return status;
+}
+
+static jint
+android_hardware_SoundTrigger_stopRecognition(JNIEnv *env, jobject thiz,
+ jint jHandle)
+{
+ jint status = SOUNDTRIGGER_STATUS_OK;
+ ALOGV("stopRecognition");
+ sp<SoundTrigger> module = getSoundTrigger(env, thiz);
+ if (module == NULL) {
+ return SOUNDTRIGGER_STATUS_ERROR;
+ }
+ status = module->stopRecognition(jHandle);
+ return status;
+}
+
+static JNINativeMethod gMethods[] = {
+ {"listModules",
+ "(Ljava/util/ArrayList;)I",
+ (void *)android_hardware_SoundTrigger_listModules},
+};
+
+
+static JNINativeMethod gModuleMethods[] = {
+ {"native_setup",
+ "(Ljava/lang/Object;)V",
+ (void *)android_hardware_SoundTrigger_setup},
+ {"native_finalize",
+ "()V",
+ (void *)android_hardware_SoundTrigger_finalize},
+ {"detach",
+ "()V",
+ (void *)android_hardware_SoundTrigger_detach},
+ {"loadSoundModel",
+ "(Landroid/hardware/soundtrigger/SoundTrigger$SoundModel;[I)I",
+ (void *)android_hardware_SoundTrigger_loadSoundModel},
+ {"unloadSoundModel",
+ "(I)I",
+ (void *)android_hardware_SoundTrigger_unloadSoundModel},
+ {"startRecognition",
+ "(I[B)I",
+ (void *)android_hardware_SoundTrigger_startRecognition},
+ {"stopRecognition",
+ "(I)I",
+ (void *)android_hardware_SoundTrigger_stopRecognition},
+};
+
+int register_android_hardware_SoundTrigger(JNIEnv *env)
+{
+ jclass arrayListClass = env->FindClass("java/util/ArrayList");
+ gArrayListClass = (jclass) env->NewGlobalRef(arrayListClass);
+ gArrayListMethods.add = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
+
+ jclass lClass = env->FindClass(kSoundTriggerClassPathName);
+ gSoundTriggerClass = (jclass) env->NewGlobalRef(lClass);
+
+ jclass moduleClass = env->FindClass(kModuleClassPathName);
+ gModuleClass = (jclass) env->NewGlobalRef(moduleClass);
+ gPostEventFromNative = env->GetStaticMethodID(moduleClass, "postEventFromNative",
+ "(Ljava/lang/Object;IIILjava/lang/Object;)V");
+ gModuleFields.mNativeContext = env->GetFieldID(moduleClass, "mNativeContext", "J");
+ gModuleFields.mId = env->GetFieldID(moduleClass, "mId", "I");
+
+
+ jclass modulePropertiesClass = env->FindClass(kModulePropertiesClassPathName);
+ gModulePropertiesClass = (jclass) env->NewGlobalRef(modulePropertiesClass);
+ gModulePropertiesCstor = env->GetMethodID(modulePropertiesClass, "<init>",
+ "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;IIIIIZIZI)V");
+
+ jclass soundModelClass = env->FindClass(kSoundModelClassPathName);
+ gSoundModelClass = (jclass) env->NewGlobalRef(soundModelClass);
+ gSoundModelFields.data = env->GetFieldID(soundModelClass, "data", "[B");
+
+ jclass keyPhraseClass = env->FindClass(kKeyPhraseClassPathName);
+ gKeyPhraseClass = (jclass) env->NewGlobalRef(keyPhraseClass);
+ gKeyPhraseFields.recognitionModes = env->GetFieldID(keyPhraseClass, "recognitionModes", "I");
+ gKeyPhraseFields.locale = env->GetFieldID(keyPhraseClass, "locale", "Ljava/lang/String;");
+ gKeyPhraseFields.text = env->GetFieldID(keyPhraseClass, "text", "Ljava/lang/String;");
+ gKeyPhraseFields.numUsers = env->GetFieldID(keyPhraseClass, "numUsers", "I");
+
+ jclass keyPhraseSoundModelClass = env->FindClass(kKeyPhraseSoundModelClassPathName);
+ gKeyPhraseSoundModelClass = (jclass) env->NewGlobalRef(keyPhraseSoundModelClass);
+ gKeyPhraseSoundModelFields.keyPhrases = env->GetFieldID(keyPhraseSoundModelClass,
+ "keyPhrases",
+ "[Landroid/hardware/soundtrigger/SoundTrigger$KeyPhrase;");
+
+
+ jclass recognitionEventClass = env->FindClass(kRecognitionEventClassPathName);
+ gRecognitionEventClass = (jclass) env->NewGlobalRef(recognitionEventClass);
+ gRecognitionEventCstor = env->GetMethodID(recognitionEventClass, "<init>",
+ "(IIZII[B)V");
+
+ jclass keyPhraseRecognitionEventClass = env->FindClass(kKeyPhraseRecognitionEventClassPathName);
+ gKeyPhraseRecognitionEventClass = (jclass) env->NewGlobalRef(keyPhraseRecognitionEventClass);
+ gKeyPhraseRecognitionEventCstor = env->GetMethodID(keyPhraseRecognitionEventClass, "<init>",
+ "(IIZII[BZ[Landroid/hardware/soundtrigger/SoundTrigger$KeyPhraseRecognitionExtra;)V");
+
+
+ jclass keyPhraseRecognitionExtraClass = env->FindClass(kKeyPhraseRecognitionExtraClassPathName);
+ gKeyPhraseRecognitionExtraClass = (jclass) env->NewGlobalRef(keyPhraseRecognitionExtraClass);
+ gKeyPhraseRecognitionExtraCstor = env->GetMethodID(keyPhraseRecognitionExtraClass, "<init>",
+ "([II)V");
+
+ int status = AndroidRuntime::registerNativeMethods(env,
+ kSoundTriggerClassPathName, gMethods, NELEM(gMethods));
+
+ if (status == 0) {
+ status = AndroidRuntime::registerNativeMethods(env,
+ kModuleClassPathName, gModuleMethods, NELEM(gModuleMethods));
+ }
+
+ return status;
+}
diff --git a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
index 40e9544..57058a6 100644
--- a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
+++ b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
@@ -15,6 +15,7 @@
*/
#define LOG_TAG "Legacy-CameraDevice-JNI"
+// #define LOG_NDEBUG 0
#include <utils/Log.h>
#include <utils/Errors.h>
#include <utils/Trace.h>
@@ -26,6 +27,7 @@
#include <ui/GraphicBuffer.h>
#include <system/window.h>
+#include <hardware/camera3.h>
using namespace android;
@@ -35,6 +37,8 @@ using namespace android;
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a)))
+#define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
+
/**
* Convert from RGB 888 to Y'CbCr using the conversion specified in ITU-R BT.601 for
* digital RGB with K_b = 0.114, and K_r = 0.299.
@@ -116,8 +120,9 @@ static status_t configureSurface(const sp<ANativeWindow>& anw,
return err;
}
- ALOGV("%s: Setting buffer count to %d", __FUNCTION__,
- maxBufferSlack + 1 + minUndequeuedBuffers);
+ ALOGV("%s: Setting buffer count to %d, size to (%dx%d), fmt (0x%x)", __FUNCTION__,
+ maxBufferSlack + 1 + minUndequeuedBuffers,
+ width, height, pixelFmt);
err = native_window_set_buffer_count(anw.get(), maxBufferSlack + 1 + minUndequeuedBuffers);
if (err != NO_ERROR) {
ALOGE("%s: Failed to set native window buffer count, error %s (%d).", __FUNCTION__,
@@ -146,16 +151,41 @@ static status_t produceFrame(const sp<ANativeWindow>& anw,
int32_t width, // Width of the pixelBuffer
int32_t height, // Height of the pixelBuffer
int32_t pixelFmt, // Format of the pixelBuffer
- int64_t bufSize) {
+ int32_t bufSize) {
ATRACE_CALL();
status_t err = NO_ERROR;
ANativeWindowBuffer* anb;
- ALOGV("%s: Dequeue buffer from %p",__FUNCTION__, anw.get());
+ ALOGV("%s: Dequeue buffer from %p %dx%d (fmt=%x, size=%x)",
+ __FUNCTION__, anw.get(), width, height, pixelFmt, bufSize);
+
+ if (anw == 0) {
+ ALOGE("%s: anw must not be NULL", __FUNCTION__);
+ return BAD_VALUE;
+ } else if (pixelBuffer == NULL) {
+ ALOGE("%s: pixelBuffer must not be NULL", __FUNCTION__);
+ return BAD_VALUE;
+ } else if (width < 0) {
+ ALOGE("%s: width must be non-negative", __FUNCTION__);
+ return BAD_VALUE;
+ } else if (height < 0) {
+ ALOGE("%s: height must be non-negative", __FUNCTION__);
+ return BAD_VALUE;
+ } else if (bufSize < 0) {
+ ALOGE("%s: bufSize must be non-negative", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ if (width < 0 || height < 0 || bufSize < 0) {
+ ALOGE("%s: Illegal argument, negative dimension passed to produceFrame", __FUNCTION__);
+ return BAD_VALUE;
+ }
// TODO: Switch to using Surface::lock and Surface::unlockAndPost
err = native_window_dequeue_buffer_and_wait(anw.get(), &anb);
if (err != NO_ERROR) return err;
+ // TODO: check anb is large enough to store the results
+
sp<GraphicBuffer> buf(new GraphicBuffer(anb, /*keepOwnership*/false));
switch(pixelFmt) {
@@ -181,6 +211,41 @@ static status_t produceFrame(const sp<ANativeWindow>& anw,
uPlane, vPlane, chromaStep, yStride, chromaStride);
break;
}
+ case HAL_PIXEL_FORMAT_YV12: {
+ if (bufSize < width * height * 4) {
+ ALOGE("%s: PixelBuffer size %lld to small for given dimensions", __FUNCTION__,
+ bufSize);
+ return BAD_VALUE;
+ }
+
+ if ((width & 1) || (height & 1)) {
+ ALOGE("%s: Dimens %dx%d are not divisible by 2.", __FUNCTION__, width, height);
+ return BAD_VALUE;
+ }
+
+ uint8_t* img = NULL;
+ ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get());
+ err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
+ if (err != NO_ERROR) {
+ ALOGE("%s: Error %s (%d) while locking gralloc buffer for write.", __FUNCTION__,
+ strerror(-err), err);
+ return err;
+ }
+
+ uint32_t stride = buf->getStride();
+ LOG_ALWAYS_FATAL_IF(stride % 16, "Stride is not 16 pixel aligned %d", stride);
+
+ uint32_t cStride = ALIGN(stride / 2, 16);
+ size_t chromaStep = 1;
+
+ uint8_t* yPlane = img;
+ uint8_t* crPlane = img + static_cast<uint32_t>(height) * stride;
+ uint8_t* cbPlane = crPlane + cStride * static_cast<uint32_t>(height) / 2;
+
+ rgbToYuv420(pixelBuffer, width, height, yPlane,
+ crPlane, cbPlane, chromaStep, stride, cStride);
+ break;
+ }
case HAL_PIXEL_FORMAT_YCbCr_420_888: {
// Software writes with YCbCr_420_888 format are unsupported
// by the gralloc module for now
@@ -215,7 +280,12 @@ static status_t produceFrame(const sp<ANativeWindow>& anw,
err);
return err;
}
+ struct camera3_jpeg_blob footer = {
+ jpeg_blob_id: CAMERA3_JPEG_BLOB_ID,
+ jpeg_size: (uint32_t)width
+ };
memcpy(img, pixelBuffer, width);
+ memcpy(img + anb->width - sizeof(footer), &footer, sizeof(footer));
break;
}
default: {
diff --git a/core/jni/android_media_AudioFormat.h b/core/jni/android_media_AudioFormat.h
index a2b1ed9..807dd32 100644
--- a/core/jni/android_media_AudioFormat.h
+++ b/core/jni/android_media_AudioFormat.h
@@ -20,11 +20,15 @@
#include <system/audio.h>
// keep these values in sync with AudioFormat.java
-#define ENCODING_PCM_16BIT 2
-#define ENCODING_PCM_8BIT 3
-#define ENCODING_PCM_FLOAT 4
-#define ENCODING_INVALID 0
-#define ENCODING_DEFAULT 1
+#define ENCODING_PCM_16BIT 2
+#define ENCODING_PCM_8BIT 3
+#define ENCODING_PCM_FLOAT 4
+#define ENCODING_AC3 5
+#define ENCODING_E_AC3 6
+#define ENCODING_INVALID 0
+#define ENCODING_DEFAULT 1
+
+
#define CHANNEL_INVALID 0
#define CHANNEL_OUT_DEFAULT 1
@@ -38,6 +42,10 @@ static inline audio_format_t audioFormatToNative(int audioFormat)
return AUDIO_FORMAT_PCM_8_BIT;
case ENCODING_PCM_FLOAT:
return AUDIO_FORMAT_PCM_FLOAT;
+ case ENCODING_AC3:
+ return AUDIO_FORMAT_AC3;
+ case ENCODING_E_AC3:
+ return AUDIO_FORMAT_E_AC3;
case ENCODING_DEFAULT:
return AUDIO_FORMAT_DEFAULT;
default:
@@ -54,6 +62,10 @@ static inline int audioFormatFromNative(audio_format_t nativeFormat)
return ENCODING_PCM_8BIT;
case AUDIO_FORMAT_PCM_FLOAT:
return ENCODING_PCM_FLOAT;
+ case AUDIO_FORMAT_AC3:
+ return ENCODING_AC3;
+ case AUDIO_FORMAT_E_AC3:
+ return ENCODING_E_AC3;
case AUDIO_FORMAT_DEFAULT:
return ENCODING_DEFAULT;
default:
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index bf47dd3..849531c 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -244,6 +244,12 @@ android_media_AudioSystem_isSourceActive(JNIEnv *env, jobject thiz, jint source)
}
static jint
+android_media_AudioSystem_newAudioSessionId(JNIEnv *env, jobject thiz)
+{
+ return AudioSystem::newAudioSessionId();
+}
+
+static jint
android_media_AudioSystem_setParameters(JNIEnv *env, jobject thiz, jstring keyValuePairs)
{
const jchar* c_keyValuePairs = env->GetStringCritical(keyValuePairs, 0);
@@ -281,6 +287,8 @@ android_media_AudioSystem_error_callback(status_t err)
env->CallStaticVoidMethod(clazz, env->GetStaticMethodID(clazz,
"errorCallbackFromNative","(I)V"),
check_AudioSystem_Command(err));
+
+ env->DeleteLocalRef(clazz);
}
static jint
@@ -1295,6 +1303,7 @@ static JNINativeMethod gMethods[] = {
{"isStreamActive", "(II)Z", (void *)android_media_AudioSystem_isStreamActive},
{"isStreamActiveRemotely","(II)Z", (void *)android_media_AudioSystem_isStreamActiveRemotely},
{"isSourceActive", "(I)Z", (void *)android_media_AudioSystem_isSourceActive},
+ {"newAudioSessionId", "()I", (void *)android_media_AudioSystem_newAudioSessionId},
{"setDeviceConnectionState", "(IILjava/lang/String;)I", (void *)android_media_AudioSystem_setDeviceConnectionState},
{"getDeviceConnectionState", "(ILjava/lang/String;)I", (void *)android_media_AudioSystem_getDeviceConnectionState},
{"setPhoneState", "(I)I", (void *)android_media_AudioSystem_setPhoneState},
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index e548e91..264a9ae 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -220,8 +220,13 @@ android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this,
}
// compute the frame count
- const size_t bytesPerSample = audio_bytes_per_sample(format);
- size_t frameCount = buffSizeInBytes / (channelCount * bytesPerSample);
+ size_t frameCount;
+ if (audio_is_linear_pcm(format)) {
+ const size_t bytesPerSample = audio_bytes_per_sample(format);
+ frameCount = buffSizeInBytes / (channelCount * bytesPerSample);
+ } else {
+ frameCount = buffSizeInBytes;
+ }
jclass clazz = env->GetObjectClass(thiz);
if (clazz == NULL) {
@@ -266,7 +271,7 @@ android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this,
format,// word length, PCM
nativeChannelMask,
frameCount,
- AUDIO_OUTPUT_FLAG_NONE,
+ audio_is_linear_pcm(format) ? AUDIO_OUTPUT_FLAG_NONE : AUDIO_OUTPUT_FLAG_DIRECT,
audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user)
0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
0,// shared mem
@@ -478,14 +483,6 @@ jint writeToTrack(const sp<AudioTrack>& track, jint audioFormat, const jbyte* da
switch (format) {
default:
- // TODO Currently the only possible values for format are AUDIO_FORMAT_PCM_16_BIT,
- // AUDIO_FORMAT_PCM_8_BIT, and AUDIO_FORMAT_PCM_FLOAT,
- // due to the limited set of values for audioFormat.
- // The next section of the switch will probably work for more formats, but it has only
- // been tested for AUDIO_FORMAT_PCM_16_BIT and AUDIO_FORMAT_PCM_FLOAT,
- // so that's why the "default" case fails.
- break;
-
case AUDIO_FORMAT_PCM_FLOAT:
case AUDIO_FORMAT_PCM_16_BIT: {
// writing to shared memory, check for capacity
@@ -904,8 +901,12 @@ static jint android_media_AudioTrack_get_min_buff_size(JNIEnv *env, jobject thi
return -1;
}
const audio_format_t format = audioFormatToNative(audioFormat);
- const size_t bytesPerSample = audio_bytes_per_sample(format);
- return frameCount * channelCount * bytesPerSample;
+ if (audio_is_linear_pcm(format)) {
+ const size_t bytesPerSample = audio_bytes_per_sample(format);
+ return frameCount * channelCount * bytesPerSample;
+ } else {
+ return frameCount;
+ }
}
// ----------------------------------------------------------------------------
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 86207f0..87ee618 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -174,21 +174,21 @@ static int read_memtrack_memory(struct memtrack_proc* p, int pid,
ssize_t pss = memtrack_proc_graphics_pss(p);
if (pss < 0) {
- ALOGW("failed to get graphics pss: %d", pss);
+ ALOGW("failed to get graphics pss: %zd", pss);
return pss;
}
graphics_mem->graphics = pss / 1024;
pss = memtrack_proc_gl_pss(p);
if (pss < 0) {
- ALOGW("failed to get gl pss: %d", pss);
+ ALOGW("failed to get gl pss: %zd", pss);
return pss;
}
graphics_mem->gl = pss / 1024;
pss = memtrack_proc_other_pss(p);
if (pss < 0) {
- ALOGW("failed to get other pss: %d", pss);
+ ALOGW("failed to get other pss: %zd", pss);
return pss;
}
graphics_mem->other = pss / 1024;
@@ -231,9 +231,9 @@ static void read_mapinfo(FILE *fp, stats_t* stats)
unsigned referenced = 0;
unsigned temp;
- unsigned long int start;
- unsigned long int end = 0;
- unsigned long int prevEnd = 0;
+ uint64_t start;
+ uint64_t end = 0;
+ uint64_t prevEnd = 0;
char* name;
int name_pos;
@@ -255,7 +255,7 @@ static void read_mapinfo(FILE *fp, stats_t* stats)
if (len < 1) return;
line[--len] = 0;
- if (sscanf(line, "%lx-%lx %*s %*x %*x:%*x %*d%n", &start, &end, &name_pos) != 2) {
+ if (sscanf(line, "%" SCNx64 "-%" SCNx64 " %*s %*x %*x:%*x %*d%n", &start, &end, &name_pos) != 2) {
skip = true;
} else {
while (isspace(line[name_pos])) {
@@ -371,7 +371,7 @@ static void read_mapinfo(FILE *fp, stats_t* stats)
referenced = temp;
} else if (line[0] == 'S' && sscanf(line, "Swap: %d kB", &temp) == 1) {
swapped_out = temp;
- } else if (strlen(line) > 30 && line[8] == '-' && line[17] == ' ') {
+ } else if (sscanf(line, "%" SCNx64 "-%" SCNx64 " %*s %*x %*x:%*x %*d", &start, &end) == 2) {
// looks like a new mapping
// example: "10000000-10001000 ---p 10000000 00:00 0"
break;
diff --git a/core/jni/android_server_FingerprintManager.cpp b/core/jni/android_server_FingerprintManager.cpp
index f8a1fd9..b174d1b 100644
--- a/core/jni/android_server_FingerprintManager.cpp
+++ b/core/jni/android_server_FingerprintManager.cpp
@@ -20,54 +20,185 @@
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/Log.h>
+#include <hardware/hardware.h>
+#include <hardware/fingerprint.h>
#include <utils/Log.h>
+#define FIND_CLASS(var, className) \
+ var = env->FindClass(className); \
+ LOG_FATAL_IF(! var, "Unable to find class " className); \
+ var = jclass(env->NewGlobalRef(var));
+
+#define GET_STATIC_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
+ var = env->GetStaticMethodID(clazz, methodName, fieldDescriptor); \
+ LOG_FATAL_IF(! var, "Unable to find static method" methodName);
+
+#define GET_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
+ var = env->GetMethodID(clazz, methodName, fieldDescriptor); \
+ LOG_FATAL_IF(! var, "Unable to find method" methodName);
+
+#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
+ var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
+ LOG_FATAL_IF(! var, "Unable to find field " fieldName);
+
namespace android {
+static const uint16_t kVersion = HARDWARE_MODULE_API_VERSION(1, 0);
+
+static const char* FINGERPRINT_SERVICE = "com/android/server/fingerprint/FingerprintService";
static struct {
jclass clazz;
jmethodID notify;
-} gFingerprintManagerClassInfo;
+ jobject callbackObject;
+} gFingerprintServiceClassInfo;
+
+static struct {
+ fingerprint_module_t const* module;
+ fingerprint_device_t *device;
+} gContext;
+
+// Called by the HAL to notify us of fingerprint events
+static void hal_notify_callback(fingerprint_msg_t msg) {
+ uint32_t arg1 = 0;
+ uint32_t arg2 = 0;
+ uint32_t arg3 = 0; // TODO
+ switch (msg.type) {
+ case FINGERPRINT_ERROR:
+ arg1 = msg.data.error;
+ break;
+ case FINGERPRINT_ACQUIRED:
+ arg1 = msg.data.acquired.acquired_info;
+ break;
+ case FINGERPRINT_PROCESSED:
+ arg1 = msg.data.processed.id;
+ break;
+ case FINGERPRINT_TEMPLATE_ENROLLING:
+ arg1 = msg.data.enroll.id;
+ arg2 = msg.data.enroll.samples_remaining;
+ arg3 = msg.data.enroll.data_collected_bmp;
+ break;
+ case FINGERPRINT_TEMPLATE_REMOVED:
+ arg1 = msg.data.removed.id;
+ break;
+ default:
+ ALOGE("fingerprint: invalid msg: %d", msg.type);
+ return;
+ }
+ //ALOG(LOG_VERBOSE, LOG_TAG, "hal_notify(msg=%d, arg1=%d, arg2=%d)\n", msg.type, arg1, arg2);
+
+ // TODO: fix gross hack to attach JNI to calling thread
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ if (env == NULL) {
+ JavaVMAttachArgs args = {JNI_VERSION_1_4, NULL, NULL};
+ JavaVM* vm = AndroidRuntime::getJavaVM();
+ int result = vm->AttachCurrentThread(&env, (void*) &args);
+ if (result != JNI_OK) {
+ ALOGE("Can't call JNI method: attach failed: %#x", result);
+ return;
+ }
+ }
+ env->CallVoidMethod(gFingerprintServiceClassInfo.callbackObject,
+ gFingerprintServiceClassInfo.notify, msg.type, arg1, arg2);
+}
+
+static void nativeInit(JNIEnv *env, jobject clazz, jobject callbackObj) {
+ ALOG(LOG_VERBOSE, LOG_TAG, "nativeInit()\n");
+ FIND_CLASS(gFingerprintServiceClassInfo.clazz, FINGERPRINT_SERVICE);
+ GET_METHOD_ID(gFingerprintServiceClassInfo.notify, gFingerprintServiceClassInfo.clazz,
+ "notify", "(III)V");
+ gFingerprintServiceClassInfo.callbackObject = env->NewGlobalRef(callbackObj);
+}
static jint nativeEnroll(JNIEnv* env, jobject clazz, jint timeout) {
- return -1; // TODO
+ ALOG(LOG_VERBOSE, LOG_TAG, "nativeEnroll()\n");
+ int ret = gContext.device->enroll(gContext.device, timeout);
+ return reinterpret_cast<jint>(ret);
+}
+
+static jint nativeEnrollCancel(JNIEnv* env, jobject clazz) {
+ ALOG(LOG_VERBOSE, LOG_TAG, "nativeEnrollCancel()\n");
+ int ret = gContext.device->enroll_cancel(gContext.device);
+ return reinterpret_cast<jint>(ret);
}
static jint nativeRemove(JNIEnv* env, jobject clazz, jint fingerprintId) {
- return -1; // TODO
+ ALOG(LOG_VERBOSE, LOG_TAG, "nativeRemove(%d)\n", fingerprintId);
+ int ret = gContext.device->remove(gContext.device, fingerprintId);
+ return reinterpret_cast<jint>(ret);
+}
+
+static jint nativeOpenHal(JNIEnv* env, jobject clazz) {
+ ALOG(LOG_VERBOSE, LOG_TAG, "nativeOpenHal()\n");
+ int err;
+ const hw_module_t *hw_module = NULL;
+ if (0 != (err = hw_get_module(FINGERPRINT_HARDWARE_MODULE_ID, &hw_module))) {
+ ALOGE("Can't open fingerprint HW Module, error: %d", err);
+ return 0;
+ }
+ if (NULL == hw_module) {
+ ALOGE("No valid fingerprint module");
+ return 0;
+ }
+
+ gContext.module = reinterpret_cast<const fingerprint_module_t*>(hw_module);
+
+ if (gContext.module->common.methods->open == NULL) {
+ ALOGE("No valid open method");
+ return 0;
+ }
+
+ hw_device_t *device = NULL;
+
+ if (0 != (err = gContext.module->common.methods->open(hw_module, NULL, &device))) {
+ ALOGE("Can't open fingerprint methods, error: %d", err);
+ return 0;
+ }
+
+ if (kVersion != device->version) {
+ ALOGE("Wrong fp version. Expected %d, got %d", kVersion, device->version);
+ // return 0; // FIXME
+ }
+
+ gContext.device = reinterpret_cast<fingerprint_device_t*>(device);
+ err = gContext.device->set_notify(gContext.device, hal_notify_callback);
+ if (err < 0) {
+ ALOGE("Failed in call to set_notify(), err=%d", err);
+ return 0;
+ }
+
+ // Sanity check - remove
+ if (gContext.device->notify != hal_notify_callback) {
+ ALOGE("NOTIFY not set properly: %p != %p", gContext.device->notify, hal_notify_callback);
+ }
+
+ ALOG(LOG_VERBOSE, LOG_TAG, "fingerprint HAL successfully initialized");
+ return reinterpret_cast<jlong>(gContext.device);
+}
+
+static jint nativeCloseHal(JNIEnv* env, jobject clazz) {
+ return -ENOSYS; // TODO
}
// ----------------------------------------------------------------------------
+// TODO: clean up void methods
static const JNINativeMethod g_methods[] = {
{ "nativeEnroll", "(I)I", (void*)nativeEnroll },
+ { "nativeEnrollCancel", "()I", (void*)nativeEnroll },
{ "nativeRemove", "(I)I", (void*)nativeRemove },
+ { "nativeOpenHal", "()I", (void*)nativeOpenHal },
+ { "nativeCloseHal", "()I", (void*)nativeCloseHal },
+ { "nativeInit", "(Lcom/android/server/fingerprint/FingerprintService;)V", (void*)nativeInit }
};
-#define FIND_CLASS(var, className) \
- var = env->FindClass(className); \
- LOG_FATAL_IF(! var, "Unable to find class " className); \
- var = jclass(env->NewGlobalRef(var));
-
-#define GET_STATIC_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
- var = env->GetStaticMethodID(clazz, methodName, fieldDescriptor); \
- LOG_FATAL_IF(! var, "Unable to find static method" methodName);
-
-#define GET_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
- var = env->GetMethodID(clazz, methodName, fieldDescriptor); \
- LOG_FATAL_IF(! var, "Unable to find method" methodName);
-
-#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
- var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
- LOG_FATAL_IF(! var, "Unable to find field " fieldName);
-
-int register_android_server_FingerprintManager(JNIEnv* env) {
- FIND_CLASS(gFingerprintManagerClassInfo.clazz,
- "android/service/fingerprint/FingerprintManager");
- GET_METHOD_ID(gFingerprintManagerClassInfo.notify, gFingerprintManagerClassInfo.clazz,
- "notify", "(III)V");
- return AndroidRuntime::registerNativeMethods(
- env, "com/android/service/fingerprint/FingerprintManager", g_methods, NELEM(g_methods));
+int register_android_server_fingerprint_FingerprintService(JNIEnv* env) {
+ FIND_CLASS(gFingerprintServiceClassInfo.clazz, FINGERPRINT_SERVICE);
+ GET_METHOD_ID(gFingerprintServiceClassInfo.notify, gFingerprintServiceClassInfo.clazz, "notify",
+ "(III)V");
+ int result = AndroidRuntime::registerNativeMethods(
+ env, FINGERPRINT_SERVICE, g_methods, NELEM(g_methods));
+ ALOG(LOG_VERBOSE, LOG_TAG, "FingerprintManager JNI ready.\n");
+ return result;
}
} // namespace android
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 01f4d3a..a6b65cc 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -45,6 +45,8 @@
#define POLICY_DEBUG 0
#define GUARD_THREAD_PRIORITY 0
+#define DEBUG_PROC(x) //x
+
using namespace android;
#if GUARD_THREAD_PRIORITY
@@ -725,6 +727,7 @@ jboolean android_os_Process_parseProcLineArray(JNIEnv* env, jobject clazz,
const char term = (char)(mode&PROC_TERM_MASK);
const jsize start = i;
if (i >= endIndex) {
+ DEBUG_PROC(ALOGW("Ran off end of data @%d", i));
res = JNI_FALSE;
break;
}
@@ -822,19 +825,20 @@ jboolean android_os_Process_readProcFile(JNIEnv* env, jobject clazz,
return JNI_FALSE;
}
int fd = open(file8, O_RDONLY);
- env->ReleaseStringUTFChars(file, file8);
if (fd < 0) {
- //ALOGW("Unable to open process file: %s\n", file8);
+ DEBUG_PROC(ALOGW("Unable to open process file: %s\n", file8));
+ env->ReleaseStringUTFChars(file, file8);
return JNI_FALSE;
}
+ env->ReleaseStringUTFChars(file, file8);
char buffer[256];
const int len = read(fd, buffer, sizeof(buffer)-1);
close(fd);
if (len < 0) {
- //ALOGW("Unable to open process file: %s fd=%d\n", file8, fd);
+ DEBUG_PROC(ALOGW("Unable to open process file: %s fd=%d\n", file8, fd));
return JNI_FALSE;
}
buffer[len] = 0;
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index d032cb6..2a1fd1b 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -20,15 +20,10 @@
#include "GraphicsJNI.h"
#include <nativehelper/JNIHelp.h>
-#include "android_view_GraphicBuffer.h"
-
#include <android_runtime/AndroidRuntime.h>
-#include <android_runtime/android_graphics_SurfaceTexture.h>
#include <androidfw/ResourceTypes.h>
-#include <gui/GLConsumer.h>
-
#include <private/hwui/DrawGlInfo.h>
#include <cutils/properties.h>
@@ -37,15 +32,13 @@
#include <SkCanvas.h>
#include <SkMatrix.h>
#include <SkPaint.h>
+#include <SkPorterDuff.h>
#include <SkRegion.h>
#include <SkScalerContext.h>
#include <SkTemplates.h>
#include <SkXfermode.h>
#include <DisplayListRenderer.h>
-#include <LayerRenderer.h>
-#include <OpenGLRenderer.h>
-#include <Stencil.h>
#include <Rect.h>
#include <RenderNode.h>
#include <CanvasProperty.h>
@@ -64,7 +57,7 @@ namespace android {
using namespace uirenderer;
/**
- * Note: OpenGLRenderer JNI layer is generated and compiled only on supported
+ * Note: DisplayListRenderer JNI layer is generated and compiled only on supported
* devices. This means all the logic must be compiled only when the
* preprocessor variable USE_OPENGL_RENDERER is defined.
*/
@@ -91,57 +84,13 @@ static struct {
} gRectClassInfo;
// ----------------------------------------------------------------------------
-// Caching
-// ----------------------------------------------------------------------------
-
-static void android_view_GLES20Canvas_flushCaches(JNIEnv* env, jobject clazz,
- jint mode) {
- if (Caches::hasInstance()) {
- Caches::getInstance().flush(static_cast<Caches::FlushMode>(mode));
- }
-}
-
-static jboolean android_view_GLES20Canvas_initCaches(JNIEnv* env, jobject clazz) {
- if (Caches::hasInstance()) {
- return Caches::getInstance().init() ? JNI_TRUE : JNI_FALSE;
- }
- return JNI_FALSE;
-}
-
-static void android_view_GLES20Canvas_terminateCaches(JNIEnv* env, jobject clazz) {
- if (Caches::hasInstance()) {
- Caches::getInstance().terminate();
- }
-}
-
-// ----------------------------------------------------------------------------
-// Caching
-// ----------------------------------------------------------------------------
-
-static void android_view_GLES20Canvas_initAtlas(JNIEnv* env, jobject clazz,
- jobject graphicBuffer, jlongArray atlasMapArray, jint count) {
-
- sp<GraphicBuffer> buffer = graphicBufferForJavaObject(env, graphicBuffer);
- jlong* jAtlasMap = env->GetLongArrayElements(atlasMapArray, NULL);
- Caches::getInstance().assetAtlas.init(buffer, jAtlasMap, count);
- env->ReleaseLongArrayElements(atlasMapArray, jAtlasMap, 0);
-}
-
-// ----------------------------------------------------------------------------
// Constructors
// ----------------------------------------------------------------------------
-static jlong android_view_GLES20Canvas_createRenderer(JNIEnv* env, jobject clazz) {
- RENDERER_LOGD("Create OpenGLRenderer");
- OpenGLRenderer* renderer = new OpenGLRenderer();
- renderer->initProperties();
- return reinterpret_cast<jlong>(renderer);
-}
-
static void android_view_GLES20Canvas_destroyRenderer(JNIEnv* env, jobject clazz,
jlong rendererPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
- RENDERER_LOGD("Destroy OpenGLRenderer");
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
+ RENDERER_LOGD("Destroy DisplayListRenderer");
delete renderer;
}
@@ -151,33 +100,29 @@ static void android_view_GLES20Canvas_destroyRenderer(JNIEnv* env, jobject clazz
static void android_view_GLES20Canvas_setViewport(JNIEnv* env, jobject clazz,
jlong rendererPtr, jint width, jint height) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
renderer->setViewport(width, height);
}
static int android_view_GLES20Canvas_prepare(JNIEnv* env, jobject clazz,
jlong rendererPtr, jboolean opaque) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
return renderer->prepare(opaque);
}
static int android_view_GLES20Canvas_prepareDirty(JNIEnv* env, jobject clazz,
jlong rendererPtr, jint left, jint top, jint right, jint bottom,
jboolean opaque) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
return renderer->prepareDirty(left, top, right, bottom, opaque);
}
static void android_view_GLES20Canvas_finish(JNIEnv* env, jobject clazz,
jlong rendererPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
renderer->finish();
}
-static jint android_view_GLES20Canvas_getStencilSize(JNIEnv* env, jobject clazz) {
- return Stencil::getStencilSize();
-}
-
static void android_view_GLES20Canvas_setProperty(JNIEnv* env,
jobject clazz, jstring name, jstring value) {
if (!Caches::hasInstance()) {
@@ -202,7 +147,7 @@ static void android_view_GLES20Canvas_setProperty(JNIEnv* env,
static jint android_view_GLES20Canvas_callDrawGLFunction(JNIEnv* env, jobject clazz,
jlong rendererPtr, jlong functorPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
Functor* functor = reinterpret_cast<Functor*>(functorPtr);
android::uirenderer::Rect dirty;
return renderer->callDrawGLFunction(functor, dirty);
@@ -226,25 +171,25 @@ static jint android_view_GLES20Canvas_getMaxTextureHeight(JNIEnv* env, jobject c
static jint android_view_GLES20Canvas_save(JNIEnv* env, jobject clazz, jlong rendererPtr,
jint flags) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
return renderer->save(flags);
}
static jint android_view_GLES20Canvas_getSaveCount(JNIEnv* env, jobject clazz,
jlong rendererPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
return renderer->getSaveCount();
}
static void android_view_GLES20Canvas_restore(JNIEnv* env, jobject clazz,
jlong rendererPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
renderer->restore();
}
static void android_view_GLES20Canvas_restoreToCount(JNIEnv* env, jobject clazz,
jlong rendererPtr, jint saveCount) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
renderer->restoreToCount(saveCount);
}
@@ -255,14 +200,14 @@ static void android_view_GLES20Canvas_restoreToCount(JNIEnv* env, jobject clazz,
static jint android_view_GLES20Canvas_saveLayer(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
jlong paintPtr, jint saveFlags) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
return renderer->saveLayer(left, top, right, bottom, paint, saveFlags);
}
static jint android_view_GLES20Canvas_saveLayerClip(JNIEnv* env, jobject clazz,
jlong rendererPtr, jlong paintPtr, jint saveFlags) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds());
return renderer->saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom,
@@ -272,13 +217,13 @@ static jint android_view_GLES20Canvas_saveLayerClip(JNIEnv* env, jobject clazz,
static jint android_view_GLES20Canvas_saveLayerAlpha(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
jint alpha, jint saveFlags) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
return renderer->saveLayerAlpha(left, top, right, bottom, alpha, saveFlags);
}
static jint android_view_GLES20Canvas_saveLayerAlphaClip(JNIEnv* env, jobject clazz,
jlong rendererPtr, jint alpha, jint saveFlags) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds());
return renderer->saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
alpha, saveFlags);
@@ -290,7 +235,7 @@ static jint android_view_GLES20Canvas_saveLayerAlphaClip(JNIEnv* env, jobject cl
static jboolean android_view_GLES20Canvas_quickReject(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
const bool result = renderer->quickRejectConservative(left, top, right, bottom);
return result ? JNI_TRUE : JNI_FALSE;
}
@@ -298,7 +243,7 @@ static jboolean android_view_GLES20Canvas_quickReject(JNIEnv* env, jobject clazz
static jboolean android_view_GLES20Canvas_clipRectF(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
jint op) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
const bool result = renderer->clipRect(left, top, right, bottom,
static_cast<SkRegion::Op>(op));
return result ? JNI_TRUE : JNI_FALSE;
@@ -307,7 +252,7 @@ static jboolean android_view_GLES20Canvas_clipRectF(JNIEnv* env, jobject clazz,
static jboolean android_view_GLES20Canvas_clipRect(JNIEnv* env, jobject clazz,
jlong rendererPtr, jint left, jint top, jint right, jint bottom,
jint op) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
const bool result = renderer->clipRect(float(left), float(top), float(right),
float(bottom),
static_cast<SkRegion::Op>(op));
@@ -316,7 +261,7 @@ static jboolean android_view_GLES20Canvas_clipRect(JNIEnv* env, jobject clazz,
static jboolean android_view_GLES20Canvas_clipPath(JNIEnv* env, jobject clazz,
jlong rendererPtr, jlong pathPtr, jint op) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
const bool result = renderer->clipPath(path, static_cast<SkRegion::Op>(op));
return result ? JNI_TRUE : JNI_FALSE;
@@ -324,7 +269,7 @@ static jboolean android_view_GLES20Canvas_clipPath(JNIEnv* env, jobject clazz,
static jboolean android_view_GLES20Canvas_clipRegion(JNIEnv* env, jobject clazz,
jlong rendererPtr, jlong regionPtr, jint op) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkRegion* region = reinterpret_cast<SkRegion*>(regionPtr);
const bool result = renderer->clipRegion(region, static_cast<SkRegion::Op>(op));
return result ? JNI_TRUE : JNI_FALSE;
@@ -332,7 +277,7 @@ static jboolean android_view_GLES20Canvas_clipRegion(JNIEnv* env, jobject clazz,
static jboolean android_view_GLES20Canvas_getClipBounds(JNIEnv* env, jobject clazz,
jlong rendererPtr, jobject rect) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds());
env->CallVoidMethod(rect, gRectClassInfo.set,
@@ -347,47 +292,47 @@ static jboolean android_view_GLES20Canvas_getClipBounds(JNIEnv* env, jobject cla
static void android_view_GLES20Canvas_translate(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloat dx, jfloat dy) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
renderer->translate(dx, dy);
}
static void android_view_GLES20Canvas_rotate(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloat degrees) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
renderer->rotate(degrees);
}
static void android_view_GLES20Canvas_scale(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloat sx, jfloat sy) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
renderer->scale(sx, sy);
}
static void android_view_GLES20Canvas_skew(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloat sx, jfloat sy) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
renderer->skew(sx, sy);
}
static void android_view_GLES20Canvas_setMatrix(JNIEnv* env, jobject clazz,
jlong rendererPtr, jlong matrixPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
- renderer->setMatrix(matrix);
+ renderer->setMatrix(matrix ? *matrix : SkMatrix::I());
}
static void android_view_GLES20Canvas_getMatrix(JNIEnv* env, jobject clazz,
jlong rendererPtr, jlong matrixPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
renderer->getMatrix(matrix);
}
static void android_view_GLES20Canvas_concatMatrix(JNIEnv* env, jobject clazz,
jlong rendererPtr, jlong matrixPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
- renderer->concatMatrix(matrix);
+ renderer->concatMatrix(*matrix);
}
// ----------------------------------------------------------------------------
@@ -401,7 +346,7 @@ static void android_view_GLES20Canvas_drawBitmap(JNIEnv* env, jobject clazz,
// This object allows the renderer to allocate a global JNI ref to the buffer object.
JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
renderer->drawBitmap(bitmap, left, top, paint);
}
@@ -414,7 +359,7 @@ static void android_view_GLES20Canvas_drawBitmapRect(JNIEnv* env, jobject clazz,
// This object allows the renderer to allocate a global JNI ref to the buffer object.
JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
renderer->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
dstLeft, dstTop, dstRight, dstBottom, paint);
@@ -427,20 +372,20 @@ static void android_view_GLES20Canvas_drawBitmapMatrix(JNIEnv* env, jobject claz
// This object allows the renderer to allocate a global JNI ref to the buffer object.
JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
- renderer->drawBitmap(bitmap, matrix, paint);
+ renderer->drawBitmap(bitmap, *matrix, paint);
}
static void android_view_GLES20Canvas_drawBitmapData(JNIEnv* env, jobject clazz,
jlong rendererPtr, jintArray colors, jint offset, jint stride,
jfloat left, jfloat top, jint width, jint height, jboolean hasAlpha, jlong paintPtr) {
+ const SkImageInfo info = SkImageInfo::Make(width, height,
+ hasAlpha ? kN32_SkColorType : kRGB_565_SkColorType,
+ kPremul_SkAlphaType);
SkBitmap* bitmap = new SkBitmap;
- bitmap->setConfig(hasAlpha ? SkBitmap::kARGB_8888_Config : SkBitmap::kRGB_565_Config,
- width, height);
-
- if (!bitmap->allocPixels()) {
+ if (!bitmap->allocPixels(info)) {
delete bitmap;
return;
}
@@ -450,7 +395,7 @@ static void android_view_GLES20Canvas_drawBitmapData(JNIEnv* env, jobject clazz,
return;
}
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
renderer->drawBitmapData(bitmap, left, top, paint);
@@ -471,7 +416,7 @@ static void android_view_GLES20Canvas_drawBitmapMesh(JNIEnv* env, jobject clazz,
jfloat* verticesArray = vertices ? env->GetFloatArrayElements(vertices, NULL) + offset : NULL;
jint* colorsArray = colors ? env->GetIntArrayElements(colors, NULL) + colorOffset : NULL;
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
renderer->drawBitmapMesh(bitmap, meshWidth, meshHeight, verticesArray, colorsArray, paint);
@@ -486,22 +431,23 @@ static void android_view_GLES20Canvas_drawPatch(JNIEnv* env, jobject clazz,
// This object allows the renderer to allocate a global JNI ref to the buffer object.
JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
Res_png_9patch* patch = reinterpret_cast<Res_png_9patch*>(patchPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
renderer->drawPatch(bitmap, patch, left, top, right, bottom, paint);
}
static void android_view_GLES20Canvas_drawColor(JNIEnv* env, jobject clazz,
- jlong rendererPtr, jint color, jint mode) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
- renderer->drawColor(color, static_cast<SkXfermode::Mode>(mode));
+ jlong rendererPtr, jint color, jint modeHandle) {
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
+ SkPorterDuff::Mode mode = static_cast<SkPorterDuff::Mode>(modeHandle);
+ renderer->drawColor(color, SkPorterDuff::ToXfermodeMode(mode));
}
static void android_view_GLES20Canvas_drawRect(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
jlong paintPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
renderer->drawRect(left, top, right, bottom, paint);
}
@@ -509,21 +455,21 @@ static void android_view_GLES20Canvas_drawRect(JNIEnv* env, jobject clazz,
static void android_view_GLES20Canvas_drawRoundRect(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
jfloat rx, jfloat ry, jlong paintPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
renderer->drawRoundRect(left, top, right, bottom, rx, ry, paint);
}
static void android_view_GLES20Canvas_drawCircle(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloat x, jfloat y, jfloat radius, jlong paintPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
renderer->drawCircle(x, y, radius, paint);
}
static void android_view_GLES20Canvas_drawCircleProps(JNIEnv* env, jobject clazz,
jlong rendererPtr, jlong xPropPtr, jlong yPropPtr, jlong radiusPropPtr, jlong paintPropPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
CanvasPropertyPrimitive* xProp = reinterpret_cast<CanvasPropertyPrimitive*>(xPropPtr);
CanvasPropertyPrimitive* yProp = reinterpret_cast<CanvasPropertyPrimitive*>(yPropPtr);
CanvasPropertyPrimitive* radiusProp = reinterpret_cast<CanvasPropertyPrimitive*>(radiusPropPtr);
@@ -534,7 +480,7 @@ static void android_view_GLES20Canvas_drawCircleProps(JNIEnv* env, jobject clazz
static void android_view_GLES20Canvas_drawOval(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
jlong paintPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
renderer->drawOval(left, top, right, bottom, paint);
}
@@ -542,14 +488,14 @@ static void android_view_GLES20Canvas_drawOval(JNIEnv* env, jobject clazz,
static void android_view_GLES20Canvas_drawArc(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
jfloat startAngle, jfloat sweepAngle, jboolean useCenter, jlong paintPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
renderer->drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint);
}
static void android_view_GLES20Canvas_drawRegionAsRects(JNIEnv* env, jobject clazz,
jlong rendererPtr, jlong regionPtr, jlong paintPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkRegion* region = reinterpret_cast<SkRegion*>(regionPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
if (paint->getStyle() != SkPaint::kFill_Style ||
@@ -577,18 +523,9 @@ static void android_view_GLES20Canvas_drawRegionAsRects(JNIEnv* env, jobject cla
}
}
-static void android_view_GLES20Canvas_drawRects(JNIEnv* env, jobject clazz,
- jlong rendererPtr, jfloatArray rects, jint count, jlong paintPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
- jfloat* storage = env->GetFloatArrayElements(rects, NULL);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
- renderer->drawRects(storage, count, paint);
- env->ReleaseFloatArrayElements(rects, storage, 0);
-}
-
static void android_view_GLES20Canvas_drawPoints(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloatArray points, jint offset, jint count, jlong paintPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
jfloat* storage = env->GetFloatArrayElements(points, NULL);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
renderer->drawPoints(storage + offset, count, paint);
@@ -597,7 +534,7 @@ static void android_view_GLES20Canvas_drawPoints(JNIEnv* env, jobject clazz,
static void android_view_GLES20Canvas_drawPath(JNIEnv* env, jobject clazz,
jlong rendererPtr, jlong pathPtr, jlong paintPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
renderer->drawPath(path, paint);
@@ -605,7 +542,7 @@ static void android_view_GLES20Canvas_drawPath(JNIEnv* env, jobject clazz,
static void android_view_GLES20Canvas_drawLines(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloatArray points, jint offset, jint count, jlong paintPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
jfloat* storage = env->GetFloatArrayElements(points, NULL);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
renderer->drawLines(storage + offset, count, paint);
@@ -618,13 +555,13 @@ static void android_view_GLES20Canvas_drawLines(JNIEnv* env, jobject clazz,
static void android_view_GLES20Canvas_setupPaintFilter(JNIEnv* env, jobject clazz,
jlong rendererPtr, jint clearBits, jint setBits) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
renderer->setupPaintFilter(clearBits, setBits);
}
static void android_view_GLES20Canvas_resetPaintFilter(JNIEnv* env, jobject clazz,
jlong rendererPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
renderer->resetPaintFilter();
}
@@ -651,7 +588,7 @@ static float xOffsetForTextAlign(SkPaint* paint, float totalAdvance) {
class RenderTextFunctor {
public:
- RenderTextFunctor(const Layout& layout, OpenGLRenderer* renderer, jfloat x, jfloat y,
+ RenderTextFunctor(const Layout& layout, DisplayListRenderer* renderer, jfloat x, jfloat y,
SkPaint* paint, uint16_t* glyphs, float* pos, float totalAdvance,
uirenderer::Rect& bounds)
: layout(layout), renderer(renderer), x(x), y(y), paint(paint), glyphs(glyphs),
@@ -669,7 +606,7 @@ public:
}
private:
const Layout& layout;
- OpenGLRenderer* renderer;
+ DisplayListRenderer* renderer;
jfloat x;
jfloat y;
SkPaint* paint;
@@ -679,7 +616,7 @@ private:
uirenderer::Rect& bounds;
};
-static void renderTextLayout(OpenGLRenderer* renderer, Layout* layout,
+static void renderTextLayout(DisplayListRenderer* renderer, Layout* layout,
jfloat x, jfloat y, SkPaint* paint) {
size_t nGlyphs = layout->nGlyphs();
float* pos = new float[nGlyphs * 2];
@@ -697,17 +634,17 @@ static void renderTextLayout(OpenGLRenderer* renderer, Layout* layout,
}
#endif
-static void renderText(OpenGLRenderer* renderer, const jchar* text, int count,
- jfloat x, jfloat y, int flags, SkPaint* paint, TypefaceImpl* typeface) {
+static void renderText(DisplayListRenderer* renderer, const jchar* text, int count,
+ jfloat x, jfloat y, int bidiFlags, SkPaint* paint, TypefaceImpl* typeface) {
#ifdef USE_MINIKIN
Layout layout;
- std::string css = MinikinUtils::setLayoutProperties(&layout, paint, flags, typeface);
+ std::string css = MinikinUtils::setLayoutProperties(&layout, paint, bidiFlags, typeface);
layout.doLayout(text, 0, count, count, css);
x += xOffsetForTextAlign(paint, layout.getAdvance());
renderTextLayout(renderer, &layout, x, y, paint);
#else
sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
- text, 0, count, count, flags);
+ text, 0, count, count, bidiFlags);
if (value == NULL) {
return;
}
@@ -726,10 +663,50 @@ static void renderText(OpenGLRenderer* renderer, const jchar* text, int count,
#endif
}
-static void renderTextOnPath(OpenGLRenderer* renderer, const jchar* text, int count,
- SkPath* path, jfloat hOffset, jfloat vOffset, int flags, SkPaint* paint) {
+#ifdef USE_MINIKIN
+class RenderTextOnPathFunctor {
+public:
+ RenderTextOnPathFunctor(const Layout& layout, DisplayListRenderer* renderer, float hOffset,
+ float vOffset, SkPaint* paint, SkPath* path)
+ : layout(layout), renderer(renderer), hOffset(hOffset), vOffset(vOffset),
+ paint(paint), path(path) {
+ }
+ void operator()(size_t start, size_t end) {
+ uint16_t glyphs[1];
+ for (size_t i = start; i < end; i++) {
+ glyphs[0] = layout.getGlyphId(i);
+ float x = hOffset + layout.getX(i);
+ float y = vOffset + layout.getY(i);
+ renderer->drawTextOnPath((const char*) glyphs, sizeof(glyphs), 1, path, x, y, paint);
+ }
+ }
+private:
+ const Layout& layout;
+ DisplayListRenderer* renderer;
+ float hOffset;
+ float vOffset;
+ SkPaint* paint;
+ SkPath* path;
+};
+#endif
+
+static void renderTextOnPath(DisplayListRenderer* renderer, const jchar* text, int count,
+ SkPath* path, jfloat hOffset, jfloat vOffset, int bidiFlags, SkPaint* paint,
+ TypefaceImpl* typeface) {
+#ifdef USE_MINIKIN
+ Layout layout;
+ std::string css = MinikinUtils::setLayoutProperties(&layout, paint, bidiFlags, typeface);
+ layout.doLayout(text, 0, count, count, css);
+ hOffset += MinikinUtils::hOffsetForTextAlign(paint, layout, *path);
+ SkPaint::Align align = paint->getTextAlign();
+ paint->setTextAlign(SkPaint::kLeft_Align);
+
+ RenderTextOnPathFunctor f(layout, renderer, hOffset, vOffset, paint, path);
+ MinikinUtils::forFontRun(layout, paint, f);
+ paint->setTextAlign(align);
+#else
sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
- text, 0, count, count, flags);
+ text, 0, count, count, bidiFlags);
if (value == NULL) {
return;
}
@@ -738,20 +715,21 @@ static void renderTextOnPath(OpenGLRenderer* renderer, const jchar* text, int co
int bytesCount = glyphsCount * sizeof(jchar);
renderer->drawTextOnPath((const char*) glyphs, bytesCount, glyphsCount, path,
hOffset, vOffset, paint);
+#endif
}
-static void renderTextRun(OpenGLRenderer* renderer, const jchar* text,
+static void renderTextRun(DisplayListRenderer* renderer, const jchar* text,
jint start, jint count, jint contextCount, jfloat x, jfloat y,
- int flags, SkPaint* paint, TypefaceImpl* typeface) {
+ int bidiFlags, SkPaint* paint, TypefaceImpl* typeface) {
#ifdef USE_MINIKIN
Layout layout;
- std::string css = MinikinUtils::setLayoutProperties(&layout, paint, flags, typeface);
+ std::string css = MinikinUtils::setLayoutProperties(&layout, paint, bidiFlags, typeface);
layout.doLayout(text, start, count, contextCount, css);
x += xOffsetForTextAlign(paint, layout.getAdvance());
renderTextLayout(renderer, &layout, x, y, paint);
#else
sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
- text, start, count, contextCount, flags);
+ text, start, count, contextCount, bidiFlags);
if (value == NULL) {
return;
}
@@ -772,124 +750,87 @@ static void renderTextRun(OpenGLRenderer* renderer, const jchar* text,
static void android_view_GLES20Canvas_drawTextArray(JNIEnv* env, jobject clazz,
jlong rendererPtr, jcharArray text, jint index, jint count,
- jfloat x, jfloat y, jint flags, jlong paintPtr, jlong typefacePtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ jfloat x, jfloat y, jint bidiFlags, jlong paintPtr, jlong typefacePtr) {
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
jchar* textArray = env->GetCharArrayElements(text, NULL);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
- renderText(renderer, textArray + index, count, x, y, flags, paint, typeface);
+ renderText(renderer, textArray + index, count, x, y, bidiFlags, paint, typeface);
env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
}
static void android_view_GLES20Canvas_drawText(JNIEnv* env, jobject clazz,
jlong rendererPtr, jstring text, jint start, jint end,
- jfloat x, jfloat y, jint flags, jlong paintPtr, jlong typefacePtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ jfloat x, jfloat y, jint bidiFlags, jlong paintPtr, jlong typefacePtr) {
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
const jchar* textArray = env->GetStringChars(text, NULL);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
- renderText(renderer, textArray + start, end - start, x, y, flags, paint, typeface);
+ renderText(renderer, textArray + start, end - start, x, y, bidiFlags, paint, typeface);
env->ReleaseStringChars(text, textArray);
}
static void android_view_GLES20Canvas_drawTextArrayOnPath(JNIEnv* env, jobject clazz,
jlong rendererPtr, jcharArray text, jint index, jint count,
- jlong pathPtr, jfloat hOffset, jfloat vOffset, jint flags, jlong paintPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ jlong pathPtr, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintPtr,
+ jlong typefacePtr) {
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
jchar* textArray = env->GetCharArrayElements(text, NULL);
SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
+ TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
renderTextOnPath(renderer, textArray + index, count, path,
- hOffset, vOffset, flags, paint);
+ hOffset, vOffset, bidiFlags, paint, typeface);
env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
}
static void android_view_GLES20Canvas_drawTextOnPath(JNIEnv* env, jobject clazz,
jlong rendererPtr, jstring text, jint start, jint end,
- jlong pathPtr, jfloat hOffset, jfloat vOffset, jint flags, jlong paintPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ jlong pathPtr, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintPtr,
+ jlong typefacePtr) {
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
const jchar* textArray = env->GetStringChars(text, NULL);
SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
+ TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
renderTextOnPath(renderer, textArray + start, end - start, path,
- hOffset, vOffset, flags, paint);
+ hOffset, vOffset, bidiFlags, paint, typeface);
env->ReleaseStringChars(text, textArray);
}
static void android_view_GLES20Canvas_drawTextRunArray(JNIEnv* env, jobject clazz,
jlong rendererPtr, jcharArray text, jint index, jint count,
- jint contextIndex, jint contextCount, jfloat x, jfloat y, jint dirFlags,
+ jint contextIndex, jint contextCount, jfloat x, jfloat y, jboolean isRtl,
jlong paintPtr, jlong typefacePtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
jchar* textArray = env->GetCharArrayElements(text, NULL);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
+ int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
renderTextRun(renderer, textArray + contextIndex, index - contextIndex,
- count, contextCount, x, y, dirFlags, paint, typeface);
+ count, contextCount, x, y, bidiFlags, paint, typeface);
env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
}
static void android_view_GLES20Canvas_drawTextRun(JNIEnv* env, jobject clazz,
jlong rendererPtr, jstring text, jint start, jint end,
- jint contextStart, int contextEnd, jfloat x, jfloat y, jint dirFlags,
+ jint contextStart, int contextEnd, jfloat x, jfloat y, jboolean isRtl,
jlong paintPtr, jlong typefacePtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
const jchar* textArray = env->GetStringChars(text, NULL);
jint count = end - start;
jint contextCount = contextEnd - contextStart;
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
+ int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
renderTextRun(renderer, textArray + contextStart, start - contextStart,
- count, contextCount, x, y, dirFlags, paint, typeface);
- env->ReleaseStringChars(text, textArray);
-}
-
-static void renderPosText(OpenGLRenderer* renderer, const jchar* text, int count,
- const jfloat* positions, jint dirFlags, SkPaint* paint) {
- sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
- text, 0, count, count, dirFlags);
- if (value == NULL) {
- return;
- }
- const jchar* glyphs = value->getGlyphs();
- size_t glyphsCount = value->getGlyphsCount();
- if (count < int(glyphsCount)) glyphsCount = count;
- int bytesCount = glyphsCount * sizeof(jchar);
-
- renderer->drawPosText((const char*) glyphs, bytesCount, glyphsCount, positions, paint);
-}
-
-static void android_view_GLES20Canvas_drawPosTextArray(JNIEnv* env, jobject clazz,
- jlong rendererPtr, jcharArray text, jint index, jint count,
- jfloatArray pos, jlong paintPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
- jchar* textArray = env->GetCharArrayElements(text, NULL);
- jfloat* positions = env->GetFloatArrayElements(pos, NULL);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
-
- renderPosText(renderer, textArray + index, count, positions, kBidi_LTR, paint);
-
- env->ReleaseFloatArrayElements(pos, positions, JNI_ABORT);
- env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
-}
-
-static void android_view_GLES20Canvas_drawPosText(JNIEnv* env, jobject clazz,
- jlong rendererPtr, jstring text, jint start, jint end,
- jfloatArray pos, jlong paintPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
- const jchar* textArray = env->GetStringChars(text, NULL);
- jfloat* positions = env->GetFloatArrayElements(pos, NULL);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
-
- renderPosText(renderer, textArray + start, end - start, positions, kBidi_LTR, paint);
-
- env->ReleaseFloatArrayElements(pos, positions, JNI_ABORT);
+ count, contextCount, x, y, bidiFlags, paint, typeface);
env->ReleaseStringChars(text, textArray);
}
@@ -907,13 +848,13 @@ static jlong android_view_GLES20Canvas_createDisplayListRenderer(JNIEnv* env, jo
return reinterpret_cast<jlong>(new DisplayListRenderer);
}
-static jint android_view_GLES20Canvas_drawDisplayList(JNIEnv* env,
- jobject clazz, jlong rendererPtr, jlong displayListPtr,
+static jint android_view_GLES20Canvas_drawRenderNode(JNIEnv* env,
+ jobject clazz, jlong rendererPtr, jlong renderNodePtr,
jobject dirty, jint flags) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
- RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
+ RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
android::uirenderer::Rect bounds;
- status_t status = renderer->drawDisplayList(displayList, bounds, flags);
+ status_t status = renderer->drawRenderNode(renderNode, bounds, flags);
if (status != DrawGlInfo::kStatusDone && dirty != NULL) {
env->CallVoidMethod(dirty, gRectClassInfo.set,
int(bounds.left), int(bounds.top), int(bounds.right), int(bounds.bottom));
@@ -927,44 +868,11 @@ static jint android_view_GLES20Canvas_drawDisplayList(JNIEnv* env,
static void android_view_GLES20Canvas_drawLayer(JNIEnv* env, jobject clazz,
jlong rendererPtr, jlong layerPtr, jfloat x, jfloat y) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
Layer* layer = reinterpret_cast<Layer*>(layerPtr);
renderer->drawLayer(layer, x, y);
}
-static jboolean android_view_GLES20Canvas_copyLayer(JNIEnv* env, jobject clazz,
- jlong layerPtr, jlong bitmapPtr) {
- Layer* layer = reinterpret_cast<Layer*>(layerPtr);
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
- return LayerRenderer::copyLayer(layer, bitmap);
-}
-
-static void android_view_GLES20Canvas_pushLayerUpdate(JNIEnv* env, jobject clazz,
- jlong rendererPtr, jlong layerPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
- Layer* layer = reinterpret_cast<Layer*>(layerPtr);
- renderer->pushLayerUpdate(layer);
-}
-
-static void android_view_GLES20Canvas_cancelLayerUpdate(JNIEnv* env, jobject clazz,
- jlong rendererPtr, jlong layerPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
- Layer* layer = reinterpret_cast<Layer*>(layerPtr);
- renderer->cancelLayerUpdate(layer);
-}
-
-static void android_view_GLES20Canvas_clearLayerUpdates(JNIEnv* env, jobject clazz,
- jlong rendererPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
- renderer->clearLayerUpdates();
-}
-
-static void android_view_GLES20Canvas_flushLayerUpdates(JNIEnv* env, jobject clazz,
- jlong rendererPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
- renderer->flushLayerUpdates();
-}
-
#endif // USE_OPENGL_RENDERER
// ----------------------------------------------------------------------------
@@ -1009,14 +917,7 @@ static JNINativeMethod gMethods[] = {
{ "nIsAvailable", "()Z", (void*) android_view_GLES20Canvas_isAvailable },
#ifdef USE_OPENGL_RENDERER
- { "nFlushCaches", "(I)V", (void*) android_view_GLES20Canvas_flushCaches },
- { "nInitCaches", "()Z", (void*) android_view_GLES20Canvas_initCaches },
- { "nTerminateCaches", "()V", (void*) android_view_GLES20Canvas_terminateCaches },
- { "nInitAtlas", "(Landroid/view/GraphicBuffer;[JI)V",
- (void*) android_view_GLES20Canvas_initAtlas },
-
- { "nCreateRenderer", "()J", (void*) android_view_GLES20Canvas_createRenderer },
{ "nDestroyRenderer", "(J)V", (void*) android_view_GLES20Canvas_destroyRenderer },
{ "nSetViewport", "(JII)V", (void*) android_view_GLES20Canvas_setViewport },
{ "nPrepare", "(JZ)I", (void*) android_view_GLES20Canvas_prepare },
@@ -1025,9 +926,6 @@ static JNINativeMethod gMethods[] = {
{ "nSetProperty", "(Ljava/lang/String;Ljava/lang/String;)V",
(void*) android_view_GLES20Canvas_setProperty },
-
- { "nGetStencilSize", "()I", (void*) android_view_GLES20Canvas_getStencilSize },
-
{ "nCallDrawGLFunction", "(JJ)I", (void*) android_view_GLES20Canvas_callDrawGLFunction },
{ "nSave", "(JI)I", (void*) android_view_GLES20Canvas_save },
@@ -1067,7 +965,6 @@ static JNINativeMethod gMethods[] = {
{ "nDrawColor", "(JII)V", (void*) android_view_GLES20Canvas_drawColor },
{ "nDrawRect", "(JFFFFJ)V", (void*) android_view_GLES20Canvas_drawRect },
{ "nDrawRects", "(JJJ)V", (void*) android_view_GLES20Canvas_drawRegionAsRects },
- { "nDrawRects", "(J[FIJ)V", (void*) android_view_GLES20Canvas_drawRects },
{ "nDrawRoundRect", "(JFFFFFFJ)V", (void*) android_view_GLES20Canvas_drawRoundRect },
{ "nDrawCircle", "(JFFFJ)V", (void*) android_view_GLES20Canvas_drawCircle },
{ "nDrawCircle", "(JJJJJ)V", (void*) android_view_GLES20Canvas_drawCircleProps },
@@ -1085,33 +982,22 @@ static JNINativeMethod gMethods[] = {
{ "nDrawText", "(JLjava/lang/String;IIFFIJJ)V",
(void*) android_view_GLES20Canvas_drawText },
- { "nDrawTextOnPath", "(J[CIIJFFIJ)V", (void*) android_view_GLES20Canvas_drawTextArrayOnPath },
- { "nDrawTextOnPath", "(JLjava/lang/String;IIJFFIJ)V",
+ { "nDrawTextOnPath", "(J[CIIJFFIJJ)V", (void*) android_view_GLES20Canvas_drawTextArrayOnPath },
+ { "nDrawTextOnPath", "(JLjava/lang/String;IIJFFIJJ)V",
(void*) android_view_GLES20Canvas_drawTextOnPath },
- { "nDrawTextRun", "(J[CIIIIFFIJJ)V", (void*) android_view_GLES20Canvas_drawTextRunArray },
- { "nDrawTextRun", "(JLjava/lang/String;IIIIFFIJJ)V",
+ { "nDrawTextRun", "(J[CIIIIFFZJJ)V", (void*) android_view_GLES20Canvas_drawTextRunArray },
+ { "nDrawTextRun", "(JLjava/lang/String;IIIIFFZJJ)V",
(void*) android_view_GLES20Canvas_drawTextRun },
- { "nDrawPosText", "(J[CII[FJ)V", (void*) android_view_GLES20Canvas_drawPosTextArray },
- { "nDrawPosText", "(JLjava/lang/String;II[FJ)V",
- (void*) android_view_GLES20Canvas_drawPosText },
-
- { "nGetClipBounds", "(JLandroid/graphics/Rect;)Z",
- (void*) android_view_GLES20Canvas_getClipBounds },
+ { "nGetClipBounds", "(JLandroid/graphics/Rect;)Z", (void*) android_view_GLES20Canvas_getClipBounds },
- { "nFinishRecording", "(J)J", (void*) android_view_GLES20Canvas_finishRecording },
- { "nDrawDisplayList", "(JJLandroid/graphics/Rect;I)I",
- (void*) android_view_GLES20Canvas_drawDisplayList },
+ { "nFinishRecording", "(J)J", (void*) android_view_GLES20Canvas_finishRecording },
+ { "nDrawRenderNode", "(JJLandroid/graphics/Rect;I)I", (void*) android_view_GLES20Canvas_drawRenderNode },
{ "nCreateDisplayListRenderer", "()J", (void*) android_view_GLES20Canvas_createDisplayListRenderer },
{ "nDrawLayer", "(JJFF)V", (void*) android_view_GLES20Canvas_drawLayer },
- { "nCopyLayer", "(JJ)Z", (void*) android_view_GLES20Canvas_copyLayer },
- { "nClearLayerUpdates", "(J)V", (void*) android_view_GLES20Canvas_clearLayerUpdates },
- { "nFlushLayerUpdates", "(J)V", (void*) android_view_GLES20Canvas_flushLayerUpdates },
- { "nPushLayerUpdate", "(JJ)V", (void*) android_view_GLES20Canvas_pushLayerUpdate },
- { "nCancelLayerUpdate", "(JJ)V", (void*) android_view_GLES20Canvas_cancelLayerUpdate },
{ "nGetMaximumTextureWidth", "()I", (void*) android_view_GLES20Canvas_getMaxTextureWidth },
{ "nGetMaximumTextureHeight", "()I", (void*) android_view_GLES20Canvas_getMaxTextureHeight },
diff --git a/core/jni/android_view_GLRenderer.cpp b/core/jni/android_view_GLRenderer.cpp
deleted file mode 100644
index d0269a3..0000000
--- a/core/jni/android_view_GLRenderer.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "GLRenderer"
-
-#include "jni.h"
-#include <nativehelper/JNIHelp.h>
-#include <android_runtime/AndroidRuntime.h>
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <EGL/egl_cache.h>
-
-#include <utils/Timers.h>
-
-#include <private/hwui/DrawGlInfo.h>
-
-#include <Caches.h>
-#include <Extensions.h>
-#include <LayerRenderer.h>
-#include <RenderNode.h>
-
-#ifdef USE_OPENGL_RENDERER
- EGLAPI void EGLAPIENTRY eglBeginFrame(EGLDisplay dpy, EGLSurface surface);
-#endif
-
-namespace android {
-
-/**
- * Note: OpenGLRenderer JNI layer is generated and compiled only on supported
- * devices. This means all the logic must be compiled only when the
- * preprocessor variable USE_OPENGL_RENDERER is defined.
- */
-#ifdef USE_OPENGL_RENDERER
-
-// ----------------------------------------------------------------------------
-// Defines
-// ----------------------------------------------------------------------------
-
-// Debug
-#define DEBUG_RENDERER 0
-
-// Debug
-#if DEBUG_RENDERER
- #define RENDERER_LOGD(...) ALOGD(__VA_ARGS__)
-#else
- #define RENDERER_LOGD(...)
-#endif
-
-// ----------------------------------------------------------------------------
-// Surface and display management
-// ----------------------------------------------------------------------------
-
-static jboolean android_view_GLRenderer_preserveBackBuffer(JNIEnv* env, jobject clazz) {
- EGLDisplay display = eglGetCurrentDisplay();
- EGLSurface surface = eglGetCurrentSurface(EGL_DRAW);
-
- eglGetError();
- eglSurfaceAttrib(display, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED);
-
- EGLint error = eglGetError();
- if (error != EGL_SUCCESS) {
- RENDERER_LOGD("Could not enable buffer preserved swap behavior (%x)", error);
- }
-
- return error == EGL_SUCCESS;
-}
-
-static jboolean android_view_GLRenderer_isBackBufferPreserved(JNIEnv* env, jobject clazz) {
- EGLDisplay display = eglGetCurrentDisplay();
- EGLSurface surface = eglGetCurrentSurface(EGL_DRAW);
- EGLint value;
-
- eglGetError();
- eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &value);
-
- EGLint error = eglGetError();
- if (error != EGL_SUCCESS) {
- RENDERER_LOGD("Could not query buffer preserved swap behavior (%x)", error);
- }
-
- return error == EGL_SUCCESS && value == EGL_BUFFER_PRESERVED;
-}
-
-// ----------------------------------------------------------------------------
-// Tracing and debugging
-// ----------------------------------------------------------------------------
-
-static bool android_view_GLRenderer_loadProperties(JNIEnv* env, jobject clazz) {
- if (uirenderer::Caches::hasInstance()) {
- return uirenderer::Caches::getInstance().initProperties();
- }
- return false;
-}
-
-static void android_view_GLRenderer_beginFrame(JNIEnv* env, jobject clazz,
- jintArray size) {
-
- EGLDisplay display = eglGetCurrentDisplay();
- EGLSurface surface = eglGetCurrentSurface(EGL_DRAW);
-
- if (size) {
- EGLint value;
- jint* storage = env->GetIntArrayElements(size, NULL);
-
- eglQuerySurface(display, surface, EGL_WIDTH, &value);
- storage[0] = value;
-
- eglQuerySurface(display, surface, EGL_HEIGHT, &value);
- storage[1] = value;
-
- env->ReleaseIntArrayElements(size, storage, 0);
- }
-
- eglBeginFrame(display, surface);
-}
-
-static jlong android_view_GLRenderer_getSystemTime(JNIEnv* env, jobject clazz) {
- if (uirenderer::Extensions::getInstance().hasNvSystemTime()) {
- return eglGetSystemTimeNV();
- }
- return systemTime(SYSTEM_TIME_MONOTONIC);
-}
-
-static void android_view_GLRenderer_destroyLayer(JNIEnv* env, jobject clazz,
- jlong layerPtr) {
- using namespace android::uirenderer;
- Layer* layer = reinterpret_cast<Layer*>(layerPtr);
- LayerRenderer::destroyLayer(layer);
-}
-
-static void android_view_GLRenderer_prepareTree(JNIEnv* env, jobject clazz,
- jlong renderNodePtr) {
- using namespace android::uirenderer;
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- TreeInfo ignoredInfo;
- renderNode->prepareTree(ignoredInfo);
-}
-
-static void android_view_GLRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
- jlong functorPtr, jboolean hasContext) {
- using namespace android::uirenderer;
- Functor* functor = reinterpret_cast<Functor*>(functorPtr);
- DrawGlInfo::Mode mode = hasContext ? DrawGlInfo::kModeProcess : DrawGlInfo::kModeProcessNoContext;
- (*functor)(mode, NULL);
-}
-
-#endif // USE_OPENGL_RENDERER
-
-// ----------------------------------------------------------------------------
-// Shaders
-// ----------------------------------------------------------------------------
-
-static void android_view_GLRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz,
- jstring diskCachePath) {
-
- const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL);
- egl_cache_t::get()->setCacheFilename(cacheArray);
- env->ReleaseStringUTFChars(diskCachePath, cacheArray);
-}
-
-// ----------------------------------------------------------------------------
-// JNI Glue
-// ----------------------------------------------------------------------------
-
-const char* const kClassPathName = "android/view/GLRenderer";
-
-static JNINativeMethod gMethods[] = {
-#ifdef USE_OPENGL_RENDERER
- { "isBackBufferPreserved", "()Z", (void*) android_view_GLRenderer_isBackBufferPreserved },
- { "preserveBackBuffer", "()Z", (void*) android_view_GLRenderer_preserveBackBuffer },
- { "loadProperties", "()Z", (void*) android_view_GLRenderer_loadProperties },
-
- { "beginFrame", "([I)V", (void*) android_view_GLRenderer_beginFrame },
-
- { "getSystemTime", "()J", (void*) android_view_GLRenderer_getSystemTime },
- { "nDestroyLayer", "(J)V", (void*) android_view_GLRenderer_destroyLayer },
- { "nPrepareTree", "(J)V", (void*) android_view_GLRenderer_prepareTree },
- { "nInvokeFunctor", "(JZ)V", (void*) android_view_GLRenderer_invokeFunctor },
-#endif
-
- { "setupShadersDiskCache", "(Ljava/lang/String;)V",
- (void*) android_view_GLRenderer_setupShadersDiskCache },
-};
-
-int register_android_view_GLRenderer(JNIEnv* env) {
- return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
-}
-
-};
diff --git a/core/jni/android_view_GraphicBuffer.cpp b/core/jni/android_view_GraphicBuffer.cpp
index 8a426ac..5ebed9c 100644
--- a/core/jni/android_view_GraphicBuffer.cpp
+++ b/core/jni/android_view_GraphicBuffer.cpp
@@ -21,6 +21,7 @@
#include "android_os_Parcel.h"
#include "android_view_GraphicBuffer.h"
+#include "android/graphics/GraphicsJNI.h"
#include <android_runtime/AndroidRuntime.h>
@@ -75,7 +76,7 @@ static struct {
static struct {
jfieldID mSurfaceFormat;
- jmethodID safeCanvasSwap;
+ jmethodID setNativeBitmap;
} gCanvasClassInfo;
#define GET_INT(object, field) \
@@ -141,16 +142,16 @@ static void android_view_GraphiceBuffer_destroy(JNIEnv* env, jobject clazz,
// Canvas management
// ----------------------------------------------------------------------------
-static inline SkBitmap::Config convertPixelFormat(int32_t format) {
+static inline SkColorType convertPixelFormat(int32_t format) {
switch (format) {
case PIXEL_FORMAT_RGBA_8888:
- return SkBitmap::kARGB_8888_Config;
+ return kN32_SkColorType;
case PIXEL_FORMAT_RGBX_8888:
- return SkBitmap::kARGB_8888_Config;
+ return kN32_SkColorType;
case PIXEL_FORMAT_RGB_565:
- return SkBitmap::kRGB_565_Config;
+ return kRGB_565_SkColorType;
default:
- return SkBitmap::kNo_Config;
+ return kUnknown_SkColorType;
}
}
@@ -187,8 +188,10 @@ static jboolean android_view_GraphicBuffer_lockCanvas(JNIEnv* env, jobject,
ssize_t bytesCount = buffer->getStride() * bytesPerPixel(buffer->getPixelFormat());
SkBitmap bitmap;
- bitmap.setConfig(convertPixelFormat(buffer->getPixelFormat()),
- buffer->getWidth(), buffer->getHeight(), bytesCount);
+ bitmap.setInfo(SkImageInfo::Make(buffer->getWidth(), buffer->getHeight(),
+ convertPixelFormat(buffer->getPixelFormat()),
+ kPremul_SkAlphaType),
+ bytesCount);
if (buffer->getWidth() > 0 && buffer->getHeight() > 0) {
bitmap.setPixels(bits);
@@ -197,12 +200,11 @@ static jboolean android_view_GraphicBuffer_lockCanvas(JNIEnv* env, jobject,
}
SET_INT(canvas, gCanvasClassInfo.mSurfaceFormat, buffer->getPixelFormat());
-
- SkCanvas* nativeCanvas = SkNEW_ARGS(SkCanvas, (bitmap));
- INVOKEV(canvas, gCanvasClassInfo.safeCanvasSwap, (jlong)nativeCanvas, false);
+ INVOKEV(canvas, gCanvasClassInfo.setNativeBitmap, reinterpret_cast<jlong>(&bitmap));
SkRect clipRect;
clipRect.set(rect.left, rect.top, rect.right, rect.bottom);
+ SkCanvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvas);
nativeCanvas->clipRect(clipRect);
if (dirtyRect) {
@@ -218,8 +220,7 @@ static jboolean android_view_GraphicBuffer_unlockCanvasAndPost(JNIEnv* env, jobj
GraphicBufferWrapper* wrapper =
reinterpret_cast<GraphicBufferWrapper*>(wrapperHandle);
- SkCanvas* nativeCanvas = SkNEW(SkCanvas);
- INVOKEV(canvas, gCanvasClassInfo.safeCanvasSwap, (jlong)nativeCanvas, false);
+ INVOKEV(canvas, gCanvasClassInfo.setNativeBitmap, (jlong)0);
if (wrapper) {
status_t status = wrapper->buffer->unlock();
@@ -319,7 +320,7 @@ int register_android_view_GraphicBuffer(JNIEnv* env) {
FIND_CLASS(clazz, "android/graphics/Canvas");
GET_FIELD_ID(gCanvasClassInfo.mSurfaceFormat, clazz, "mSurfaceFormat", "I");
- GET_METHOD_ID(gCanvasClassInfo.safeCanvasSwap, clazz, "safeCanvasSwap", "(JZ)V");
+ GET_METHOD_ID(gCanvasClassInfo.setNativeBitmap, clazz, "setNativeBitmap", "(J)V");
return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
}
diff --git a/core/jni/android_view_HardwareLayer.cpp b/core/jni/android_view_HardwareLayer.cpp
index 33a2705..ace17ec 100644
--- a/core/jni/android_view_HardwareLayer.cpp
+++ b/core/jni/android_view_HardwareLayer.cpp
@@ -43,21 +43,6 @@ using namespace uirenderer;
#ifdef USE_OPENGL_RENDERER
-static jlong android_view_HardwareLayer_createTextureLayer(JNIEnv* env, jobject clazz) {
- Layer* layer = LayerRenderer::createTextureLayer();
- if (!layer) return 0;
-
- return reinterpret_cast<jlong>( new DeferredLayerUpdater(layer) );
-}
-
-static jlong android_view_HardwareLayer_createRenderLayer(JNIEnv* env, jobject clazz,
- jint width, jint height) {
- Layer* layer = LayerRenderer::createRenderLayer(width, height);
- if (!layer) return 0;
-
- return reinterpret_cast<jlong>( new DeferredLayerUpdater(layer) );
-}
-
static void android_view_HardwareLayer_onTextureDestroyed(JNIEnv* env, jobject clazz,
jlong layerUpdaterPtr) {
DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr);
@@ -102,21 +87,6 @@ static void android_view_HardwareLayer_updateSurfaceTexture(JNIEnv* env, jobject
layer->updateTexImage();
}
-static void android_view_HardwareLayer_updateRenderLayer(JNIEnv* env, jobject clazz,
- jlong layerUpdaterPtr, jlong displayListPtr,
- jint left, jint top, jint right, jint bottom) {
- DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr);
- RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
- layer->setDisplayList(displayList, left, top, right, bottom);
-}
-
-static jboolean android_view_HardwareLayer_flushChanges(JNIEnv* env, jobject clazz,
- jlong layerUpdaterPtr) {
- DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr);
- TreeInfo ignoredInfo;
- return layer->apply(ignoredInfo);
-}
-
static jlong android_view_HardwareLayer_getLayer(JNIEnv* env, jobject clazz,
jlong layerUpdaterPtr) {
DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr);
@@ -140,8 +110,6 @@ const char* const kClassPathName = "android/view/HardwareLayer";
static JNINativeMethod gMethods[] = {
#ifdef USE_OPENGL_RENDERER
- { "nCreateTextureLayer", "()J", (void*) android_view_HardwareLayer_createTextureLayer },
- { "nCreateRenderLayer", "(II)J", (void*) android_view_HardwareLayer_createRenderLayer },
{ "nOnTextureDestroyed", "(J)V", (void*) android_view_HardwareLayer_onTextureDestroyed },
{ "nPrepare", "(JIIZ)Z", (void*) android_view_HardwareLayer_prepare },
@@ -150,9 +118,6 @@ static JNINativeMethod gMethods[] = {
{ "nSetSurfaceTexture", "(JLandroid/graphics/SurfaceTexture;Z)V",
(void*) android_view_HardwareLayer_setSurfaceTexture },
{ "nUpdateSurfaceTexture", "(J)V", (void*) android_view_HardwareLayer_updateSurfaceTexture },
- { "nUpdateRenderLayer", "(JJIIII)V", (void*) android_view_HardwareLayer_updateRenderLayer },
-
- { "nFlushChanges", "(J)Z", (void*) android_view_HardwareLayer_flushChanges },
{ "nGetLayer", "(J)J", (void*) android_view_HardwareLayer_getLayer },
{ "nGetTexName", "(J)I", (void*) android_view_HardwareLayer_getTexName },
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index 26022e0..3ffde2d 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -38,6 +38,11 @@ using namespace uirenderer;
*/
#ifdef USE_OPENGL_RENDERER
+#define SET_AND_DIRTY(prop, val, dirtyFlag) \
+ (reinterpret_cast<RenderNode*>(renderNodePtr)->mutateStagingProperties().prop(val) \
+ ? (reinterpret_cast<RenderNode*>(renderNodePtr)->setPropertyFieldsDirty(dirtyFlag), true) \
+ : false)
+
// ----------------------------------------------------------------------------
// DisplayList view properties
// ----------------------------------------------------------------------------
@@ -82,235 +87,199 @@ static void android_view_RenderNode_setDisplayListData(JNIEnv* env,
// RenderProperties - setters
// ----------------------------------------------------------------------------
-static void android_view_RenderNode_setCaching(JNIEnv* env,
- jobject clazz, jlong renderNodePtr, jboolean caching) {
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- renderNode->mutateStagingProperties().setCaching(caching);
- renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
+static jboolean android_view_RenderNode_setLayerType(JNIEnv* env,
+ jobject clazz, jlong renderNodePtr, jint jlayerType) {
+ LayerType layerType = static_cast<LayerType>(jlayerType);
+ return SET_AND_DIRTY(mutateLayerProperties().setType, layerType, RenderNode::GENERIC);
+}
+
+static jboolean android_view_RenderNode_setLayerPaint(JNIEnv* env,
+ jobject clazz, jlong renderNodePtr, jlong paintPtr) {
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
+ return SET_AND_DIRTY(mutateLayerProperties().setFromPaint, paint, RenderNode::GENERIC);
}
-static void android_view_RenderNode_setStaticMatrix(JNIEnv* env,
+static jboolean android_view_RenderNode_setStaticMatrix(JNIEnv* env,
jobject clazz, jlong renderNodePtr, jlong matrixPtr) {
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
- renderNode->mutateStagingProperties().setStaticMatrix(matrix);
- renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
+ return SET_AND_DIRTY(setStaticMatrix, matrix, RenderNode::GENERIC);
}
-static void android_view_RenderNode_setAnimationMatrix(JNIEnv* env,
+static jboolean android_view_RenderNode_setAnimationMatrix(JNIEnv* env,
jobject clazz, jlong renderNodePtr, jlong matrixPtr) {
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
- renderNode->mutateStagingProperties().setAnimationMatrix(matrix);
- renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
+ return SET_AND_DIRTY(setAnimationMatrix, matrix, RenderNode::GENERIC);
}
-static void android_view_RenderNode_setClipToBounds(JNIEnv* env,
+static jboolean android_view_RenderNode_setClipToBounds(JNIEnv* env,
jobject clazz, jlong renderNodePtr, jboolean clipToBounds) {
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- renderNode->mutateStagingProperties().setClipToBounds(clipToBounds);
- renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
+ return SET_AND_DIRTY(setClipToBounds, clipToBounds, RenderNode::GENERIC);
}
-static void android_view_RenderNode_setProjectBackwards(JNIEnv* env,
+static jboolean android_view_RenderNode_setProjectBackwards(JNIEnv* env,
jobject clazz, jlong renderNodePtr, jboolean shouldProject) {
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- renderNode->mutateStagingProperties().setProjectBackwards(shouldProject);
- renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
+ return SET_AND_DIRTY(setProjectBackwards, shouldProject, RenderNode::GENERIC);
}
-static void android_view_RenderNode_setProjectionReceiver(JNIEnv* env,
+static jboolean android_view_RenderNode_setProjectionReceiver(JNIEnv* env,
jobject clazz, jlong renderNodePtr, jboolean shouldRecieve) {
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- renderNode->mutateStagingProperties().setProjectionReceiver(shouldRecieve);
- renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
+ return SET_AND_DIRTY(setProjectionReceiver, shouldRecieve, RenderNode::GENERIC);
}
-static void android_view_RenderNode_setOutlineRoundRect(JNIEnv* env,
+static jboolean android_view_RenderNode_setOutlineRoundRect(JNIEnv* env,
jobject clazz, jlong renderNodePtr, jint left, jint top,
jint right, jint bottom, jfloat radius) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().mutableOutline().setRoundRect(left, top, right, bottom, radius);
renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
+ return true;
}
-static void android_view_RenderNode_setOutlineConvexPath(JNIEnv* env,
+static jboolean android_view_RenderNode_setOutlineConvexPath(JNIEnv* env,
jobject clazz, jlong renderNodePtr, jlong outlinePathPtr) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
SkPath* outlinePath = reinterpret_cast<SkPath*>(outlinePathPtr);
renderNode->mutateStagingProperties().mutableOutline().setConvexPath(outlinePath);
renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
+ return true;
}
-static void android_view_RenderNode_setOutlineEmpty(JNIEnv* env,
+static jboolean android_view_RenderNode_setOutlineEmpty(JNIEnv* env,
jobject clazz, jlong renderNodePtr) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().mutableOutline().setEmpty();
renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
+ return true;
}
-static void android_view_RenderNode_setClipToOutline(JNIEnv* env,
+static jboolean android_view_RenderNode_setClipToOutline(JNIEnv* env,
jobject clazz, jlong renderNodePtr, jboolean clipToOutline) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().mutableOutline().setShouldClip(clipToOutline);
renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
+ return true;
}
-static void android_view_RenderNode_setRevealClip(JNIEnv* env,
+static jboolean android_view_RenderNode_setRevealClip(JNIEnv* env,
jobject clazz, jlong renderNodePtr, jboolean shouldClip, jboolean inverseClip,
jfloat x, jfloat y, jfloat radius) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().mutableRevealClip().set(
shouldClip, inverseClip, x, y, radius);
renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
+ return true;
}
-static void android_view_RenderNode_setAlpha(JNIEnv* env,
+static jboolean android_view_RenderNode_setAlpha(JNIEnv* env,
jobject clazz, jlong renderNodePtr, float alpha) {
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- renderNode->mutateStagingProperties().setAlpha(alpha);
- renderNode->setPropertyFieldsDirty(RenderNode::ALPHA);
+ return SET_AND_DIRTY(setAlpha, alpha, RenderNode::ALPHA);
}
-static void android_view_RenderNode_setHasOverlappingRendering(JNIEnv* env,
+static jboolean android_view_RenderNode_setHasOverlappingRendering(JNIEnv* env,
jobject clazz, jlong renderNodePtr, bool hasOverlappingRendering) {
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- renderNode->mutateStagingProperties().setHasOverlappingRendering(hasOverlappingRendering);
- renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
+ return SET_AND_DIRTY(setHasOverlappingRendering, hasOverlappingRendering,
+ RenderNode::GENERIC);
}
-static void android_view_RenderNode_setElevation(JNIEnv* env,
+static jboolean android_view_RenderNode_setElevation(JNIEnv* env,
jobject clazz, jlong renderNodePtr, float elevation) {
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- renderNode->mutateStagingProperties().setElevation(elevation);
- renderNode->setPropertyFieldsDirty(RenderNode::Z);
+ return SET_AND_DIRTY(setElevation, elevation, RenderNode::Z);
}
-static void android_view_RenderNode_setTranslationX(JNIEnv* env,
+static jboolean android_view_RenderNode_setTranslationX(JNIEnv* env,
jobject clazz, jlong renderNodePtr, float tx) {
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- renderNode->mutateStagingProperties().setTranslationX(tx);
- renderNode->setPropertyFieldsDirty(RenderNode::TRANSLATION_X | RenderNode::X);
+ return SET_AND_DIRTY(setTranslationX, tx, RenderNode::TRANSLATION_X | RenderNode::X);
}
-static void android_view_RenderNode_setTranslationY(JNIEnv* env,
+static jboolean android_view_RenderNode_setTranslationY(JNIEnv* env,
jobject clazz, jlong renderNodePtr, float ty) {
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- renderNode->mutateStagingProperties().setTranslationY(ty);
- renderNode->setPropertyFieldsDirty(RenderNode::TRANSLATION_Y | RenderNode::Y);
+ return SET_AND_DIRTY(setTranslationY, ty, RenderNode::TRANSLATION_Y | RenderNode::Y);
}
-static void android_view_RenderNode_setTranslationZ(JNIEnv* env,
+static jboolean android_view_RenderNode_setTranslationZ(JNIEnv* env,
jobject clazz, jlong renderNodePtr, float tz) {
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- renderNode->mutateStagingProperties().setTranslationZ(tz);
- renderNode->setPropertyFieldsDirty(RenderNode::TRANSLATION_Z | RenderNode::Z);
+ return SET_AND_DIRTY(setTranslationZ, tz, RenderNode::TRANSLATION_Z | RenderNode::Z);
}
-static void android_view_RenderNode_setRotation(JNIEnv* env,
+static jboolean android_view_RenderNode_setRotation(JNIEnv* env,
jobject clazz, jlong renderNodePtr, float rotation) {
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- renderNode->mutateStagingProperties().setRotation(rotation);
- renderNode->setPropertyFieldsDirty(RenderNode::ROTATION);
+ return SET_AND_DIRTY(setRotation, rotation, RenderNode::ROTATION);
}
-static void android_view_RenderNode_setRotationX(JNIEnv* env,
+static jboolean android_view_RenderNode_setRotationX(JNIEnv* env,
jobject clazz, jlong renderNodePtr, float rx) {
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- renderNode->mutateStagingProperties().setRotationX(rx);
- renderNode->setPropertyFieldsDirty(RenderNode::ROTATION_X);
+ return SET_AND_DIRTY(setRotationX, rx, RenderNode::ROTATION_X);
}
-static void android_view_RenderNode_setRotationY(JNIEnv* env,
+static jboolean android_view_RenderNode_setRotationY(JNIEnv* env,
jobject clazz, jlong renderNodePtr, float ry) {
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- renderNode->mutateStagingProperties().setRotationY(ry);
- renderNode->setPropertyFieldsDirty(RenderNode::ROTATION_Y);
+ return SET_AND_DIRTY(setRotationY, ry, RenderNode::ROTATION_Y);
}
-static void android_view_RenderNode_setScaleX(JNIEnv* env,
+static jboolean android_view_RenderNode_setScaleX(JNIEnv* env,
jobject clazz, jlong renderNodePtr, float sx) {
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- renderNode->mutateStagingProperties().setScaleX(sx);
- renderNode->setPropertyFieldsDirty(RenderNode::SCALE_X);
+ return SET_AND_DIRTY(setScaleX, sx, RenderNode::SCALE_X);
}
-static void android_view_RenderNode_setScaleY(JNIEnv* env,
+static jboolean android_view_RenderNode_setScaleY(JNIEnv* env,
jobject clazz, jlong renderNodePtr, float sy) {
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- renderNode->mutateStagingProperties().setScaleY(sy);
- renderNode->setPropertyFieldsDirty(RenderNode::SCALE_Y);
+ return SET_AND_DIRTY(setScaleY, sy, RenderNode::SCALE_Y);
}
-static void android_view_RenderNode_setPivotX(JNIEnv* env,
+static jboolean android_view_RenderNode_setPivotX(JNIEnv* env,
jobject clazz, jlong renderNodePtr, float px) {
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- renderNode->mutateStagingProperties().setPivotX(px);
- renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
+ return SET_AND_DIRTY(setPivotX, px, RenderNode::GENERIC);
}
-static void android_view_RenderNode_setPivotY(JNIEnv* env,
+static jboolean android_view_RenderNode_setPivotY(JNIEnv* env,
jobject clazz, jlong renderNodePtr, float py) {
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- renderNode->mutateStagingProperties().setPivotY(py);
- renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
+ return SET_AND_DIRTY(setPivotY, py, RenderNode::GENERIC);
}
-static void android_view_RenderNode_setCameraDistance(JNIEnv* env,
+static jboolean android_view_RenderNode_setCameraDistance(JNIEnv* env,
jobject clazz, jlong renderNodePtr, float distance) {
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- renderNode->mutateStagingProperties().setCameraDistance(distance);
- renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
+ return SET_AND_DIRTY(setCameraDistance, distance, RenderNode::GENERIC);
}
-static void android_view_RenderNode_setLeft(JNIEnv* env,
+static jboolean android_view_RenderNode_setLeft(JNIEnv* env,
jobject clazz, jlong renderNodePtr, int left) {
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- renderNode->mutateStagingProperties().setLeft(left);
- renderNode->setPropertyFieldsDirty(RenderNode::X);
+ return SET_AND_DIRTY(setLeft, left, RenderNode::X);
}
-static void android_view_RenderNode_setTop(JNIEnv* env,
+static jboolean android_view_RenderNode_setTop(JNIEnv* env,
jobject clazz, jlong renderNodePtr, int top) {
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- renderNode->mutateStagingProperties().setTop(top);
- renderNode->setPropertyFieldsDirty(RenderNode::Y);
+ return SET_AND_DIRTY(setTop, top, RenderNode::Y);
}
-static void android_view_RenderNode_setRight(JNIEnv* env,
+static jboolean android_view_RenderNode_setRight(JNIEnv* env,
jobject clazz, jlong renderNodePtr, int right) {
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- renderNode->mutateStagingProperties().setRight(right);
- renderNode->setPropertyFieldsDirty(RenderNode::X);
+ return SET_AND_DIRTY(setRight, right, RenderNode::X);
}
-static void android_view_RenderNode_setBottom(JNIEnv* env,
+static jboolean android_view_RenderNode_setBottom(JNIEnv* env,
jobject clazz, jlong renderNodePtr, int bottom) {
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- renderNode->mutateStagingProperties().setBottom(bottom);
- renderNode->setPropertyFieldsDirty(RenderNode::Y);
+ return SET_AND_DIRTY(setBottom, bottom, RenderNode::Y);
}
-static void android_view_RenderNode_setLeftTopRightBottom(JNIEnv* env,
+static jboolean android_view_RenderNode_setLeftTopRightBottom(JNIEnv* env,
jobject clazz, jlong renderNodePtr, int left, int top,
int right, int bottom) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- renderNode->mutateStagingProperties().setLeftTopRightBottom(left, top, right, bottom);
- renderNode->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+ if (renderNode->mutateStagingProperties().setLeftTopRightBottom(left, top, right, bottom)) {
+ renderNode->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+ return true;
+ }
+ return false;
}
-static void android_view_RenderNode_offsetLeftAndRight(JNIEnv* env,
+static jboolean android_view_RenderNode_offsetLeftAndRight(JNIEnv* env,
jobject clazz, jlong renderNodePtr, float offset) {
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- renderNode->mutateStagingProperties().offsetLeftRight(offset);
- renderNode->setPropertyFieldsDirty(RenderNode::X);
+ return SET_AND_DIRTY(offsetLeftRight, offset, RenderNode::X);
}
-static void android_view_RenderNode_offsetTopAndBottom(JNIEnv* env,
+static jboolean android_view_RenderNode_offsetTopAndBottom(JNIEnv* env,
jobject clazz, jlong renderNodePtr, float offset) {
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- renderNode->mutateStagingProperties().offsetTopBottom(offset);
- renderNode->setPropertyFieldsDirty(RenderNode::Y);
+ return SET_AND_DIRTY(offsetTopBottom, offset, RenderNode::Y);
}
// ----------------------------------------------------------------------------
@@ -513,41 +482,42 @@ static JNINativeMethod gMethods[] = {
{ "nOutput", "(J)V", (void*) android_view_RenderNode_output },
{ "nGetDebugSize", "(J)I", (void*) android_view_RenderNode_getDebugSize },
- { "nSetCaching", "(JZ)V", (void*) android_view_RenderNode_setCaching },
- { "nSetStaticMatrix", "(JJ)V", (void*) android_view_RenderNode_setStaticMatrix },
- { "nSetAnimationMatrix", "(JJ)V", (void*) android_view_RenderNode_setAnimationMatrix },
- { "nSetClipToBounds", "(JZ)V", (void*) android_view_RenderNode_setClipToBounds },
- { "nSetProjectBackwards", "(JZ)V", (void*) android_view_RenderNode_setProjectBackwards },
- { "nSetProjectionReceiver","(JZ)V", (void*) android_view_RenderNode_setProjectionReceiver },
-
- { "nSetOutlineRoundRect", "(JIIIIF)V", (void*) android_view_RenderNode_setOutlineRoundRect },
- { "nSetOutlineConvexPath", "(JJ)V", (void*) android_view_RenderNode_setOutlineConvexPath },
- { "nSetOutlineEmpty", "(J)V", (void*) android_view_RenderNode_setOutlineEmpty },
- { "nSetClipToOutline", "(JZ)V", (void*) android_view_RenderNode_setClipToOutline },
- { "nSetRevealClip", "(JZZFFF)V", (void*) android_view_RenderNode_setRevealClip },
-
- { "nSetAlpha", "(JF)V", (void*) android_view_RenderNode_setAlpha },
- { "nSetHasOverlappingRendering", "(JZ)V",
+ { "nSetLayerType", "(JI)Z", (void*) android_view_RenderNode_setLayerType },
+ { "nSetLayerPaint", "(JJ)Z", (void*) android_view_RenderNode_setLayerPaint },
+ { "nSetStaticMatrix", "(JJ)Z", (void*) android_view_RenderNode_setStaticMatrix },
+ { "nSetAnimationMatrix", "(JJ)Z", (void*) android_view_RenderNode_setAnimationMatrix },
+ { "nSetClipToBounds", "(JZ)Z", (void*) android_view_RenderNode_setClipToBounds },
+ { "nSetProjectBackwards", "(JZ)Z", (void*) android_view_RenderNode_setProjectBackwards },
+ { "nSetProjectionReceiver","(JZ)Z", (void*) android_view_RenderNode_setProjectionReceiver },
+
+ { "nSetOutlineRoundRect", "(JIIIIF)Z", (void*) android_view_RenderNode_setOutlineRoundRect },
+ { "nSetOutlineConvexPath", "(JJ)Z", (void*) android_view_RenderNode_setOutlineConvexPath },
+ { "nSetOutlineEmpty", "(J)Z", (void*) android_view_RenderNode_setOutlineEmpty },
+ { "nSetClipToOutline", "(JZ)Z", (void*) android_view_RenderNode_setClipToOutline },
+ { "nSetRevealClip", "(JZZFFF)Z", (void*) android_view_RenderNode_setRevealClip },
+
+ { "nSetAlpha", "(JF)Z", (void*) android_view_RenderNode_setAlpha },
+ { "nSetHasOverlappingRendering", "(JZ)Z",
(void*) android_view_RenderNode_setHasOverlappingRendering },
- { "nSetElevation", "(JF)V", (void*) android_view_RenderNode_setElevation },
- { "nSetTranslationX", "(JF)V", (void*) android_view_RenderNode_setTranslationX },
- { "nSetTranslationY", "(JF)V", (void*) android_view_RenderNode_setTranslationY },
- { "nSetTranslationZ", "(JF)V", (void*) android_view_RenderNode_setTranslationZ },
- { "nSetRotation", "(JF)V", (void*) android_view_RenderNode_setRotation },
- { "nSetRotationX", "(JF)V", (void*) android_view_RenderNode_setRotationX },
- { "nSetRotationY", "(JF)V", (void*) android_view_RenderNode_setRotationY },
- { "nSetScaleX", "(JF)V", (void*) android_view_RenderNode_setScaleX },
- { "nSetScaleY", "(JF)V", (void*) android_view_RenderNode_setScaleY },
- { "nSetPivotX", "(JF)V", (void*) android_view_RenderNode_setPivotX },
- { "nSetPivotY", "(JF)V", (void*) android_view_RenderNode_setPivotY },
- { "nSetCameraDistance", "(JF)V", (void*) android_view_RenderNode_setCameraDistance },
- { "nSetLeft", "(JI)V", (void*) android_view_RenderNode_setLeft },
- { "nSetTop", "(JI)V", (void*) android_view_RenderNode_setTop },
- { "nSetRight", "(JI)V", (void*) android_view_RenderNode_setRight },
- { "nSetBottom", "(JI)V", (void*) android_view_RenderNode_setBottom },
- { "nSetLeftTopRightBottom","(JIIII)V", (void*) android_view_RenderNode_setLeftTopRightBottom },
- { "nOffsetLeftAndRight", "(JF)V", (void*) android_view_RenderNode_offsetLeftAndRight },
- { "nOffsetTopAndBottom", "(JF)V", (void*) android_view_RenderNode_offsetTopAndBottom },
+ { "nSetElevation", "(JF)Z", (void*) android_view_RenderNode_setElevation },
+ { "nSetTranslationX", "(JF)Z", (void*) android_view_RenderNode_setTranslationX },
+ { "nSetTranslationY", "(JF)Z", (void*) android_view_RenderNode_setTranslationY },
+ { "nSetTranslationZ", "(JF)Z", (void*) android_view_RenderNode_setTranslationZ },
+ { "nSetRotation", "(JF)Z", (void*) android_view_RenderNode_setRotation },
+ { "nSetRotationX", "(JF)Z", (void*) android_view_RenderNode_setRotationX },
+ { "nSetRotationY", "(JF)Z", (void*) android_view_RenderNode_setRotationY },
+ { "nSetScaleX", "(JF)Z", (void*) android_view_RenderNode_setScaleX },
+ { "nSetScaleY", "(JF)Z", (void*) android_view_RenderNode_setScaleY },
+ { "nSetPivotX", "(JF)Z", (void*) android_view_RenderNode_setPivotX },
+ { "nSetPivotY", "(JF)Z", (void*) android_view_RenderNode_setPivotY },
+ { "nSetCameraDistance", "(JF)Z", (void*) android_view_RenderNode_setCameraDistance },
+ { "nSetLeft", "(JI)Z", (void*) android_view_RenderNode_setLeft },
+ { "nSetTop", "(JI)Z", (void*) android_view_RenderNode_setTop },
+ { "nSetRight", "(JI)Z", (void*) android_view_RenderNode_setRight },
+ { "nSetBottom", "(JI)Z", (void*) android_view_RenderNode_setBottom },
+ { "nSetLeftTopRightBottom","(JIIII)Z", (void*) android_view_RenderNode_setLeftTopRightBottom },
+ { "nOffsetLeftAndRight", "(JF)Z", (void*) android_view_RenderNode_offsetLeftAndRight },
+ { "nOffsetTopAndBottom", "(JF)Z", (void*) android_view_RenderNode_offsetTopAndBottom },
{ "nHasOverlappingRendering", "(J)Z", (void*) android_view_RenderNode_hasOverlappingRendering },
{ "nGetClipToOutline", "(J)Z", (void*) android_view_RenderNode_getClipToOutline },
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 6c9d060..7018751 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -70,7 +70,7 @@ static struct {
static struct {
jfieldID mSurfaceFormat;
- jmethodID safeCanvasSwap;
+ jmethodID setNativeBitmap;
} gCanvasClassInfo;
// ----------------------------------------------------------------------------
@@ -95,6 +95,7 @@ sp<Surface> android_view_Surface_getSurface(JNIEnv* env, jobject surfaceObj) {
env->GetLongField(surfaceObj, gSurfaceClassInfo.mNativeObject));
env->MonitorExit(lock);
}
+ env->DeleteLocalRef(lock);
return sur;
}
@@ -172,17 +173,17 @@ static jboolean nativeIsConsumerRunningBehind(JNIEnv* env, jclass clazz, jlong n
return value;
}
-static inline SkBitmap::Config convertPixelFormat(PixelFormat format) {
+static inline SkColorType convertPixelFormat(PixelFormat format) {
/* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then
- we can map to SkBitmap::kARGB_8888_Config, and optionally call
+ we can map to kN32_SkColorType, and optionally call
bitmap.setAlphaType(kOpaque_SkAlphaType) on the resulting SkBitmap
(as an accelerator)
*/
switch (format) {
- case PIXEL_FORMAT_RGBX_8888: return SkBitmap::kARGB_8888_Config;
- case PIXEL_FORMAT_RGBA_8888: return SkBitmap::kARGB_8888_Config;
- case PIXEL_FORMAT_RGB_565: return SkBitmap::kRGB_565_Config;
- default: return SkBitmap::kNo_Config;
+ case PIXEL_FORMAT_RGBX_8888: return kN32_SkColorType;
+ case PIXEL_FORMAT_RGBA_8888: return kN32_SkColorType;
+ case PIXEL_FORMAT_RGB_565: return kRGB_565_SkColorType;
+ default: return kUnknown_SkColorType;
}
}
@@ -219,12 +220,16 @@ static jlong nativeLockCanvas(JNIEnv* env, jclass clazz,
// Associate a SkCanvas object to this surface
env->SetIntField(canvasObj, gCanvasClassInfo.mSurfaceFormat, outBuffer.format);
- SkBitmap bitmap;
- ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
- bitmap.setConfig(convertPixelFormat(outBuffer.format), outBuffer.width, outBuffer.height, bpr);
+ SkImageInfo info = SkImageInfo::Make(outBuffer.width, outBuffer.height,
+ convertPixelFormat(outBuffer.format),
+ kPremul_SkAlphaType);
if (outBuffer.format == PIXEL_FORMAT_RGBX_8888) {
- bitmap.setAlphaType(kOpaque_SkAlphaType);
+ info.fAlphaType = kOpaque_SkAlphaType;
}
+
+ SkBitmap bitmap;
+ ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
+ bitmap.setInfo(info, bpr);
if (outBuffer.width > 0 && outBuffer.height > 0) {
bitmap.setPixels(outBuffer.bits);
} else {
@@ -232,10 +237,11 @@ static jlong nativeLockCanvas(JNIEnv* env, jclass clazz,
bitmap.setPixels(NULL);
}
- SkCanvas* nativeCanvas = SkNEW_ARGS(SkCanvas, (bitmap));
- env->CallVoidMethod(canvasObj, gCanvasClassInfo.safeCanvasSwap, (jlong)nativeCanvas, false);
+ env->CallVoidMethod(canvasObj, gCanvasClassInfo.setNativeBitmap,
+ reinterpret_cast<jlong>(&bitmap));
if (dirtyRectPtr) {
+ SkCanvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj);
nativeCanvas->clipRect( SkRect::Make(reinterpret_cast<const SkIRect&>(dirtyRect)) );
}
@@ -262,8 +268,7 @@ static void nativeUnlockCanvasAndPost(JNIEnv* env, jclass clazz,
}
// detach the canvas from the surface
- SkCanvas* nativeCanvas = SkNEW(SkCanvas);
- env->CallVoidMethod(canvasObj, gCanvasClassInfo.safeCanvasSwap, (jlong)nativeCanvas, false);
+ env->CallVoidMethod(canvasObj, gCanvasClassInfo.setNativeBitmap, (jlong)0);
// unlock surface
status_t err = surface->unlockAndPost();
@@ -375,7 +380,7 @@ int register_android_view_Surface(JNIEnv* env)
clazz = env->FindClass("android/graphics/Canvas");
gCanvasClassInfo.mSurfaceFormat = env->GetFieldID(clazz, "mSurfaceFormat", "I");
- gCanvasClassInfo.safeCanvasSwap = env->GetMethodID(clazz, "safeCanvasSwap", "(JZ)V");
+ gCanvasClassInfo.setNativeBitmap = env->GetMethodID(clazz, "setNativeBitmap", "(J)V");
clazz = env->FindClass("android/graphics/Rect");
gRectClassInfo.left = env->GetFieldID(clazz, "left", "I");
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 5a935a9..9783e91 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -42,6 +42,8 @@
#include <ScopedUtfChars.h>
+#include "SkTemplates.h"
+
// ----------------------------------------------------------------------------
namespace android {
@@ -59,8 +61,17 @@ static struct {
jfieldID xDpi;
jfieldID yDpi;
jfieldID secure;
+ jfieldID appVsyncOffsetNanos;
+ jfieldID presentationDeadlineNanos;
} gPhysicalDisplayInfoClassInfo;
+static struct {
+ jfieldID bottom;
+ jfieldID left;
+ jfieldID right;
+ jfieldID top;
+} gRectClassInfo;
+
// Implements SkMallocPixelRef::ReleaseProc, to delete the screenshot on unref.
void DeleteScreenshot(void* addr, void* context) {
SkASSERT(addr == ((ScreenshotClient*) context)->getPixels());
@@ -104,28 +115,34 @@ static void nativeDestroy(JNIEnv* env, jclass clazz, jlong nativeObject) {
ctrl->decStrong((void *)nativeCreate);
}
-static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz, jobject displayTokenObj,
- jint width, jint height, jint minLayer, jint maxLayer, bool allLayers,
- bool useIdentityTransform) {
+static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz,
+ jobject displayTokenObj, jobject sourceCropObj, jint width, jint height,
+ jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform) {
sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);
if (displayToken == NULL) {
return NULL;
}
- ScreenshotClient* screenshot = new ScreenshotClient();
+ int left = env->GetIntField(sourceCropObj, gRectClassInfo.left);
+ int top = env->GetIntField(sourceCropObj, gRectClassInfo.top);
+ int right = env->GetIntField(sourceCropObj, gRectClassInfo.right);
+ int bottom = env->GetIntField(sourceCropObj, gRectClassInfo.bottom);
+ Rect sourceCrop(left, top, right, bottom);
+
+ SkAutoTDelete<ScreenshotClient> screenshot(new ScreenshotClient());
status_t res;
if (width > 0 && height > 0) {
if (allLayers) {
- res = screenshot->update(displayToken, width, height, useIdentityTransform);
- } else {
- res = screenshot->update(displayToken, width, height, minLayer, maxLayer,
+ res = screenshot->update(displayToken, sourceCrop, width, height,
useIdentityTransform);
+ } else {
+ res = screenshot->update(displayToken, sourceCrop, width, height,
+ minLayer, maxLayer, useIdentityTransform);
}
} else {
- res = screenshot->update(displayToken, useIdentityTransform);
+ res = screenshot->update(displayToken, sourceCrop, useIdentityTransform);
}
if (res != NO_ERROR) {
- delete screenshot;
return NULL;
}
@@ -150,7 +167,6 @@ static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz, jobject display
break;
}
default: {
- delete screenshot;
return NULL;
}
}
@@ -159,12 +175,12 @@ static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz, jobject display
screenshot->getStride() * android::bytesPerPixel(screenshot->getFormat());
SkBitmap* bitmap = new SkBitmap();
- bitmap->setConfig(screenshotInfo, (size_t)rowBytes);
+ bitmap->setInfo(screenshotInfo, (size_t)rowBytes);
if (screenshotInfo.fWidth > 0 && screenshotInfo.fHeight > 0) {
// takes ownership of ScreenshotClient
SkMallocPixelRef* pixels = SkMallocPixelRef::NewWithProc(screenshotInfo,
(size_t) rowBytes, NULL, (void*) screenshot->getPixels(), &DeleteScreenshot,
- (void*) screenshot);
+ (void*) (screenshot.detach()));
pixels->setImmutable();
bitmap->setPixelRef(pixels)->unref();
bitmap->lockPixels();
@@ -174,20 +190,25 @@ static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz, jobject display
GraphicsJNI::kBitmapCreateFlag_Premultiplied, NULL);
}
-static void nativeScreenshot(JNIEnv* env, jclass clazz,
- jobject displayTokenObj, jobject surfaceObj,
- jint width, jint height, jint minLayer, jint maxLayer, bool allLayers,
- bool useIdentityTransform) {
+static void nativeScreenshot(JNIEnv* env, jclass clazz, jobject displayTokenObj,
+ jobject surfaceObj, jobject sourceCropObj, jint width, jint height,
+ jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform) {
sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);
if (displayToken != NULL) {
sp<Surface> consumer = android_view_Surface_getSurface(env, surfaceObj);
if (consumer != NULL) {
+ int left = env->GetIntField(sourceCropObj, gRectClassInfo.left);
+ int top = env->GetIntField(sourceCropObj, gRectClassInfo.top);
+ int right = env->GetIntField(sourceCropObj, gRectClassInfo.right);
+ int bottom = env->GetIntField(sourceCropObj, gRectClassInfo.bottom);
+ Rect sourceCrop(left, top, right, bottom);
+
if (allLayers) {
minLayer = 0;
maxLayer = -1;
}
- ScreenshotClient::capture(
- displayToken, consumer->getIGraphicBufferProducer(),
+ ScreenshotClient::capture(displayToken,
+ consumer->getIGraphicBufferProducer(), sourceCrop,
width, height, uint32_t(minLayer), uint32_t(maxLayer),
useIdentityTransform);
}
@@ -373,6 +394,10 @@ static jobjectArray nativeGetDisplayConfigs(JNIEnv* env, jclass clazz,
env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.xDpi, info.xdpi);
env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.yDpi, info.ydpi);
env->SetBooleanField(infoObj, gPhysicalDisplayInfoClassInfo.secure, info.secure);
+ env->SetLongField(infoObj, gPhysicalDisplayInfoClassInfo.appVsyncOffsetNanos,
+ info.appVsyncOffset);
+ env->SetLongField(infoObj, gPhysicalDisplayInfoClassInfo.presentationDeadlineNanos,
+ info.presentationDeadline);
env->SetObjectArrayElement(configArray, static_cast<jsize>(c), infoObj);
env->DeleteLocalRef(infoObj);
}
@@ -393,20 +418,12 @@ static jboolean nativeSetActiveConfig(JNIEnv* env, jclass clazz, jobject tokenOb
return err == NO_ERROR ? JNI_TRUE : JNI_FALSE;
}
-static void nativeBlankDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) {
- sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
- if (token == NULL) return;
-
- ALOGD_IF_SLOW(100, "Excessive delay in blankDisplay() while turning screen off");
- SurfaceComposerClient::blankDisplay(token);
-}
-
-static void nativeUnblankDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) {
+static void nativeSetDisplayPowerMode(JNIEnv* env, jclass clazz, jobject tokenObj, jint mode) {
sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
if (token == NULL) return;
- ALOGD_IF_SLOW(100, "Excessive delay in unblankDisplay() while turning screen on");
- SurfaceComposerClient::unblankDisplay(token);
+ ALOGD_IF_SLOW(100, "Excessive delay in setPowerMode()");
+ SurfaceComposerClient::setDisplayPowerMode(token, mode);
}
static jboolean nativeClearContentFrameStats(JNIEnv* env, jclass clazz, jlong nativeObject) {
@@ -563,9 +580,9 @@ static JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeRelease },
{"nativeDestroy", "(J)V",
(void*)nativeDestroy },
- {"nativeScreenshot", "(Landroid/os/IBinder;IIIIZZ)Landroid/graphics/Bitmap;",
+ {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/graphics/Rect;IIIIZZ)Landroid/graphics/Bitmap;",
(void*)nativeScreenshotBitmap },
- {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/view/Surface;IIIIZZ)V",
+ {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/view/Surface;Landroid/graphics/Rect;IIIIZZ)V",
(void*)nativeScreenshot },
{"nativeOpenTransaction", "()V",
(void*)nativeOpenTransaction },
@@ -609,10 +626,6 @@ static JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeGetActiveConfig },
{"nativeSetActiveConfig", "(Landroid/os/IBinder;I)Z",
(void*)nativeSetActiveConfig },
- {"nativeBlankDisplay", "(Landroid/os/IBinder;)V",
- (void*)nativeBlankDisplay },
- {"nativeUnblankDisplay", "(Landroid/os/IBinder;)V",
- (void*)nativeUnblankDisplay },
{"nativeClearContentFrameStats", "(J)Z",
(void*)nativeClearContentFrameStats },
{"nativeGetContentFrameStats", "(JLandroid/view/WindowContentFrameStats;)Z",
@@ -621,6 +634,8 @@ static JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeClearAnimationFrameStats },
{"nativeGetAnimationFrameStats", "(Landroid/view/WindowAnimationFrameStats;)Z",
(void*)nativeGetAnimationFrameStats },
+ {"nativeSetDisplayPowerMode", "(Landroid/os/IBinder;I)V",
+ (void*)nativeSetDisplayPowerMode },
};
int register_android_view_SurfaceControl(JNIEnv* env)
@@ -639,6 +654,16 @@ int register_android_view_SurfaceControl(JNIEnv* env)
gPhysicalDisplayInfoClassInfo.xDpi = env->GetFieldID(clazz, "xDpi", "F");
gPhysicalDisplayInfoClassInfo.yDpi = env->GetFieldID(clazz, "yDpi", "F");
gPhysicalDisplayInfoClassInfo.secure = env->GetFieldID(clazz, "secure", "Z");
+ gPhysicalDisplayInfoClassInfo.appVsyncOffsetNanos = env->GetFieldID(clazz,
+ "appVsyncOffsetNanos", "J");
+ gPhysicalDisplayInfoClassInfo.presentationDeadlineNanos = env->GetFieldID(clazz,
+ "presentationDeadlineNanos", "J");
+
+ jclass rectClazz = env->FindClass("android/graphics/Rect");
+ gRectClassInfo.bottom = env->GetFieldID(rectClazz, "bottom", "I");
+ gRectClassInfo.left = env->GetFieldID(rectClazz, "left", "I");
+ gRectClassInfo.right = env->GetFieldID(rectClazz, "right", "I");
+ gRectClassInfo.top = env->GetFieldID(rectClazz, "top", "I");
jclass frameStatsClazz = env->FindClass("android/view/FrameStats");
jfieldID undefined_time_nano_field = env->GetStaticFieldID(frameStatsClazz, "UNDEFINED_TIME_NANO", "J");
diff --git a/core/jni/android_view_TextureView.cpp b/core/jni/android_view_TextureView.cpp
index 9258543..5c04a78 100644
--- a/core/jni/android_view_TextureView.cpp
+++ b/core/jni/android_view_TextureView.cpp
@@ -29,6 +29,8 @@
#include <SkCanvas.h>
#include <SkImage.h>
+#include "android/graphics/GraphicsJNI.h"
+
namespace android {
// ----------------------------------------------------------------------------
@@ -45,7 +47,7 @@ static struct {
static struct {
jfieldID mSurfaceFormat;
- jmethodID safeCanvasSwap;
+ jmethodID setNativeBitmap;
} gCanvasClassInfo;
static struct {
@@ -71,17 +73,28 @@ static struct {
// Native layer
// ----------------------------------------------------------------------------
-static inline SkBitmap::Config convertPixelFormat(int32_t format) {
- switch (format) {
+// FIXME: consider exporting this to share (e.g. android_view_Surface.cpp)
+static inline SkImageInfo convertPixelFormat(const ANativeWindow_Buffer& buffer) {
+ SkImageInfo info;
+ info.fWidth = buffer.width;
+ info.fHeight = buffer.height;
+ switch (buffer.format) {
case WINDOW_FORMAT_RGBA_8888:
- return SkBitmap::kARGB_8888_Config;
+ info.fColorType = kN32_SkColorType;
+ info.fAlphaType = kPremul_SkAlphaType;
+ break;
case WINDOW_FORMAT_RGBX_8888:
- return SkBitmap::kARGB_8888_Config;
+ info.fColorType = kN32_SkColorType;
+ info.fAlphaType = kOpaque_SkAlphaType;
case WINDOW_FORMAT_RGB_565:
- return SkBitmap::kRGB_565_Config;
+ info.fColorType = kRGB_565_SkColorType;
+ info.fAlphaType = kOpaque_SkAlphaType;
default:
- return SkBitmap::kNo_Config;
+ info.fColorType = kUnknown_SkColorType;
+ info.fAlphaType = kIgnore_SkAlphaType;
+ break;
}
+ return info;
}
/**
@@ -146,11 +159,7 @@ static jboolean android_view_TextureView_lockCanvas(JNIEnv* env, jobject,
ssize_t bytesCount = buffer.stride * bytesPerPixel(buffer.format);
SkBitmap bitmap;
- bitmap.setConfig(convertPixelFormat(buffer.format), buffer.width, buffer.height, bytesCount);
-
- if (buffer.format == WINDOW_FORMAT_RGBX_8888) {
- bitmap.setAlphaType(kOpaque_SkAlphaType);
- }
+ bitmap.setInfo(convertPixelFormat(buffer), bytesCount);
if (buffer.width > 0 && buffer.height > 0) {
bitmap.setPixels(buffer.bits);
@@ -159,12 +168,11 @@ static jboolean android_view_TextureView_lockCanvas(JNIEnv* env, jobject,
}
SET_INT(canvas, gCanvasClassInfo.mSurfaceFormat, buffer.format);
-
- SkCanvas* nativeCanvas = SkNEW_ARGS(SkCanvas, (bitmap));
- INVOKEV(canvas, gCanvasClassInfo.safeCanvasSwap, (jlong)nativeCanvas, false);
+ INVOKEV(canvas, gCanvasClassInfo.setNativeBitmap, reinterpret_cast<jlong>(&bitmap));
SkRect clipRect;
clipRect.set(rect.left, rect.top, rect.right, rect.bottom);
+ SkCanvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvas);
nativeCanvas->clipRect(clipRect);
if (dirtyRect) {
@@ -178,8 +186,7 @@ static jboolean android_view_TextureView_lockCanvas(JNIEnv* env, jobject,
static void android_view_TextureView_unlockCanvasAndPost(JNIEnv* env, jobject,
jlong nativeWindow, jobject canvas) {
- SkCanvas* nativeCanvas = SkNEW(SkCanvas);
- INVOKEV(canvas, gCanvasClassInfo.safeCanvasSwap, (jlong)nativeCanvas, false);
+ INVOKEV(canvas, gCanvasClassInfo.setNativeBitmap, (jlong)0);
if (nativeWindow) {
sp<ANativeWindow> window((ANativeWindow*) nativeWindow);
@@ -228,7 +235,7 @@ int register_android_view_TextureView(JNIEnv* env) {
FIND_CLASS(clazz, "android/graphics/Canvas");
GET_FIELD_ID(gCanvasClassInfo.mSurfaceFormat, clazz, "mSurfaceFormat", "I");
- GET_METHOD_ID(gCanvasClassInfo.safeCanvasSwap, clazz, "safeCanvasSwap", "(JZ)V");
+ GET_METHOD_ID(gCanvasClassInfo.setNativeBitmap, clazz, "setNativeBitmap", "(J)V");
FIND_CLASS(clazz, "android/view/TextureView");
GET_FIELD_ID(gTextureViewClassInfo.nativeWindow, clazz, "mNativeWindow", "J");
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 1397131..3e62d0b 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -22,6 +22,10 @@
#include <nativehelper/JNIHelp.h>
#include <android_runtime/AndroidRuntime.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <EGL/egl_cache.h>
+
#include <utils/StrongPointer.h>
#include <android_runtime/android_view_Surface.h>
#include <system/window.h>
@@ -45,6 +49,14 @@ using namespace android::uirenderer::renderthread;
static jmethodID gRunnableMethod;
+static JNIEnv* getenv(JavaVM* vm) {
+ JNIEnv* env;
+ if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+ LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", vm);
+ }
+ return env;
+}
+
class JavaTask : public RenderTask {
public:
JavaTask(JNIEnv* env, jobject jrunnable) {
@@ -53,44 +65,17 @@ public:
}
virtual void run() {
- env()->CallVoidMethod(mRunnable, gRunnableMethod);
- env()->DeleteGlobalRef(mRunnable);
+ JNIEnv* env = getenv(mVm);
+ env->CallVoidMethod(mRunnable, gRunnableMethod);
+ env->DeleteGlobalRef(mRunnable);
delete this;
};
private:
- JNIEnv* env() {
- JNIEnv* env;
- if (mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
- return 0;
- }
- return env;
- }
-
JavaVM* mVm;
jobject mRunnable;
};
-class SetAtlasTask : public RenderTask {
-public:
- SetAtlasTask(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size)
- : mBuffer(buffer)
- , mMap(map)
- , mMapSize(size) {
- }
-
- virtual void run() {
- CanvasContext::setTextureAtlas(mBuffer, mMap, mMapSize);
- mMap = 0;
- delete this;
- }
-
-private:
- sp<GraphicBuffer> mBuffer;
- int64_t* mMap;
- size_t mMapSize;
-};
-
class OnFinishedEvent {
public:
OnFinishedEvent(BaseRenderNodeAnimator* animator, AnimationListener* listener)
@@ -118,12 +103,34 @@ private:
std::vector<OnFinishedEvent> mOnFinishedEvents;
};
-class RootRenderNode : public RenderNode, public AnimationHook {
+class RenderingException : public MessageHandler {
+public:
+ RenderingException(JavaVM* vm, const std::string& message)
+ : mVm(vm)
+ , mMessage(message) {
+ }
+
+ virtual void handleMessage(const Message&) {
+ throwException(mVm, mMessage);
+ }
+
+ static void throwException(JavaVM* vm, const std::string& message) {
+ JNIEnv* env = getenv(vm);
+ jniThrowException(env, "java/lang/IllegalStateException", message.c_str());
+ }
+
+private:
+ JavaVM* mVm;
+ std::string mMessage;
+};
+
+class RootRenderNode : public RenderNode, AnimationHook, ErrorHandler {
public:
- RootRenderNode() : RenderNode() {
+ RootRenderNode(JNIEnv* env) : RenderNode() {
mLooper = Looper::getForThread();
LOG_ALWAYS_FATAL_IF(!mLooper.get(),
"Must create RootRenderNode on a thread with a looper!");
+ env->GetJavaVM(&mVm);
}
virtual ~RootRenderNode() {}
@@ -133,10 +140,16 @@ public:
mOnFinishedEvents.push_back(event);
}
+ virtual void onError(const std::string& message) {
+ mLooper->sendMessage(new RenderingException(mVm, message), 0);
+ }
+
virtual void prepareTree(TreeInfo& info) {
info.animationHook = this;
+ info.errorHandler = this;
RenderNode::prepareTree(info);
info.animationHook = NULL;
+ info.errorHandler = NULL;
// post all the finished stuff
if (mOnFinishedEvents.size()) {
@@ -146,13 +159,21 @@ public:
}
}
+protected:
+ virtual void damageSelf(TreeInfo& info) {
+ // Intentionally a no-op. As RootRenderNode gets a new DisplayListData
+ // every frame this would result in every draw push being a full inval,
+ // which is wrong. Only RootRenderNode has this issue.
+ }
+
private:
sp<Looper> mLooper;
std::vector<OnFinishedEvent> mOnFinishedEvents;
+ JavaVM* mVm;
};
static void android_view_ThreadedRenderer_setAtlas(JNIEnv* env, jobject clazz,
- jobject graphicBuffer, jlongArray atlasMapArray) {
+ jlong proxyPtr, jobject graphicBuffer, jlongArray atlasMapArray) {
sp<GraphicBuffer> buffer = graphicBufferForJavaObject(env, graphicBuffer);
jsize len = env->GetArrayLength(atlasMapArray);
if (len <= 0) {
@@ -162,12 +183,12 @@ static void android_view_ThreadedRenderer_setAtlas(JNIEnv* env, jobject clazz,
int64_t* map = new int64_t[len];
env->GetLongArrayRegion(atlasMapArray, 0, len, map);
- SetAtlasTask* task = new SetAtlasTask(buffer, map, len);
- RenderThread::getInstance().queue(task);
+ RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+ proxy->setTextureAtlas(buffer, map, len);
}
static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) {
- RootRenderNode* node = new RootRenderNode();
+ RootRenderNode* node = new RootRenderNode(env);
node->incStrong(0);
node->setName("RootRenderNode");
return reinterpret_cast<jlong>(node);
@@ -238,11 +259,9 @@ static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz,
}
static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
- jlong proxyPtr, jlong frameTimeNanos, jlong recordDuration, jfloat density,
- jint dirtyLeft, jint dirtyTop, jint dirtyRight, jint dirtyBottom) {
+ jlong proxyPtr, jlong frameTimeNanos, jlong recordDuration, jfloat density) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
- return proxy->syncAndDrawFrame(frameTimeNanos, recordDuration, density,
- dirtyLeft, dirtyTop, dirtyRight, dirtyBottom);
+ return proxy->syncAndDrawFrame(frameTimeNanos, recordDuration, density);
}
static void android_view_ThreadedRenderer_destroyCanvasAndSurface(JNIEnv* env, jobject clazz,
@@ -252,10 +271,9 @@ static void android_view_ThreadedRenderer_destroyCanvasAndSurface(JNIEnv* env, j
}
static void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
- jlong proxyPtr, jlong functorPtr, jboolean waitForCompletion) {
- RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+ jlong functorPtr, jboolean waitForCompletion) {
Functor* functor = reinterpret_cast<Functor*>(functorPtr);
- proxy->invokeFunctor(functor, waitForCompletion);
+ RenderProxy::invokeFunctor(functor, waitForCompletion);
}
static void android_view_ThreadedRenderer_runWithGlContext(JNIEnv* env, jobject clazz,
@@ -329,6 +347,18 @@ static void android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv* env, jobject c
#endif
// ----------------------------------------------------------------------------
+// Shaders
+// ----------------------------------------------------------------------------
+
+static void android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz,
+ jstring diskCachePath) {
+
+ const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL);
+ egl_cache_t::get()->setCacheFilename(cacheArray);
+ env->ReleaseStringUTFChars(diskCachePath, cacheArray);
+}
+
+// ----------------------------------------------------------------------------
// JNI Glue
// ----------------------------------------------------------------------------
@@ -336,7 +366,7 @@ const char* const kClassPathName = "android/view/ThreadedRenderer";
static JNINativeMethod gMethods[] = {
#ifdef USE_OPENGL_RENDERER
- { "nSetAtlas", "(Landroid/view/GraphicBuffer;[J)V", (void*) android_view_ThreadedRenderer_setAtlas },
+ { "nSetAtlas", "(JLandroid/view/GraphicBuffer;[J)V", (void*) android_view_ThreadedRenderer_setAtlas },
{ "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode },
{ "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy },
{ "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy },
@@ -347,9 +377,9 @@ static JNINativeMethod gMethods[] = {
{ "nPauseSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_pauseSurface },
{ "nSetup", "(JIIFFFF)V", (void*) android_view_ThreadedRenderer_setup },
{ "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
- { "nSyncAndDrawFrame", "(JJJFIIII)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
+ { "nSyncAndDrawFrame", "(JJJF)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
{ "nDestroyCanvasAndSurface", "(J)V", (void*) android_view_ThreadedRenderer_destroyCanvasAndSurface },
- { "nInvokeFunctor", "(JJZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
+ { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
{ "nRunWithGlContext", "(JLjava/lang/Runnable;)V", (void*) android_view_ThreadedRenderer_runWithGlContext },
{ "nCreateDisplayListLayer", "(JII)J", (void*) android_view_ThreadedRenderer_createDisplayListLayer },
{ "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
@@ -361,6 +391,8 @@ static JNINativeMethod gMethods[] = {
{ "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending },
{ "nDumpProfileInfo", "(JLjava/io/FileDescriptor;)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo },
#endif
+ { "setupShadersDiskCache", "(Ljava/lang/String;)V",
+ (void*) android_view_ThreadedRenderer_setupShadersDiskCache },
};
int register_android_view_ThreadedRenderer(JNIEnv* env) {
diff --git a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
index 381a5ee..226b764 100644
--- a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
+++ b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
@@ -46,6 +46,9 @@
#define LIB_SUFFIX ".so"
#define LIB_SUFFIX_LEN (sizeof(LIB_SUFFIX) - 1)
+#define RS_BITCODE_SUFFIX ".bc"
+#define RS_BITCODE_SUFFIX_LEN (sizeof(RS_BITCODE_SUFFIX) -1)
+
#define GDBSERVER "gdbserver"
#define GDBSERVER_LEN (sizeof(GDBSERVER) - 1)
@@ -487,6 +490,42 @@ com_android_internal_content_NativeLibraryHelper_findSupportedAbi(JNIEnv *env, j
return (jint) findSupportedAbi(env, apkHandle, javaCpuAbisToSearch);
}
+enum bitcode_scan_result_t {
+ APK_SCAN_ERROR = -1,
+ NO_BITCODE_PRESENT = 0,
+ BITCODE_PRESENT = 1,
+};
+
+static jint
+com_android_internal_content_NativeLibraryHelper_hasRenderscriptBitcode(JNIEnv *env, jclass clazz,
+ jlong apkHandle) {
+ ZipFileRO* zipFile = reinterpret_cast<ZipFileRO*>(apkHandle);
+ void* cookie = NULL;
+ if (!zipFile->startIteration(&cookie)) {
+ return APK_SCAN_ERROR;
+ }
+
+ char fileName[PATH_MAX];
+ ZipEntryRO next = NULL;
+ while ((next = zipFile->nextEntry(cookie)) != NULL) {
+ if (zipFile->getEntryFileName(next, fileName, sizeof(fileName))) {
+ continue;
+ }
+
+ const size_t fileNameLen = strlen(fileName);
+ const char* lastSlash = strrchr(fileName, '/');
+ const char* baseName = (lastSlash == NULL) ? fileName : fileName + 1;
+ if (!strncmp(fileName + fileNameLen - RS_BITCODE_SUFFIX_LEN, RS_BITCODE_SUFFIX,
+ RS_BITCODE_SUFFIX_LEN) && isFilenameSafe(baseName)) {
+ zipFile->endIteration(cookie);
+ return BITCODE_PRESENT;
+ }
+ }
+
+ zipFile->endIteration(cookie);
+ return NO_BITCODE_PRESENT;
+}
+
static jlong
com_android_internal_content_NativeLibraryHelper_openApk(JNIEnv *env, jclass, jstring apkPath)
{
@@ -518,6 +557,8 @@ static JNINativeMethod gMethods[] = {
{"nativeFindSupportedAbi",
"(J[Ljava/lang/String;)I",
(void *)com_android_internal_content_NativeLibraryHelper_findSupportedAbi},
+ {"hasRenderscriptBitcode", "(J)I",
+ (void *)com_android_internal_content_NativeLibraryHelper_hasRenderscriptBitcode},
};
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index c58bf04..0cdddba 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -14,46 +14,40 @@
* limitations under the License.
*/
-#include "android_runtime/AndroidRuntime.h"
+#define LOG_TAG "Zygote"
// sys/mount.h has to come before linux/fs.h due to redefinition of MS_RDONLY, MS_BIND, etc
#include <sys/mount.h>
#include <linux/fs.h>
#include <grp.h>
+#include <fcntl.h>
#include <paths.h>
#include <signal.h>
#include <stdlib.h>
+#include <unistd.h>
+#include <sys/capability.h>
+#include <sys/personality.h>
+#include <sys/prctl.h>
#include <sys/resource.h>
-#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
#include <sys/wait.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include "cutils/fs.h"
-#include "cutils/multiuser.h"
-#include "cutils/sched_policy.h"
-#include "utils/String8.h"
+
+#include <cutils/fs.h>
+#include <cutils/multiuser.h>
+#include <cutils/sched_policy.h>
+#include <utils/String8.h>
+#include <selinux/android.h>
+
+#include "android_runtime/AndroidRuntime.h"
#include "JNIHelp.h"
#include "ScopedLocalRef.h"
#include "ScopedPrimitiveArray.h"
#include "ScopedUtfChars.h"
-#if defined(HAVE_PRCTL)
-#include <sys/prctl.h>
-#endif
-
-#include <selinux/android.h>
-
-#if defined(__linux__)
-#include <sys/personality.h>
-#include <sys/utsname.h>
-#if defined(HAVE_ANDROID_OS)
-#include <sys/capability.h>
-#endif
-#endif
-
namespace {
using android::String8;
@@ -97,11 +91,9 @@ static void SigChldHandler(int /*signal_number*/) {
if (WTERMSIG(status) != SIGKILL) {
ALOGI("Process %d exited due to signal (%d)", pid, WTERMSIG(status));
}
-#ifdef WCOREDUMP
if (WCOREDUMP(status)) {
ALOGI("Process %d dumped core.", pid);
}
-#endif /* ifdef WCOREDUMP */
}
// If the just-crashed process is the system_server, bring down zygote
@@ -199,8 +191,6 @@ static void SetRLimits(JNIEnv* env, jobjectArray javaRlimits) {
}
}
-#if defined(HAVE_ANDROID_OS)
-
// The debug malloc library needs to know whether it's the zygote or a child.
extern "C" int gMallocLeakZygoteChild;
@@ -254,17 +244,6 @@ static void SetSchedulerPolicy(JNIEnv* env) {
}
}
-#else
-
-static int gMallocLeakZygoteChild = 0;
-
-static void EnableKeepCapabilities(JNIEnv*) {}
-static void DropCapabilitiesBoundingSet(JNIEnv*) {}
-static void SetCapabilities(JNIEnv*, int64_t, int64_t) {}
-static void SetSchedulerPolicy(JNIEnv*) {}
-
-#endif
-
// Create a private mount namespace and bind mount appropriate emulated
// storage for the given user.
static bool MountEmulatedStorage(uid_t uid, jint mount_mode) {
@@ -337,7 +316,6 @@ static bool MountEmulatedStorage(uid_t uid, jint mount_mode) {
return true;
}
-#if defined(__linux__)
static bool NeedsNoRandomizeWorkaround() {
#if !defined(__arm__)
return false;
@@ -357,7 +335,6 @@ static bool NeedsNoRandomizeWorkaround() {
return (major < 3) || ((major == 3) && (minor < 4));
#endif
}
-#endif
// Utility to close down the Zygote socket file descriptors while
// the child is still running as root with Zygote's privileges. Each
@@ -474,7 +451,6 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra
RuntimeAbort(env);
}
-#if defined(__linux__)
if (NeedsNoRandomizeWorkaround()) {
// Work around ARM kernel ASLR lossage (http://b/5817320).
int old_personality = personality(0xffffffff);
@@ -483,58 +459,49 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra
ALOGW("personality(%d) failed", new_personality);
}
}
-#endif
SetCapabilities(env, permittedCapabilities, effectiveCapabilities);
SetSchedulerPolicy(env);
-#if defined(HAVE_ANDROID_OS)
- { // NOLINT(whitespace/braces)
- const char* se_info_c_str = NULL;
- ScopedUtfChars* se_info = NULL;
- if (java_se_info != NULL) {
- se_info = new ScopedUtfChars(env, java_se_info);
- se_info_c_str = se_info->c_str();
- if (se_info_c_str == NULL) {
- ALOGE("se_info_c_str == NULL");
- RuntimeAbort(env);
- }
- }
- const char* se_name_c_str = NULL;
- ScopedUtfChars* se_name = NULL;
- if (java_se_name != NULL) {
- se_name = new ScopedUtfChars(env, java_se_name);
- se_name_c_str = se_name->c_str();
- if (se_name_c_str == NULL) {
- ALOGE("se_name_c_str == NULL");
- RuntimeAbort(env);
- }
- }
- rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
- if (rc == -1) {
- ALOGE("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid,
- is_system_server, se_info_c_str, se_name_c_str);
- RuntimeAbort(env);
- }
-
- // Make it easier to debug audit logs by setting the main thread's name to the
- // nice name rather than "app_process".
- if (se_info_c_str == NULL && is_system_server) {
- se_name_c_str = "system_server";
- }
- if (se_info_c_str != NULL) {
- SetThreadName(se_name_c_str);
- }
+ const char* se_info_c_str = NULL;
+ ScopedUtfChars* se_info = NULL;
+ if (java_se_info != NULL) {
+ se_info = new ScopedUtfChars(env, java_se_info);
+ se_info_c_str = se_info->c_str();
+ if (se_info_c_str == NULL) {
+ ALOGE("se_info_c_str == NULL");
+ RuntimeAbort(env);
+ }
+ }
+ const char* se_name_c_str = NULL;
+ ScopedUtfChars* se_name = NULL;
+ if (java_se_name != NULL) {
+ se_name = new ScopedUtfChars(env, java_se_name);
+ se_name_c_str = se_name->c_str();
+ if (se_name_c_str == NULL) {
+ ALOGE("se_name_c_str == NULL");
+ RuntimeAbort(env);
+ }
+ }
+ rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
+ if (rc == -1) {
+ ALOGE("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid,
+ is_system_server, se_info_c_str, se_name_c_str);
+ RuntimeAbort(env);
+ }
- delete se_info;
- delete se_name;
+ // Make it easier to debug audit logs by setting the main thread's name to the
+ // nice name rather than "app_process".
+ if (se_info_c_str == NULL && is_system_server) {
+ se_name_c_str = "system_server";
}
-#else
- UNUSED(is_system_server);
- UNUSED(java_se_info);
- UNUSED(java_se_name);
-#endif
+ if (se_info_c_str != NULL) {
+ SetThreadName(se_name_c_str);
+ }
+
+ delete se_info;
+ delete se_name;
UnsetSigChldHandler();