SkiaExamples improvements.

Make it possible for a client to write a Hello World in less than 50 lines.

R=caryclark@google.com

Review URL: https://codereview.chromium.org/18574002

git-svn-id: http://skia.googlecode.com/svn/trunk@10319 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
sglez@google.com 2013-07-24 17:48:03 +00:00
parent 03d5f4b598
commit 43f2b2c833
5 changed files with 247 additions and 168 deletions

View File

@ -7,7 +7,7 @@
*
*/
#include "BaseExample.h"
#include "SkExample.h"
#include "SkApplication.h"
#include "SkDraw.h"
@ -15,98 +15,96 @@
#include "SkGraphics.h"
#include "SkUnitMappers.h"
class HelloSkia : public BaseExample {
public:
HelloSkia(void* hWnd, int argc, char** argv)
: INHERITED(hWnd, argc, argv)
{
fBGColor = SK_ColorWHITE;
fRotationAngle = SkIntToScalar(0);
class HelloSkia : public SkExample {
public:
HelloSkia(SkExampleWindow* window) : SkExample(window) {
fName = "HelloSkia";
fBGColor = SK_ColorWHITE;
fRotationAngle = SkIntToScalar(0);
setupBackend(kGPU_DeviceType);
// Another option is software rendering:
// setupBackend(kRaster_DeviceType);
}
fWindow->setupBackend(SkExampleWindow::kGPU_DeviceType);
// Another option is software rendering:
// setupBackend(SkExampleWindow::kRaster_DeviceType);
}
protected:
virtual void draw(SkCanvas* canvas) SK_OVERRIDE {
// Clear background
canvas->drawColor(fBGColor);
protected:
void draw(SkCanvas* canvas) {
// Clear background
canvas->drawColor(fBGColor);
SkPaint paint;
paint.setColor(SK_ColorRED);
SkPaint paint;
paint.setColor(SK_ColorRED);
// Draw a rectangle with blue paint
SkRect rect = {
// Draw a rectangle with blue paint
SkRect rect = {
SkIntToScalar(10), SkIntToScalar(10),
SkIntToScalar(128), SkIntToScalar(128)
};
canvas->drawRect(rect, paint);
};
canvas->drawRect(rect, paint);
// Set up a linear gradient and draw a circle
{
SkPoint linearPoints[] = {
// Set up a linear gradient and draw a circle
{
SkPoint linearPoints[] = {
{SkIntToScalar(0), SkIntToScalar(0)},
{SkIntToScalar(300), SkIntToScalar(300)}
};
SkColor linearColors[] = {SK_ColorGREEN, SK_ColorBLACK};
};
SkColor linearColors[] = {SK_ColorGREEN, SK_ColorBLACK};
SkUnitMapper* linearMapper = new SkDiscreteMapper(100);
SkAutoUnref lm_deleter(linearMapper);
SkUnitMapper* linearMapper = new SkDiscreteMapper(100);
SkAutoUnref lm_deleter(linearMapper);
SkShader* shader = SkGradientShader::CreateLinear(
linearPoints, linearColors, NULL, 2,
SkShader::kMirror_TileMode, linearMapper);
SkAutoUnref shader_deleter(shader);
SkShader* shader = SkGradientShader::CreateLinear(
linearPoints, linearColors, NULL, 2,
SkShader::kMirror_TileMode, linearMapper);
SkAutoUnref shader_deleter(shader);
paint.setShader(shader);
paint.setFlags(SkPaint::kAntiAlias_Flag);
paint.setShader(shader);
paint.setFlags(SkPaint::kAntiAlias_Flag);
canvas->drawCircle(SkIntToScalar(200), SkIntToScalar(200),
SkIntToScalar(64), paint);
canvas->drawCircle(SkIntToScalar(200), SkIntToScalar(200),
SkIntToScalar(64), paint);
// Detach shader
paint.setShader(NULL);
}
// Draw a message with a nice black paint.
paint.setFlags(
SkPaint::kAntiAlias_Flag |
SkPaint::kSubpixelText_Flag | // ... avoid waggly text when rotating.
SkPaint::kUnderlineText_Flag);
paint.setColor(SK_ColorBLACK);
paint.setTextSize(SkIntToScalar(20));
canvas->save();
static const char message[] = "Hello Skia!!!";
// Translate and rotate
canvas->translate(SkIntToScalar(300), SkIntToScalar(300));
fRotationAngle += SkDoubleToScalar(0.2);
if (fRotationAngle > SkDoubleToScalar(360.0)) {
fRotationAngle -= SkDoubleToScalar(360.0);
}
canvas->rotate(fRotationAngle);
// Draw the text:
canvas->drawText(message, strlen(message), SkIntToScalar(0), SkIntToScalar(0), paint);
canvas->restore();
// Invalidate the window to force a redraw. Poor man's animation mechanism.
this->inval(NULL);
INHERITED::draw(canvas);
// Detach shader
paint.setShader(NULL);
}
private:
SkScalar fRotationAngle;
SkColor fBGColor;
typedef BaseExample INHERITED;
// Draw a message with a nice black paint.
paint.setFlags(
SkPaint::kAntiAlias_Flag |
SkPaint::kSubpixelText_Flag | // ... avoid waggly text when rotating.
SkPaint::kUnderlineText_Flag);
paint.setColor(SK_ColorBLACK);
paint.setTextSize(SkIntToScalar(20));
canvas->save();
static const char message[] = "Hello Skia!!!";
// Translate and rotate
canvas->translate(SkIntToScalar(300), SkIntToScalar(300));
fRotationAngle += SkDoubleToScalar(0.2);
if (fRotationAngle > SkDoubleToScalar(360.0)) {
fRotationAngle -= SkDoubleToScalar(360.0);
}
canvas->rotate(fRotationAngle);
// Draw the text:
canvas->drawText(message, strlen(message), SkIntToScalar(0), SkIntToScalar(0), paint);
canvas->restore();
// Invalidate the window to force a redraw. Poor man's animation mechanism.
this->fWindow->inval(NULL);
}
private:
SkScalar fRotationAngle;
SkColor fBGColor;
};
SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) {
return new HelloSkia(hwnd, argc, argv);
static SkExample* MyFactory(SkExampleWindow* window) {
return new HelloSkia(window);
}
// Register this class as a Skia Example.
SkExample::Registry registry(MyFactory);

View File

@ -7,15 +7,25 @@
*
*/
#include "BaseExample.h"
#include "SkExample.h"
#include "gl/GrGLUtil.h"
#include "gl/GrGLDefines.h"
#include "gl/GrGLInterface.h"
#include "SkApplication.h"
#include "SkCommandLineFlags.h"
#include "SkGpuDevice.h"
#include "SkGraphics.h"
DEFINE_string2(match, m, NULL, "[~][^]substring[$] [...] of test name to run.\n" \
"Multiple matches may be separated by spaces.\n" \
"~ causes a matching test to always be skipped\n" \
"^ requires the start of the test to match\n" \
"$ requires the end of the test to match\n" \
"^ and $ requires an exact match\n" \
"If a test does not match any list entry,\n" \
"it is skipped unless some list entry starts with ~");
void application_init() {
SkGraphics::Init();
SkEvent::Init();
@ -26,10 +36,24 @@ void application_term() {
SkGraphics::Term();
}
BaseExample::BaseExample(void* hWnd, int argc, char** argv)
: INHERITED(hWnd) {}
SkExampleWindow::SkExampleWindow(void* hwnd)
: INHERITED(hwnd) {
fRegistry = SkExample::Registry::Head();
fCurrExample = fRegistry->factory()(this);
void BaseExample::tearDownBackend() {
if (FLAGS_match.count()) {
for(int i = 0; i < FLAGS_match.count(); ++i) {
fMatchStrs.push(FLAGS_match[i]);
}
// Start with the a matching sample if possible.
bool found = this->findNextMatch();
if (!found) {
SkDebugf("No matching SkExample found.\n");
}
}
}
void SkExampleWindow::tearDownBackend() {
if (kGPU_DeviceType == fType) {
SkSafeUnref(fContext);
fContext = NULL;
@ -44,7 +68,7 @@ void BaseExample::tearDownBackend() {
}
}
bool BaseExample::setupBackend(DeviceType type) {
bool SkExampleWindow::setupBackend(DeviceType type) {
fType = type;
this->setConfig(SkBitmap::kARGB_8888_Config);
@ -70,7 +94,7 @@ bool BaseExample::setupBackend(DeviceType type) {
return true;
}
void BaseExample::setupRenderTarget() {
void SkExampleWindow::setupRenderTarget() {
GrBackendRenderTargetDesc desc;
desc.fWidth = SkScalarRound(width());
desc.fHeight = SkScalarRound(height());
@ -88,7 +112,7 @@ void BaseExample::setupRenderTarget() {
fContext->setRenderTarget(fRenderTarget);
}
SkCanvas* BaseExample::createCanvas() {
SkCanvas* SkExampleWindow::createCanvas() {
if (fType == kGPU_DeviceType) {
if (NULL != fContext && NULL != fRenderTarget) {
SkAutoTUnref<SkDevice> device(new SkGpuDevice(fContext, fRenderTarget));
@ -100,7 +124,10 @@ SkCanvas* BaseExample::createCanvas() {
return INHERITED::createCanvas();
}
void BaseExample::draw(SkCanvas* canvas) {
void SkExampleWindow::draw(SkCanvas* canvas) {
if (NULL != fCurrExample) {
fCurrExample->draw(canvas);
}
if (fType == kGPU_DeviceType) {
SkASSERT(NULL != fContext);
@ -118,12 +145,12 @@ void BaseExample::draw(SkCanvas* canvas) {
INHERITED::present();
}
void BaseExample::onSizeChange() {
void SkExampleWindow::onSizeChange() {
setupRenderTarget();
}
#ifdef SK_BUILD_FOR_WIN
void BaseExample::onHandleInval(const SkIRect& rect) {
void SkExampleWindow::onHandleInval(const SkIRect& rect) {
RECT winRect;
winRect.top = rect.top();
winRect.bottom = rect.bottom();
@ -132,3 +159,39 @@ void BaseExample::onHandleInval(const SkIRect& rect) {
InvalidateRect((HWND)this->getHWND(), &winRect, false);
}
#endif
bool SkExampleWindow::findNextMatch() {
bool found = false;
// Avoid infinite loop by knowing where we started.
const SkExample::Registry* begin = fRegistry;
while (!found) {
fRegistry = fRegistry->next();
if (NULL == fRegistry) { // Reached the end of the registered samples. GOTO head.
fRegistry = SkExample::Registry::Head();
}
SkExample* next = fRegistry->factory()(this);
if (!SkCommandLineFlags::ShouldSkip(fMatchStrs, next->getName().c_str())) {
fCurrExample = next;
found = true;
}
if (begin == fRegistry) { // We looped through every sample without finding anything.
break;
}
}
return found;
}
bool SkExampleWindow::onHandleChar(SkUnichar unichar) {
if ('n' == unichar) {
bool found = findNextMatch();
if (!found) {
SkDebugf("No SkExample that matches your query\n");
}
}
return true;
}
SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) {
SkCommandLineFlags::Parse(argc, argv);
return new SkExampleWindow(hwnd);
}

View File

@ -7,23 +7,41 @@
*
*/
#ifndef BaseExample_DEFINED
#define BaseExample_DEFINED
#ifndef SkExample_DEFINED
#define SkExample_DEFINED
#include "SkWindow.h"
#include "SkTRegistry.h"
class GrContext;
struct GrGLInterface;
class GrRenderTarget;
class SkCanvas;
class SkExampleWindow;
class BaseExample : public SkOSWindow {
class SkExample : public SkNoncopyable {
public:
SkExample(SkExampleWindow* window) : fWindow(window) {}
// Your class should override this method to do its thing.
virtual void draw(SkCanvas* canvas) = 0;
SkString getName() { return fName; };
// Use this public registry to tell the world about your sample.
typedef SkTRegistry<SkExample*, SkExampleWindow*> Registry;
protected:
SkExampleWindow* fWindow;
SkString fName;
};
class SkExampleWindow : public SkOSWindow {
public:
enum DeviceType {
kRaster_DeviceType,
kGPU_DeviceType,
};
BaseExample(void* hWnd, int argc, char** argv);
SkExampleWindow(void* hwnd);
// Changes the device type of the object.
bool setupBackend(DeviceType type);
@ -32,7 +50,6 @@ public:
DeviceType getDeviceType() const { return fType; }
protected:
// Your class should override this method to do its thing.
virtual void draw(SkCanvas* canvas) SK_OVERRIDE;
virtual void onSizeChange() SK_OVERRIDE;
@ -44,14 +61,22 @@ protected:
SkCanvas* createCanvas() SK_OVERRIDE;
private:
bool findNextMatch(); // Set example to the first one that matches FLAGS_match.
void setupRenderTarget();
bool onHandleChar(SkUnichar unichar) SK_OVERRIDE;
DeviceType fType;
SkExample* fCurrExample;
const SkExample::Registry* fRegistry;
SkTDArray<const char*> fMatchStrs;
GrContext* fContext;
GrRenderTarget* fRenderTarget;
AttachmentInfo fAttachmentInfo;
const GrGLInterface* fInterface;
typedef SkOSWindow INHERITED;
};
#endif

View File

@ -1,76 +0,0 @@
{
'targets' : [
{
'target_name': 'SkiaExamples',
'type': 'executable',
'mac_bundle' : 1,
'include_dirs' : [],
'includes': [],
'sources': [
'../experimental/SkiaExamples/HelloSkiaExample.cpp',
'../experimental/SkiaExamples/BaseExample.h',
'../experimental/SkiaExamples/BaseExample.cpp',
],
'dependencies': [
'skia_lib.gyp:skia_lib',
'views.gyp:views',
'xml.gyp:xml',
],
'conditions' : [
[ 'skia_gpu == 1', {
'include_dirs' : [
'../src/gpu', #gl/GrGLUtil.h
]
}],
[ 'skia_os == "win"', {
'sources' : [
'../src/views/win/SkOSWindow_Win.cpp',
'../src/views/win/skia_win.cpp',
],
},
],
[ 'skia_os == "mac"', {
'sources': [
# SkiaExamples specific files
'../experimental/SkiaExamples/SkiaExamples-Info.plist',
'../experimental/SkiaExamples/SkExampleNSView.h',
'../experimental/SkiaExamples/SkExampleNSView.mm',
# Mac files
'../src/views/mac/SampleAppDelegate.h',
'../src/views/mac/SampleAppDelegate.mm',
'../src/views/mac/SkEventNotifier.mm',
'../src/views/mac/skia_mac.mm',
'../src/views/mac/SkNSView.h',
'../src/views/mac/SkNSView.mm',
'../src/views/mac/SkOptionsTableView.h',
'../src/views/mac/SkOptionsTableView.mm',
'../src/views/mac/SkOSWindow_Mac.mm',
'../src/views/mac/SkTextFieldCell.h',
'../src/views/mac/SkTextFieldCell.m',
],
'include_dirs' : [
'../src/views/mac/'
],
'link_settings': {
},
'xcode_settings' : {
'INFOPLIST_FILE' : '../experimental/SkiaExamples/SkiaExamples-Info.plist',
},
'mac_bundle_resources' : [
'../experimental/SkiaExamples/SkiaExamples.xib'
],
}
],
],
}
],
}
# Local Variables:
# tab-width:2
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=2 shiftwidth=2:

View File

@ -18,6 +18,75 @@
],
},
},
{
'target_name': 'SkiaExamples',
'type': 'executable',
'mac_bundle' : 1,
'include_dirs' : [
'../tools/flags',
],
'includes': [],
'sources': [
'../experimental/SkiaExamples/SkExample.h',
'../experimental/SkiaExamples/SkExample.cpp',
'../experimental/SkiaExamples/HelloSkiaExample.cpp',
],
'dependencies': [
'skia_lib.gyp:skia_lib',
'views.gyp:views',
'xml.gyp:xml',
'flags.gyp:flags'
],
'conditions' : [
[ 'skia_gpu == 1', {
'include_dirs' : [
'../src/gpu', #gl/GrGLUtil.h
]
}],
[ 'skia_os == "win"', {
'sources' : [
'../src/views/win/SkOSWindow_Win.cpp',
'../src/views/win/skia_win.cpp',
],
},
],
[ 'skia_os == "mac"', {
'sources': [
# SkiaExamples specific files
'../experimental/SkiaExamples/SkiaExamples-Info.plist',
'../experimental/SkiaExamples/SkExampleNSView.h',
'../experimental/SkiaExamples/SkExampleNSView.mm',
# Mac files
'../src/views/mac/SampleAppDelegate.h',
'../src/views/mac/SampleAppDelegate.mm',
'../src/views/mac/SkEventNotifier.mm',
'../src/views/mac/skia_mac.mm',
'../src/views/mac/SkNSView.h',
'../src/views/mac/SkNSView.mm',
'../src/views/mac/SkOptionsTableView.h',
'../src/views/mac/SkOptionsTableView.mm',
'../src/views/mac/SkOSWindow_Mac.mm',
'../src/views/mac/SkTextFieldCell.h',
'../src/views/mac/SkTextFieldCell.m',
],
'include_dirs' : [
'../src/views/mac/'
],
'link_settings': {
},
'xcode_settings' : {
'INFOPLIST_FILE' : '../experimental/SkiaExamples/SkiaExamples-Info.plist',
},
'mac_bundle_resources' : [
'../experimental/SkiaExamples/SkiaExamples.xib'
],
}
],
],
}
],
}