From 2c8208f3a444098aee562f5a1ef620142807eda2 Mon Sep 17 00:00:00 2001 From: Scroggo Date: Wed, 15 Jun 2011 16:49:08 +0000 Subject: [PATCH] Improvements to the SampleApp (primarily Android). Reviewed at http://codereview.appspot.com/4587042/ Android - Added buttons for interaction without a keyboard. - Added the ability to zoom in to a specific point (roughly). - Added event handling (for showing a slideshow, for example). - Allow changing screen orientation - Updated README file, explaining how to build Multiplatform changes - Added SampleApp header file - Remove FPS when turning off measure FPS mode git-svn-id: http://skia.googlecode.com/svn/trunk@1596 2bbb7eff-a529-9590-31e7-b0007b416f81 --- android_sample/SampleApp/Android.mk | 3 + android_sample/SampleApp/AndroidManifest.xml | 3 +- android_sample/SampleApp/README.txt | 23 +-- android_sample/SampleApp/jni/sample-jni.cpp | 121 +++++++++-- android_sample/SampleApp/res/menu/sample.xml | 19 ++ .../SampleApp/res/values/strings.xml | 4 + .../src/com/skia/sampleapp/SampleApp.java | 69 ++++++- .../src/com/skia/sampleapp/SampleView.java | 36 +++- include/views/SkOSWindow_Android.h | 8 +- samplecode/SampleApp.cpp | 188 ++++++------------ samplecode/SampleApp.h | 145 ++++++++++++++ 11 files changed, 427 insertions(+), 192 deletions(-) create mode 100644 samplecode/SampleApp.h diff --git a/android_sample/SampleApp/Android.mk b/android_sample/SampleApp/Android.mk index 59f69936b..f2fd86068 100644 --- a/android_sample/SampleApp/Android.mk +++ b/android_sample/SampleApp/Android.mk @@ -14,6 +14,8 @@ LOCAL_PACKAGE_NAME := SampleApp LOCAL_JNI_SHARED_LIBRARIES := libskia-sample +LOCAL_PROGUARD_ENABLED := disabled + include $(BUILD_PACKAGE) ###################################### @@ -37,6 +39,7 @@ LOCAL_C_INCLUDES += \ external/skia/include/gpu \ external/skia/src/core \ external/skia/gpu/include \ + frameworks/base/opengl/include/GLES2 \ $(LOCAL_PATH)/jni LOCAL_SHARED_LIBRARIES := \ diff --git a/android_sample/SampleApp/AndroidManifest.xml b/android_sample/SampleApp/AndroidManifest.xml index 071ae0339..5980d298d 100644 --- a/android_sample/SampleApp/AndroidManifest.xml +++ b/android_sample/SampleApp/AndroidManifest.xml @@ -22,6 +22,7 @@ android:debuggable="true"> @@ -29,4 +30,4 @@ - + diff --git a/android_sample/SampleApp/README.txt b/android_sample/SampleApp/README.txt index a7d8e54d2..31e649291 100644 --- a/android_sample/SampleApp/README.txt +++ b/android_sample/SampleApp/README.txt @@ -1,25 +1,6 @@ Building the sample app for Android using an Android tree: -Copy this folder into an Android tree in packages/apps. In addition to jni, -res, and src, there needs to be a fourth folder named "skia_extra". This -will include the skia files which are not part of an Android checkout. It -should have three folders: include, samplecode, and src. - -skia/trunk/include/views -> skia_extra/include/views -skia/trunk/include/xml -> skia_extra/include/xml - -skia/trunk/samplecode -> skia_extra/samplecode - -skia/trunk/src/views -> skia_extra/src/views -skia/trunk/src/ports/SkXMLParser_empty.cpp -> skia_extra/src/ports/ -skia/trunk/src/xml -> skia_extra/src/xml - -skia/trunk/include/utils/android/AndroidKeyToSkKey.h -> jni/ - -From packages/apps/SampleApp, type "mm" to build, and install the -resulting apk. - -(It may be necessary to remove samples that do not build from -skia_extra/samplecode/samplecode_files.mk) +cd into external/skia/android_sample/SampleApp. +Type "mm" to build, and install the resulting apk. TODO: Instructions for building from SDK/NDK diff --git a/android_sample/SampleApp/jni/sample-jni.cpp b/android_sample/SampleApp/jni/sample-jni.cpp index 86d07a85b..be4e4d4a6 100644 --- a/android_sample/SampleApp/jni/sample-jni.cpp +++ b/android_sample/SampleApp/jni/sample-jni.cpp @@ -15,17 +15,18 @@ * */ -#include - -#include "SkCanvas.h" -#include "SkEvent.h" -#include "SkWindow.h" +#include "GrContext.h" +#include "SampleApp.h" #include "SkApplication.h" +#include "SkCanvas.h" +#include "SkDevice.h" +#include "SkEvent.h" +#include "SkGpuCanvas.h" +#include "SkWindow.h" + +#include #include "utils/android/AndroidKeyToSkKey.h" -#include "SkDevice.h" -#include "SkGpuCanvas.h" -#include "GrContext.h" /////////////////////////////////////////// ///////////////// Globals ///////////////// @@ -35,23 +36,27 @@ struct ActivityGlue { JNIEnv* m_env; jweak m_obj; jmethodID m_setTitle; + jmethodID m_startTimer; ActivityGlue() { m_env = NULL; m_obj = NULL; m_setTitle = NULL; + m_startTimer = NULL; } } gActivityGlue; struct WindowGlue { jweak m_obj; jmethodID m_inval; + jmethodID m_queueSkEvent; WindowGlue() { m_obj = NULL; m_inval = NULL; + m_queueSkEvent = NULL; } } gWindowGlue; -SkOSWindow* gWindow; +SampleWindow* gWindow; /////////////////////////////////////////// ///////////// SkOSWindow impl ///////////// @@ -80,9 +85,25 @@ void SkOSWindow::onHandleInval(const SkIRect& rect) /////////////// SkEvent impl ////////////// /////////////////////////////////////////// -void SkEvent::SignalQueueTimer(SkMSec) {} +void SkEvent::SignalQueueTimer(SkMSec ms) +{ + if (!gActivityGlue.m_env || !gActivityGlue.m_startTimer + || !gActivityGlue.m_obj || !ms) { + return; + } + gActivityGlue.m_env->CallVoidMethod(gActivityGlue.m_obj, + gActivityGlue.m_startTimer, ms); +} -void SkEvent::SignalNonEmptyQueue() {} +void SkEvent::SignalNonEmptyQueue() +{ + if (!gActivityGlue.m_env || !gWindowGlue.m_queueSkEvent + || !gWindowGlue.m_obj) { + return; + } + gActivityGlue.m_env->CallVoidMethod(gWindowGlue.m_obj, + gWindowGlue.m_queueSkEvent); +} /////////////////////////////////////////// ////////////////// JNI //////////////////// @@ -113,8 +134,22 @@ JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_handleClick( JNIEnv* env, jobject thiz, jint x, jint y, jint state); JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_createOSWindow( JNIEnv* env, jobject thiz, jobject jsampleView); +JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_setZoomCenter( + JNIEnv* env, jobject thiz, jfloat x, jfloat y); JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_zoom( JNIEnv* env, jobject thiz, jfloat factor); +JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_nextSample( + JNIEnv* env, jobject thiz, jboolean fprevious); +JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_toggleRendering( + JNIEnv* env, jobject thiz); +JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_toggleSlideshow( + JNIEnv* env, jobject thiz); +JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_toggleFps( + JNIEnv* env, jobject thiz); +JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_processSkEvent( + JNIEnv* env, jobject thiz); +JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_serviceQueueTimer( + JNIEnv* env, jobject thiz); }; JNIEXPORT bool JNICALL Java_com_skia_sampleapp_SampleApp_handleKeyDown( @@ -162,12 +197,14 @@ JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_updateSize(JNIEnv* env, JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_createOSWindow( JNIEnv* env, jobject thiz, jobject jsampleView) { - gWindow = create_sk_window(NULL); - // Only using a method on View. - jclass clazz = gActivityGlue.m_env->FindClass("android/opengl/GLSurfaceView"); + gWindow = new SampleWindow(NULL); + jclass clazz = gActivityGlue.m_env->FindClass( + "com/skia/sampleapp/SampleView"); gWindowGlue.m_obj = gActivityGlue.m_env->NewWeakGlobalRef(jsampleView); - gWindowGlue.m_inval = GetJMethod(gActivityGlue.m_env, clazz, "requestRender", - "()V"); + gWindowGlue.m_inval = GetJMethod(gActivityGlue.m_env, clazz, + "requestRender", "()V"); + gWindowGlue.m_queueSkEvent = GetJMethod(gActivityGlue.m_env, clazz, + "queueSkEvent", "()V"); gActivityGlue.m_env->DeleteLocalRef(clazz); } @@ -175,11 +212,12 @@ JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_init(JNIEnv* env, jobject thiz) { gActivityGlue.m_env = env; - // Only using a method on Activity. - jclass clazz = env->FindClass("android/app/Activity"); + jclass clazz = env->FindClass("com/skia/sampleapp/SampleApp"); gActivityGlue.m_obj = env->NewWeakGlobalRef(thiz); gActivityGlue.m_setTitle = GetJMethod(env, clazz, "setTitle", "(Ljava/lang/CharSequence;)V"); + gActivityGlue.m_startTimer = GetJMethod(gActivityGlue.m_env, clazz, + "startTimer", "(I)V"); env->DeleteLocalRef(clazz); application_init(); @@ -235,9 +273,56 @@ JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_draw( } } +JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_setZoomCenter( + JNIEnv* env, jobject thiz, jfloat x, jfloat y) +{ + gWindow->setZoomCenter(x, y); +} + JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_zoom( JNIEnv* env, jobject thiz, jfloat factor) { gWindow->changeZoomLevel(factor); } +JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_nextSample( + JNIEnv* env, jobject thiz, jboolean fprevious) +{ + if (fprevious) { + gWindow->previousSample(); + } else { + gWindow->nextSample(); + } +} + +JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_toggleRendering( + JNIEnv* env, jobject thiz) +{ + gWindow->toggleRendering(); +} + +JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_toggleSlideshow( + JNIEnv* env, jobject thiz) +{ + gWindow->toggleSlideshow(); +} + +JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_toggleFps( + JNIEnv* env, jobject thiz) +{ + gWindow->toggleFPS(); +} + +JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_processSkEvent( + JNIEnv* env, jobject thiz) +{ + if (SkEvent::ProcessEvent()) { + SkEvent::SignalNonEmptyQueue(); + } +} + +JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_serviceQueueTimer( + JNIEnv* env, jobject thiz) +{ + SkEvent::ServiceQueueTimer(); +} diff --git a/android_sample/SampleApp/res/menu/sample.xml b/android_sample/SampleApp/res/menu/sample.xml index 49f7ebb09..193f27776 100644 --- a/android_sample/SampleApp/res/menu/sample.xml +++ b/android_sample/SampleApp/res/menu/sample.xml @@ -15,6 +15,21 @@ --> + + + + diff --git a/android_sample/SampleApp/res/values/strings.xml b/android_sample/SampleApp/res/values/strings.xml index 72d3bc859..810ff4138 100644 --- a/android_sample/SampleApp/res/values/strings.xml +++ b/android_sample/SampleApp/res/values/strings.xml @@ -15,4 +15,8 @@ --> SampleApp + Overview + Toggle rendering + Slideshow + FPS diff --git a/android_sample/SampleApp/src/com/skia/sampleapp/SampleApp.java b/android_sample/SampleApp/src/com/skia/sampleapp/SampleApp.java index fe733603e..b1160104a 100644 --- a/android_sample/SampleApp/src/com/skia/sampleapp/SampleApp.java +++ b/android_sample/SampleApp/src/com/skia/sampleapp/SampleApp.java @@ -53,10 +53,9 @@ public class SampleApp extends Activity holder.addView(mView, new LinearLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); - + mTitle.setVisibility(View.GONE); getActionBar().setDisplayShowHomeEnabled(false); - } @Override @@ -87,11 +86,43 @@ public class SampleApp extends Activity } }); return true; + case R.id.prev: + mView.queueEvent(new Runnable() { + @Override + public void run() { + nextSample(true); + } + }); + return true; case R.id.next: mView.queueEvent(new Runnable() { @Override public void run() { - handleKeyDown(KeyEvent.KEYCODE_DPAD_RIGHT, 0); + nextSample(false); + } + }); + return true; + case R.id.toggle_rendering: + mView.queueEvent(new Runnable() { + @Override + public void run() { + toggleRendering(); + } + }); + return true; + case R.id.slideshow: + mView.queueEvent(new Runnable() { + @Override + public void run() { + toggleSlideshow(); + } + }); + return true; + case R.id.fps: + mView.queueEvent(new Runnable() { + @Override + public void run() { + toggleFps(); } }); return true; @@ -118,7 +149,6 @@ public class SampleApp extends Activity handleKeyDown(keycode, uni); } }); - return true; case KeyEvent.ACTION_UP: mView.queueEvent(new Runnable() { @@ -134,7 +164,7 @@ public class SampleApp extends Activity } private static final int SET_TITLE = 1; - + private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { @@ -148,22 +178,47 @@ public class SampleApp extends Activity } } }; - + @Override public void setTitle(CharSequence title) { mHandler.obtainMessage(SET_TITLE, title).sendToTarget(); } + // Called by JNI + @SuppressWarnings("unused") + private void startTimer(int ms) { + // After the delay, queue an event to the Renderer's thread + // to handle the event on the timer queue + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + mView.queueEvent(new Runnable() { + @Override + public void run() { + serviceQueueTimer(); + } + }); + } + }, ms); + } + native void draw(); native void init(); native void term(); // Currently depends on init having already been called. - native void createOSWindow(GLSurfaceView view); + native void createOSWindow(SampleView view); native void updateSize(int w, int h); native void handleClick(int x, int y, int state); native boolean handleKeyDown(int key, int uni); native boolean handleKeyUp(int key); native void zoom(float factor); + native void setZoomCenter(float x, float y); + native void nextSample(boolean previous); + native void toggleRendering(); + native void toggleSlideshow(); + native void toggleFps(); + native void processSkEvent(); + native void serviceQueueTimer(); static { System.loadLibrary("skia-sample"); diff --git a/android_sample/SampleApp/src/com/skia/sampleapp/SampleView.java b/android_sample/SampleApp/src/com/skia/sampleapp/SampleView.java index 0d76dcea9..5ea36a864 100644 --- a/android_sample/SampleApp/src/com/skia/sampleapp/SampleView.java +++ b/android_sample/SampleApp/src/com/skia/sampleapp/SampleView.java @@ -33,9 +33,10 @@ import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; public class SampleView extends GLSurfaceView implements OnScaleGestureListener { - + private final SampleApp mApp; private ScaleGestureDetector mDetector; + public SampleView(SampleApp app) { super(app); mApp = app; @@ -46,6 +47,17 @@ public class SampleView extends GLSurfaceView implements OnScaleGestureListener mDetector = new ScaleGestureDetector(app, this); } + // Called by JNI + @SuppressWarnings("unused") + private void queueSkEvent() { + queueEvent(new Runnable() { + @Override + public void run() { + mApp.processSkEvent(); + } + }); + } + @Override public boolean onTouchEvent(MotionEvent event) { mDetector.onTouchEvent(event); @@ -62,23 +74,33 @@ public class SampleView extends GLSurfaceView implements OnScaleGestureListener mApp.handleClick(x, y, action); } }); - + return true; } + // ScaleGestureDetector.OnScaleGestureListener implementation @Override public boolean onScaleBegin(ScaleGestureDetector detector) { + final float x = detector.getFocusX(); + final float y = detector.getFocusY(); + queueEvent(new Runnable() { + @Override + public void run() { + mApp.setZoomCenter(x, y); + } + }); return true; } @Override public boolean onScale(ScaleGestureDetector detector) { if (detector.getScaleFactor() != 1) { - final float difference = detector.getCurrentSpan() - detector.getPreviousSpan(); + final float difference = detector.getCurrentSpan() + - detector.getPreviousSpan(); queueEvent(new Runnable() { @Override public void run() { - mApp.zoom(difference * .03f); + mApp.zoom(difference * .01f); } }); @@ -96,11 +118,11 @@ public class SampleView extends GLSurfaceView implements OnScaleGestureListener public void onDrawFrame(GL10 gl) { mApp.draw(); } - + public void onSurfaceChanged(GL10 gl, int width, int height) { mApp.updateSize(width, height); } - + public void onSurfaceCreated(GL10 gl, EGLConfig config) { gl.glClearStencil(0); gl.glClear(gl.GL_STENCIL_BUFFER_BIT); @@ -108,4 +130,4 @@ public class SampleView extends GLSurfaceView implements OnScaleGestureListener mApp.createOSWindow(SampleView.this); } } -} \ No newline at end of file +} diff --git a/include/views/SkOSWindow_Android.h b/include/views/SkOSWindow_Android.h index 569f3f7f9..e547609e7 100644 --- a/include/views/SkOSWindow_Android.h +++ b/include/views/SkOSWindow_Android.h @@ -18,9 +18,8 @@ #define SkOSWindow_Android_DEFINED #include "SkWindow.h" -#include "SkEvent.h" -class GrContext; +class SkIRect; class SkOSWindow : public SkWindow { public: @@ -29,10 +28,7 @@ public: bool attachGL() { return true; } void detachGL() {} void presentGL() {} - virtual bool drawsToHardware() { return false; } - virtual bool setGrContext(GrContext*) { return false; } - virtual GrContext* getGrContext() { return NULL; } - virtual void changeZoomLevel(float delta) {} + protected: // overrides from SkWindow virtual void onHandleInval(const SkIRect&); diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp index aba105b3f..c457ef68a 100644 --- a/samplecode/SampleApp.cpp +++ b/samplecode/SampleApp.cpp @@ -1,3 +1,5 @@ +#include "SampleApp.h" + #include "SkCanvas.h" #include "SkDevice.h" #include "SkGpuCanvas.h" @@ -11,9 +13,12 @@ #include "SampleCode.h" #include "GrContext.h" -#include "SkTouchGesture.h" #include "SkTypeface.h" +#ifdef ANDROID + #include "gl2.h" +#endif + #define TEST_GPIPEx #ifdef TEST_GPIPE @@ -111,12 +116,6 @@ enum FlipAxisEnum { kFlipAxis_Y = (1 << 1) }; -enum SkTriState { - kFalse_SkTriState, - kTrue_SkTriState, - kUnknown_SkTriState, -}; - static SkTriState cycle_tristate(SkTriState state) { static const SkTriState gCycle[] = { /* kFalse_SkTriState -> */ kUnknown_SkTriState, @@ -244,121 +243,12 @@ static SkView* curr_view(SkWindow* wind) { return iter.next(); } -class SampleWindow : public SkOSWindow { - SkTDArray fSamples; -public: - SampleWindow(void* hwnd); - virtual ~SampleWindow(); +void SampleWindow::setZoomCenter(float x, float y) +{ + fZoomCenterX = SkFloatToScalar(x); + fZoomCenterY = SkFloatToScalar(y); +} - virtual void draw(SkCanvas* canvas); -#ifdef ANDROID - virtual bool drawsToHardware() { return fCanvasType == kGPU_CanvasType; } - virtual bool setGrContext(GrContext*); - virtual GrContext* getGrContext(); -#endif - -protected: - virtual void onDraw(SkCanvas* canvas); - virtual bool onHandleKey(SkKey key); - virtual bool onHandleChar(SkUnichar); - virtual void onSizeChange(); - - virtual SkCanvas* beforeChildren(SkCanvas*); - virtual void afterChildren(SkCanvas*); - virtual void beforeChild(SkView* child, SkCanvas* canvas); - virtual void afterChild(SkView* child, SkCanvas* canvas); - - virtual bool onEvent(const SkEvent& evt); - virtual bool onQuery(SkEvent* evt); - - virtual bool onDispatchClick(int x, int y, Click::State); - virtual bool onClick(Click* click); - virtual Click* onFindClickHandler(SkScalar x, SkScalar y); - -#if 0 - virtual bool handleChar(SkUnichar uni); - virtual bool handleEvent(const SkEvent& evt); - virtual bool handleKey(SkKey key); - virtual bool handleKeyUp(SkKey key); - virtual bool onHandleKeyUp(SkKey key); -#endif - -private: - int fCurrIndex; - - SkPicture* fPicture; - SkGpuCanvas* fGpuCanvas; - GrContext* fGrContext; - SkPath fClipPath; - - SkTouchGesture fGesture; - SkScalar fZoomLevel; - SkScalar fZoomScale; - - enum CanvasType { - kRaster_CanvasType, - kPicture_CanvasType, - kGPU_CanvasType - }; - CanvasType fCanvasType; - - bool fUseClip; - bool fNClip; - bool fRepeatDrawing; - bool fAnimating; - bool fRotate; - bool fScale; - bool fRequestGrabImage; - bool fUsePipe; - bool fMeasureFPS; - SkMSec fMeasureFPS_Time; - - // The following are for the 'fatbits' drawing - // Latest position of the mouse. - int fMouseX, fMouseY; - int fFatBitsScale; - // Used by the text showing position and color values. - SkTypeface* fTypeface; - bool fShowZoomer; - - SkTriState fLCDState; - SkTriState fAAState; - SkTriState fFilterState; - SkTriState fHintingState; - unsigned fFlipAxis; - - int fScrollTestX, fScrollTestY; - - bool make3DReady(); -#ifdef ANDROID - virtual -#endif - void changeZoomLevel(float delta); - - void loadView(SkView*); - void updateTitle(); - bool nextSample(); - - void toggleZoomer(); - bool zoomIn(); - bool zoomOut(); - void updatePointer(int x, int y); - void showZoomer(SkCanvas* canvas); - - void postAnimatingEvent() { - if (fAnimating) { - SkEvent* evt = new SkEvent(ANIMATING_EVENTTYPE); - evt->post(this->getSinkID(), ANIMATING_DELAY); - } - } - - - static CanvasType cycle_canvastype(CanvasType); - - typedef SkOSWindow INHERITED; -}; - -#ifdef ANDROID bool SampleWindow::setGrContext(GrContext* context) { if (fGrContext) { @@ -373,7 +263,6 @@ GrContext* SampleWindow::getGrContext() { return fGrContext; } -#endif bool SampleWindow::zoomIn() { @@ -577,8 +466,8 @@ void SampleWindow::draw(SkCanvas* canvas) { gAnimTimePrev = gAnimTime; gAnimTime = SkTime::GetMSecs(); - SkScalar cx = SkScalarHalf(this->width()); - SkScalar cy = SkScalarHalf(this->height()); + SkScalar cx = fZoomCenterX; + SkScalar cy = fZoomCenterY; if (fZoomLevel) { SkMatrix m; @@ -970,12 +859,25 @@ void SampleWindow::changeZoomLevel(float delta) { this->inval(NULL); } +bool SampleWindow::previousSample() { + fCurrIndex = (fCurrIndex - 1) % fSamples.count(); + this->loadView(fSamples[fCurrIndex]()); + return true; +} + bool SampleWindow::nextSample() { fCurrIndex = (fCurrIndex + 1) % fSamples.count(); this->loadView(fSamples[fCurrIndex]()); return true; } +void SampleWindow::postAnimatingEvent() { + if (fAnimating) { + SkEvent* evt = new SkEvent(ANIMATING_EVENTTYPE); + evt->post(this->getSinkID(), ANIMATING_DELAY); + } +} + bool SampleWindow::onEvent(const SkEvent& evt) { if (evt.isType(ANIMATING_EVENTTYPE)) { if (fAnimating) { @@ -1072,9 +974,7 @@ bool SampleWindow::onHandleChar(SkUnichar uni) { switch (uni) { case 'a': - fAnimating = !fAnimating; - this->postAnimatingEvent(); - this->updateTitle(); + this->toggleSlideshow(); return true; case 'b': fAAState = cycle_tristate(fAAState); @@ -1090,8 +990,7 @@ bool SampleWindow::onHandleChar(SkUnichar uni) { SkGraphics::SetFontCacheUsed(0); return true; case 'f': - fMeasureFPS = !fMeasureFPS; - this->inval(NULL); + this->toggleFPS(); break; case 'g': fRequestGrabImage = true; @@ -1153,6 +1052,24 @@ bool SampleWindow::onHandleChar(SkUnichar uni) { return this->INHERITED::onHandleChar(uni); } +void SampleWindow::toggleFPS() { + fMeasureFPS = !fMeasureFPS; + this->inval(NULL); + this->updateTitle(); +} + +void SampleWindow::toggleSlideshow() { + fAnimating = !fAnimating; + this->postAnimatingEvent(); + this->updateTitle(); +} + +void SampleWindow::toggleRendering() { + fCanvasType = cycle_canvastype(fCanvasType); + this->updateTitle(); + this->inval(NULL); +} + #include "SkDumpCanvas.h" bool SampleWindow::onHandleKey(SkKey key) { @@ -1174,9 +1091,7 @@ bool SampleWindow::onHandleKey(SkKey key) { } break; case kLeft_SkKey: - fCanvasType = cycle_canvastype(fCanvasType); - this->updateTitle(); - this->inval(NULL); + toggleRendering(); return true; case kUp_SkKey: if (USE_ARROWS_FOR_ZOOM) { @@ -1405,6 +1320,15 @@ void SampleWindow::onSizeChange() { #endif } + fZoomCenterX = SkScalarHalf(this->width()); + fZoomCenterY = SkScalarHalf(this->height()); + + if (fGrContext) { + glViewport(0, 0, SkScalarRound(this->width()), + SkScalarRound(this->height())); + fGrContext->resetContext(); + } + this->updateTitle(); // to refresh our config } diff --git a/samplecode/SampleApp.h b/samplecode/SampleApp.h new file mode 100644 index 000000000..37a3d0959 --- /dev/null +++ b/samplecode/SampleApp.h @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2011 Skia + * + * 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 SampleWindow_DEFINED +#define SampleWindow_DEFINED + +#include "SkWindow.h" + +#include "SampleCode.h" +#include "SkPath.h" +#include "SkScalar.h" +#include "SkTDArray.h" +#include "SkTouchGesture.h" +#include "SkWindow.h" + +class GrContext; + +class SkEvent; +class SkCanvas; +class SkGpuCanvas; +class SkPicture; +class SkTypeface; + +enum SkTriState { + kFalse_SkTriState, + kTrue_SkTriState, + kUnknown_SkTriState, +}; + +class SampleWindow : public SkOSWindow { + SkTDArray fSamples; +public: + SampleWindow(void* hwnd); + virtual ~SampleWindow(); + + virtual void draw(SkCanvas* canvas); + + void toggleRendering(); + void toggleSlideshow(); + void toggleFPS(); + bool drawsToHardware() { return fCanvasType == kGPU_CanvasType; } + bool setGrContext(GrContext*); + GrContext* getGrContext(); + void setZoomCenter(float x, float y); + void changeZoomLevel(float delta); + bool nextSample(); + bool previousSample(); + +protected: + virtual void onDraw(SkCanvas* canvas); + virtual bool onHandleKey(SkKey key); + virtual bool onHandleChar(SkUnichar); + virtual void onSizeChange(); + + virtual SkCanvas* beforeChildren(SkCanvas*); + virtual void afterChildren(SkCanvas*); + virtual void beforeChild(SkView* child, SkCanvas* canvas); + virtual void afterChild(SkView* child, SkCanvas* canvas); + + virtual bool onEvent(const SkEvent& evt); + virtual bool onQuery(SkEvent* evt); + + virtual bool onDispatchClick(int x, int y, Click::State); + virtual bool onClick(Click* click); + virtual Click* onFindClickHandler(SkScalar x, SkScalar y); + +private: + int fCurrIndex; + + SkPicture* fPicture; + SkGpuCanvas* fGpuCanvas; + GrContext* fGrContext; + SkPath fClipPath; + + SkTouchGesture fGesture; + SkScalar fZoomLevel; + SkScalar fZoomScale; + + enum CanvasType { + kRaster_CanvasType, + kPicture_CanvasType, + kGPU_CanvasType + }; + CanvasType fCanvasType; + + bool fUseClip; + bool fNClip; + bool fRepeatDrawing; + bool fAnimating; + bool fRotate; + bool fScale; + bool fRequestGrabImage; + bool fUsePipe; + bool fMeasureFPS; + SkMSec fMeasureFPS_Time; + + // The following are for the 'fatbits' drawing + // Latest position of the mouse. + int fMouseX, fMouseY; + int fFatBitsScale; + // Used by the text showing position and color values. + SkTypeface* fTypeface; + bool fShowZoomer; + + SkTriState fLCDState; + SkTriState fAAState; + SkTriState fFilterState; + SkTriState fHintingState; + unsigned fFlipAxis; + + int fScrollTestX, fScrollTestY; + SkScalar fZoomCenterX, fZoomCenterY; + + bool make3DReady(); + + void loadView(SkView*); + void updateTitle(); + + void toggleZoomer(); + bool zoomIn(); + bool zoomOut(); + void updatePointer(int x, int y); + void showZoomer(SkCanvas* canvas); + + void postAnimatingEvent(); + + static CanvasType cycle_canvastype(CanvasType); + + typedef SkOSWindow INHERITED; +}; + +#endif