From 3574f1cc6b5d01aaaf47b884923b9408eabfc9ab Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 3 Aug 2023 19:32:27 -0700 Subject: [PATCH] Scripting: Export mPainter class --- src/script/image.c | 105 +++++++++++++++++++++++++++++++++++++++- src/script/test/image.c | 15 ++++++ 2 files changed, 119 insertions(+), 1 deletion(-) diff --git a/src/script/image.c b/src/script/image.c index 05ca9bcd4..13a520ad5 100644 --- a/src/script/image.c +++ b/src/script/image.c @@ -5,6 +5,15 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include +struct mScriptPainter { + struct mPainter painter; + struct mScriptValue* image; + struct mPainter* ppainter; // XXX: Figure out how to not need this without breaking the type system +}; + +mSCRIPT_DECLARE_STRUCT(mPainter); +mSCRIPT_DECLARE_STRUCT(mScriptPainter); + static struct mScriptValue* _mImageNew(unsigned width, unsigned height) { // For various reasons, it's probably a good idea to limit the maximum image size scripts can make if (width >= 10000 || height >= 10000) { @@ -30,6 +39,19 @@ static struct mScriptValue* _mImageLoad(const char* path) { result->flags = mSCRIPT_VALUE_FLAG_DEINIT; return result; } + +static struct mScriptValue* _mImageNewPainter(struct mScriptValue* image) { + mScriptValueRef(image); + struct mScriptPainter* painter = malloc(sizeof(*painter)); + mPainterInit(&painter->painter, image->value.opaque); + painter->image = image; + painter->ppainter = &painter->painter; + struct mScriptValue* result = mScriptValueAlloc(mSCRIPT_TYPE_MS_S(mScriptPainter)); + result->value.opaque = painter; + result->flags = mSCRIPT_VALUE_FLAG_DEINIT; + return result; +} + mSCRIPT_DECLARE_STRUCT_C_METHOD(mImage, U32, getPixel, mImageGetPixel, 2, U32, x, U32, y); mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mImage, setPixel, mImageSetPixel, 3, U32, x, U32, y, U32, color); mSCRIPT_DECLARE_STRUCT_C_METHOD_WITH_DEFAULTS(mImage, BOOL, save, mImageSave, 2, CHARP, path, CHARP, format); @@ -72,14 +94,95 @@ mSCRIPT_DEFINE_END; mSCRIPT_BIND_FUNCTION(mImageNew_Binding, W(mImage), _mImageNew, 2, U32, width, U32, height); mSCRIPT_BIND_FUNCTION(mImageLoad_Binding, W(mImage), _mImageLoad, 1, CHARP, path); +mSCRIPT_BIND_FUNCTION(mImageNewPainter_Binding, W(mScriptPainter), _mImageNewPainter, 1, W(mImage), image); + +void _mPainterSetBlend(struct mPainter* painter, bool enable) { + painter->blend = enable; +} + +void _mPainterSetFill(struct mPainter* painter, bool enable) { + painter->fill = enable; +} + +void _mPainterSetFillColor(struct mPainter* painter, uint32_t color) { + painter->fillColor = color; +} + +void _mPainterSetStrokeWidth(struct mPainter* painter, uint32_t width) { + painter->strokeWidth = width; +} + +void _mPainterSetStrokeColor(struct mPainter* painter, uint32_t color) { + painter->strokeColor = color; +} + +static struct mScriptValue* _mScriptPainterGet(struct mScriptPainter* painter, const char* name) { + struct mScriptValue val; + struct mScriptValue realPainter = mSCRIPT_MAKE(S(mPainter), &painter->painter); + if (!mScriptObjectGet(&realPainter, name, &val)) { + return &mScriptValueNull; + } + + struct mScriptValue* ret = malloc(sizeof(*ret)); + memcpy(ret, &val, sizeof(*ret)); + ret->refs = 1; + return ret; +} + +void _mScriptPainterDeinit(struct mScriptPainter* painter) { + mScriptValueDeref(painter->image); +} + +mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mPainter, setBlend, _mPainterSetBlend, 1, BOOL, enable); +mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mPainter, setFill, _mPainterSetFill, 1, BOOL, enable); +mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mPainter, setFillColor, _mPainterSetFillColor, 1, U32, color); +mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mPainter, setStrokeWidth, _mPainterSetStrokeWidth, 1, U32, width); +mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mPainter, setStrokeColor, _mPainterSetStrokeColor, 1, U32, color); +mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mPainter, drawRectangle, mPainterDrawRectangle, 4, S32, x, S32, y, S32, width, S32, height); +mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mPainter, drawLine, mPainterDrawLine, 4, S32, x1, S32, y1, S32, x2, S32, y2); +mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mPainter, drawCircle, mPainterDrawCircle, 3, S32, x, S32, y, S32, diameter); + +mSCRIPT_DEFINE_STRUCT(mPainter) + mSCRIPT_DEFINE_CLASS_DOCSTRING( + "A stateful object useful for performing drawing operations on an struct::mImage." + ) + mSCRIPT_DEFINE_DOCSTRING("Set whether or not alpha blending should be enabled when drawing") + mSCRIPT_DEFINE_STRUCT_METHOD(mPainter, setBlend) + mSCRIPT_DEFINE_DOCSTRING("Set whether or not the fill color should be applied when drawing") + mSCRIPT_DEFINE_STRUCT_METHOD(mPainter, setFill) + mSCRIPT_DEFINE_DOCSTRING("Set the fill color to be used when drawing") + mSCRIPT_DEFINE_STRUCT_METHOD(mPainter, setFillColor) + mSCRIPT_DEFINE_DOCSTRING("Set the stroke width to be used when drawing, or 0 to disable") + mSCRIPT_DEFINE_STRUCT_METHOD(mPainter, setStrokeWidth) + mSCRIPT_DEFINE_DOCSTRING("Set the stroke color to be used when drawing") + mSCRIPT_DEFINE_STRUCT_METHOD(mPainter, setStrokeColor) + mSCRIPT_DEFINE_DOCSTRING("Draw a rectangle with the specified dimensions") + mSCRIPT_DEFINE_STRUCT_METHOD(mPainter, drawRectangle) + mSCRIPT_DEFINE_DOCSTRING("Draw a line with the specified endpoints") + mSCRIPT_DEFINE_STRUCT_METHOD(mPainter, drawLine) + mSCRIPT_DEFINE_DOCSTRING("Draw a circle with the specified diameter with the given origin at the top-left corner of the bounding box") + mSCRIPT_DEFINE_STRUCT_METHOD(mPainter, drawCircle) +mSCRIPT_DEFINE_END; + +mSCRIPT_DECLARE_STRUCT_METHOD(mScriptPainter, W(mPainter), _get, _mScriptPainterGet, 1, CHARP, name); +mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptPainter, _deinit, _mScriptPainterDeinit, 0); + +mSCRIPT_DEFINE_STRUCT(mScriptPainter) + mSCRIPT_DEFINE_STRUCT_DEINIT(mScriptPainter) + mSCRIPT_DEFINE_STRUCT_MEMBER_NAMED(mScriptPainter, PS(mPainter), _painter, ppainter) + mSCRIPT_DEFINE_STRUCT_DEFAULT_GET(mScriptPainter) + mSCRIPT_DEFINE_STRUCT_CAST_TO_MEMBER(mScriptPainter, S(mPainter), _painter) +mSCRIPT_DEFINE_END; void mScriptContextAttachImage(struct mScriptContext* context) { mScriptContextExportNamespace(context, "image", (struct mScriptKVPair[]) { mSCRIPT_KV_PAIR(new, &mImageNew_Binding), mSCRIPT_KV_PAIR(load, &mImageLoad_Binding), + mSCRIPT_KV_PAIR(newPainter, &mImageNewPainter_Binding), mSCRIPT_KV_SENTINEL }); - mScriptContextSetDocstring(context, "image", "Methods for creating struct::mImage instances"); + mScriptContextSetDocstring(context, "image", "Methods for creating struct::mImage and struct::mPainter instances"); mScriptContextSetDocstring(context, "image.new", "Create a new image with the given dimensions"); mScriptContextSetDocstring(context, "image.load", "Load an image from a path. Currently, only `PNG` format is supported"); + mScriptContextSetDocstring(context, "image.newPainter", "Create a new painter from an existing imamge"); } diff --git a/src/script/test/image.c b/src/script/test/image.c index 541f7a210..88901d780 100644 --- a/src/script/test/image.c +++ b/src/script/test/image.c @@ -100,6 +100,20 @@ M_TEST_DEFINE(saveLoadRoundTrip) { } #endif +M_TEST_DEFINE(painterBasic) { + SETUP_LUA; + + TEST_PROGRAM("im = image.new(1, 1)"); + TEST_PROGRAM("painter = image.newPainter(im)"); + TEST_PROGRAM("assert(painter)"); + TEST_PROGRAM("painter:setFill(true)"); + TEST_PROGRAM("painter:setFillColor(0xFF123456)"); + TEST_PROGRAM("painter:drawRectangle(0, 0, 1, 1)"); + TEST_PROGRAM("assert(im:getPixel(0, 0) == 0xFF123456)"); + + mScriptContextDeinit(&context); +} + M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptImage, cmocka_unit_test(members), cmocka_unit_test(zeroDim), @@ -108,4 +122,5 @@ M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptImage, #ifdef USE_PNG cmocka_unit_test(saveLoadRoundTrip), #endif + cmocka_unit_test(painterBasic), )