experimental hack to write a forth engine to drive skia
git-svn-id: http://skia.googlecode.com/svn/trunk@343 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/forth/SampleForth.cpp b/forth/SampleForth.cpp
new file mode 100644
index 0000000..d207cb8
--- /dev/null
+++ b/forth/SampleForth.cpp
@@ -0,0 +1,248 @@
+#include "SampleCode.h"
+#include "SkColorPriv.h"
+#include "SkGradientShader.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkUtils.h"
+#include "Forth.h"
+
+class MyOutput : public ForthOutput {
+public:
+ SkString fStr;
+
+ virtual void show(const char text[]) {
+ fStr.set(text);
+ }
+};
+
+class SkForthCtx {
+public:
+ SkCanvas fCanvas;
+ SkPaint fPaint;
+
+ void init(const SkBitmap& bm) {
+ fCanvas.setBitmapDevice(bm);
+ fPaint.setAntiAlias(true);
+ }
+};
+
+class SkForthCtx_FW : public ForthWord {
+public:
+ SkForthCtx_FW() : fCtx(NULL) {}
+
+ void setCtx(SkForthCtx* ctx) { fCtx = ctx; }
+
+ SkCanvas* canvas() const { return &fCtx->fCanvas; }
+ SkPaint* paint() const { return &fCtx->fPaint; }
+
+private:
+ SkForthCtx* fCtx;
+};
+
+class setColor_FW : public SkForthCtx_FW {
+public:
+ virtual void exec(ForthEngine* fe) {
+ paint()->setColor(fe->pop());
+ }
+
+ static SkForthCtx_FW* New() { return new setColor_FW; }
+};
+
+class setStyle_FW : public SkForthCtx_FW {
+public:
+ virtual void exec(ForthEngine* fe) {
+ paint()->setStyle((SkPaint::Style)fe->pop());
+ }
+
+ static SkForthCtx_FW* New() { return new setStyle_FW; }
+};
+
+class setStrokeWidth_FW : public SkForthCtx_FW {
+public:
+ virtual void exec(ForthEngine* fe) {
+ paint()->setStrokeWidth(fe->fpop());
+ }
+
+ static SkForthCtx_FW* New() { return new setStrokeWidth_FW; }
+};
+
+class translate_FW : public SkForthCtx_FW {
+public:
+ virtual void exec(ForthEngine* fe) {
+ SkScalar dy = fe->fpop();
+ SkScalar dx = fe->fpop();
+ canvas()->translate(dx, dy);
+ }
+
+ static SkForthCtx_FW* New() { return new translate_FW; }
+};
+
+class drawColor_FW : public SkForthCtx_FW {
+public:
+ virtual void exec(ForthEngine* fe) {
+ canvas()->drawColor(fe->pop());
+ }
+
+ static SkForthCtx_FW* New() { return new drawColor_FW; }
+};
+
+class drawRect_FW : public SkForthCtx_FW {
+public:
+ virtual void exec(ForthEngine* fe) {
+ SkRect r;
+ r.fBottom = fe->fpop();
+ r.fRight = fe->fpop();
+ r.fTop = fe->fpop();
+ r.fLeft = fe->fpop();
+ canvas()->drawRect(r, *paint());
+ }
+
+ static SkForthCtx_FW* New() { return new drawRect_FW; }
+};
+
+class drawCircle_FW : public SkForthCtx_FW {
+public:
+ virtual void exec(ForthEngine* fe) {
+ SkScalar radius = fe->fpop();
+ SkScalar y = fe->fpop();
+ SkScalar x = fe->fpop();
+ canvas()->drawCircle(x, y, radius, *paint());
+ }
+
+ static SkForthCtx_FW* New() { return new drawCircle_FW; }
+};
+
+class drawLine_FW : public SkForthCtx_FW {
+public:
+ virtual void exec(ForthEngine* fe) {
+ SkScalar x0, y0, x1, y1;
+ y1 = fe->fpop();
+ x1 = fe->fpop();
+ y0 = fe->fpop();
+ x0 = fe->fpop();
+ canvas()->drawLine(x0, y0, x1, y1, *paint());
+ }
+
+ static SkForthCtx_FW* New() { return new drawLine_FW; }
+};
+
+static const struct {
+ const char* fName;
+ SkForthCtx_FW* (*fProc)();
+} gWordRecs[] = {
+ { "setColor", setColor_FW::New },
+ { "setStyle", setStyle_FW::New },
+ { "setStrokeWidth", setStrokeWidth_FW::New },
+ { "translate", translate_FW::New },
+ { "drawColor", drawColor_FW::New },
+ { "drawRect", drawRect_FW::New },
+ { "drawCircle", drawCircle_FW::New },
+ { "drawLine", drawLine_FW::New },
+};
+
+static void load_words(ForthEnv* env, SkForthCtx* ctx) {
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gWordRecs); i++) {
+ SkForthCtx_FW* word = gWordRecs[i].fProc();
+ word->setCtx(ctx);
+ env->addWord(gWordRecs[i].fName, word);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+class ForthView : public SkView {
+ ForthEnv fEnv;
+ ForthWord* fOnClickWord;
+
+ SkBitmap fBM;
+ SkForthCtx fContext;
+public:
+ ForthView() {
+ load_words(&fEnv, &fContext);
+
+ fBM.setConfig(SkBitmap::kARGB_8888_Config, 640, 480);
+ fBM.allocPixels();
+ fBM.eraseColor(0);
+ fContext.init(fBM);
+
+ fEnv.parse(": view.onClick ( x y -- ) 10. drawCircle ;");
+ fOnClickWord = fEnv.findWord("view.onClick");
+#if 0
+ env.parse(
+ ": draw1 "
+ "10. setStrokeWidth 1 setStyle #FF000000 setColor "
+ "10. 20. 200. 100. drawLine "
+ "0 setStyle #80FF0000 setColor "
+ "50. 50. 250. 150. drawRect "
+ ";");
+ env.parse("#FF0000FF drawColor "
+ "draw1 "
+ "150. 120. translate "
+ "draw1 "
+ );
+#endif
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt)) {
+ SampleCode::TitleR(evt, "Forth");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas) {
+ canvas->drawColor(0xFFDDDDDD);
+ }
+
+ void test_onClick(ForthEnv* env) {
+ ForthWord* word = env->findWord("view.onClick");
+ if (word) {
+ const intptr_t idata[2] = { 40, 2 };
+ intptr_t odata[1] = { -1 };
+ ForthCallBlock block;
+ block.in_data = idata;
+ block.in_count = 2;
+ block.out_data = odata;
+ block.out_count = 1;
+ word->call(&block);
+ SkDebugf("after view.onClick depth %d count %d top %d\n",
+ block.out_depth, block.out_count, odata[0]);
+ } else {
+ SkDebugf("------ view.onClick not found\n");
+ }
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ drawBG(canvas);
+ canvas->drawBitmap(fBM, 0, 0, NULL);
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
+ return fOnClickWord ? new Click(this) : NULL;
+ }
+
+ virtual bool onClick(Click* click) {
+ intptr_t idata[2] = {
+ f2i_bits(click->fCurr.fX), f2i_bits(click->fCurr.fY)
+ };
+ ForthCallBlock block;
+ block.in_data = idata;
+ block.in_count = 2;
+ block.out_count = 0;
+ fOnClickWord->call(&block);
+ this->inval(NULL);
+ return true;
+ }
+
+private:
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new ForthView; }
+static SkViewRegister reg(MyFactory);
+