diff --git a/libraries/script-engine/src/CanvasCommand.cpp b/libraries/script-engine/src/CanvasCommand.cpp index 3d27cec949..dd59c7b91f 100644 --- a/libraries/script-engine/src/CanvasCommand.cpp +++ b/libraries/script-engine/src/CanvasCommand.cpp @@ -26,8 +26,9 @@ STATIC_SCRIPT_TYPES_INITIALIZER((+[](ScriptManager* manager){ scriptRegisterMetaType(scriptEngine, "CanvasCommand"); scriptRegisterMetaType(scriptEngine, "CanvasImage"); - scriptRegisterMetaType(scriptEngine, "CanvasPath"); + scriptRegisterMetaType(scriptEngine, "QPainterPath"); scriptRegisterMetaType, qVectorCanvasCommandToScriptValue, qVectorCanvasCommandFromScriptValue>(scriptEngine); + scriptRegisterMetaType(scriptEngine, "CanvasPathElement"); })); const QString CMD_TYPE_PROP_NAME = "type"; @@ -408,6 +409,45 @@ QPainterPath qPainterPathFromScriptValue(const ScriptValue& object) { return p; } +ScriptValue canvasPathElementToScriptValue(ScriptEngine* engine, const CanvasPathElement& elem) { + auto obj = engine->newObject(); + obj.setProperty("type", elem.type); + obj.setProperty("x", elem.x); + obj.setProperty("y", elem.y); + + if (elem.type == QPainterPath::CurveToElement) { + obj.setProperty("c1x", elem.c1x); + obj.setProperty("c1y", elem.c1y); + obj.setProperty("c2x", elem.c2x); + obj.setProperty("c2y", elem.c2y); + } + + return obj; +} + +bool canvasPathElementFromScriptValue(const ScriptValue& obj, CanvasPathElement& elem) { + int type = obj.property("type").toInt32(); + + elem.type = type; + elem.x = obj.property("x").toNumber(); + elem.y = obj.property("y").toNumber(); + + if (type == QPainterPath::CurveToElement) { + elem.c1x = obj.property("c1x").toNumber(); + elem.c1y = obj.property("c1y").toNumber(); + elem.c2x = obj.property("c2x").toNumber(); + elem.c2y = obj.property("c2y").toNumber(); + } + + return true; +} + +CanvasPathElement canvasPathElementFromScriptValue(const ScriptValue& object) { + CanvasPathElement e; + canvasPathElementFromScriptValue(object, e); + return e; +} + CanvasCommand CanvasCommandInterface::setStrokeWidth(qreal width) const { return CanvasCommand::setStrokeWidth(width); } @@ -475,3 +515,49 @@ CanvasCommand CanvasCommandInterface::line(qreal x1, qreal y1, qreal x2, qreal y CanvasCommand CanvasCommandInterface::imageCopy(const CanvasImage& image, qreal sx, qreal sy, qreal sw, qreal sh, qreal dx, qreal dy, qreal dw, qreal dh) const { return CanvasCommand::imageCopy(image, QRectF(sx, sy, sw, sh), QRectF(dx, dy, dw, dh)); } + +CanvasPathElement CanvasCommandInterface::pathMoveTo(qreal x, qreal y) const { + return CanvasPathElement(QPainterPath::MoveToElement, x, y); +} + +CanvasPathElement CanvasCommandInterface::pathLineTo(qreal x, qreal y) const { + return CanvasPathElement(QPainterPath::LineToElement, x, y); +} + +CanvasPathElement CanvasCommandInterface::pathCubicTo(qreal c1x, qreal c1y, qreal c2x, qreal c2y, qreal x, qreal y) const { + return CanvasPathElement(QPainterPath::CurveToElement, x, y, c1x, c1y, c2x, c2y); +} + +CanvasPathElement CanvasCommandInterface::pathQuadTo(qreal cx, qreal cy, qreal endX, qreal endY) const { + QPainterPath path; + path.quadTo(cx, cy, endX, endY); + + auto elem = CanvasPathElement(); + elem.type = QPainterPath::CurveToElement; + elem.c1x = path.elementAt(0).x; + elem.c1y = path.elementAt(0).y; + elem.c2x = path.elementAt(1).x; + elem.c2y = path.elementAt(2).y; + elem.x = path.elementAt(3).x; + elem.y = path.elementAt(3).y; + + return elem; +} + +QPainterPath CanvasCommandInterface::pathEllipse(qreal x, qreal y, qreal w, qreal h) const { + QPainterPath path; + path.addEllipse(x, y, w, h); + return path; +} + +QPainterPath CanvasCommandInterface::pathRoundedRect(qreal x, qreal y, qreal w, qreal h, qreal xRadius, qreal yRadius) const { + QPainterPath path; + path.addRoundedRect(x, y, w, h, xRadius, yRadius); + return path; +} + +QPainterPath CanvasCommandInterface::pathRect(qreal x, qreal y, qreal w, qreal h) const { + QPainterPath path; + path.addRect(x, y, w, h); + return path; +} diff --git a/libraries/script-engine/src/CanvasCommand.h b/libraries/script-engine/src/CanvasCommand.h index e603e514fd..332438bd9d 100644 --- a/libraries/script-engine/src/CanvasCommand.h +++ b/libraries/script-engine/src/CanvasCommand.h @@ -33,6 +33,15 @@ struct CanvasImage { CanvasImage(QByteArray buffer, int width, int height) : buffer(buffer), width(width), height(height) {} }; +struct CanvasPathElement { + int type; + qreal x, y, c1x, c1y, c2x, c2y; + + CanvasPathElement(int type, qreal x, qreal y) : type(type), x(x), y(y), c1x(0), c1y(0), c2x(0), c2y(0) {} + CanvasPathElement(int type, qreal x, qreal y, qreal c1x, qreal c1y, qreal c2x, qreal c2y) : type(type), x(x), y(y), c1x(c1x), c1y(c1y), c2x(c2x), c2y(c2y) {} + CanvasPathElement() : type(0), x(0), y(0), c1x(0), c1y(0), c2x(0), c2y(0) {} +}; + struct CanvasCommand { enum Variant { Invalid, @@ -147,6 +156,15 @@ struct CanvasCommand { CanvasImage _image = {}; }; +/*@jsdoc + * The CanvasCommand API provides functions for generating high-level drawing + * commands for use with a Canvas entity through Entities.canvasPushCommands. + * + * @namespace CanvasCommand + * + * @hifi-interface + * @hifi-client-entity + */ class CanvasCommandInterface : public QObject, protected Scriptable { Q_OBJECT @@ -188,25 +206,177 @@ class CanvasCommandInterface : public QObject, protected Scriptable { Q_PROPERTY(int BLEND_DIFFERENCE READ BLEND_DIFFERENCE CONSTANT) Q_PROPERTY(int BLEND_EXCLUSION READ BLEND_EXCLUSION CONSTANT) + Q_PROPERTY(int PATH_TYPE_MOVE READ PATH_TYPE_MOVE CONSTANT) + Q_PROPERTY(int PATH_TYPE_LINE READ PATH_TYPE_LINE CONSTANT) + Q_PROPERTY(int PATH_TYPE_CUBIC READ PATH_TYPE_CUBIC CONSTANT) + public slots: + /*jsdoc + * @function CanvasCommand.setStrokeWidth + * @param {number} width - Stroke/line thickness + * @returns {Object} + */ CanvasCommand setStrokeWidth(qreal width) const; + + /*jsdoc + * @function CanvasCommand.setColor + * @param {Vec3} color - Fill and stroke color + * @returns {Object} + */ CanvasCommand setColor(const glm::u8vec3& color) const; + + /*jsdoc + * @function CanvasCommand.setHints + * @param {number} hints + * @returns {Object} + */ CanvasCommand setHints(int hints) const; + + /*jsdoc + * @function CanvasCommand.setBlendMode + * @param {number} mode - Blending mode + * @returns {Object} + */ CanvasCommand setBlendMode(int mode) const; + + /*jsdoc + * @function CanvasCommand.setFont + * @param {string} family - Font family name + * @param {number} size - Point size + * @param {number} weight - 400 for regular, 600 for bold + * @param {boolean} italic + * @returns {Object} + */ CanvasCommand setFont(const QString& family, int size = 12, int weight = QFont::Normal, bool italic = false) const; + + /*jsdoc + * @function CanvasCommand.clearRect + * @param {number} x + * @param {number} y + * @param {number} w + * @param {number} h + * @returns {Object} + */ CanvasCommand clearRect(int x, int y, int w, int h) const; + + /*jsdoc + * @function CanvasCommand.fillPath + * @param {CanvasPath} path + * @returns {Object} + */ CanvasCommand fillPath(const QPainterPath& path) const; + + /*jsdoc + * @function CanvasCommand.fillRect + * @param {number} x + * @param {number} y + * @param {number} w + * @param {number} h + * @returns {Object} + */ CanvasCommand fillRect(qreal x, qreal y, qreal w, qreal h) const; + + /*jsdoc + * @function CanvasCommand.fillEllipse + * @param {number} x + * @param {number} y + * @param {number} w + * @param {number} h + * @returns {Object} + */ CanvasCommand fillEllipse(qreal x, qreal y, qreal w, qreal h) const; + + /*jsdoc + * @function CanvasCommand.fillText + * @param {string} text + * @param {number} x + * @param {number} y + * @param {number} w + * @param {number} flag + * @returns {Object} + */ CanvasCommand fillText(const QString& text, qreal x, qreal y, qreal w = 0, qreal h = 0, int flag = 0) const; + + /*jsdoc + * @function CanvasCommand.strokePath + * @param {CanvasPath} path + * @returns {Object} + */ CanvasCommand strokePath(const QPainterPath& path) const; + + /*jsdoc + * @function CanvasCommand.strokeRect + * @param {number} x + * @param {number} y + * @param {number} w + * @param {number} h + * @returns {Object} + */ CanvasCommand strokeRect(qreal x, qreal y, qreal w, qreal h) const; + + /*jsdoc + * @function CanvasCommand.stokeArc + * @param {number} x + * @param {number} y + * @param {number} w + * @param {number} h + * @param {number} startAngle + * @param {number} spanAngle + * @returns {Object} + */ CanvasCommand strokeArc(qreal x, qreal y, qreal w, qreal h, qreal startAngle, qreal spanAngle) const; + + /*jsdoc + * @function CanvasCommand.strokeEllipse + * @param {number} x + * @param {number} y + * @param {number} w + * @param {number} h + * @returns {Object} + */ CanvasCommand strokeEllipse(qreal x, qreal y, qreal w, qreal h) const; + + /*jsdoc + * @function CanvasCommand.point + * @param {number} x + * @param {number} y + * @returns {Object} + */ CanvasCommand point(qreal x, qreal y) const; + + /*jsdoc + * @function CanvasCommand.line + * @param {number} x1 + * @param {number} y1 + * @param {number} x2 + * @param {number} y2 + * @returns {Object} + */ CanvasCommand line(qreal x1, qreal y1, qreal x2, qreal y2) const; + + /*jsdoc + * @function CanvasCommand.imageCopy + * @param {CanvasImage} image + * @param {number} sx + * @param {number} sy + * @param {number} sw + * @param {number} sh + * @param {number} dx + * @param {number} dy + * @param {number} dw + * @param {number} dh + * @returns {Object} + */ CanvasCommand imageCopy(const CanvasImage& image, qreal sx, qreal sy, qreal sw, qreal sh, qreal dx, qreal dy, qreal dw, qreal dh) const; + CanvasPathElement pathMoveTo(qreal x, qreal y) const; + CanvasPathElement pathLineTo(qreal x, qreal y) const; + CanvasPathElement pathCubicTo(qreal c1x, qreal c1y, qreal c2x, qreal c2y, qreal x, qreal y) const; + CanvasPathElement pathQuadTo(qreal cx, qreal cy, qreal endX, qreal endY) const; + QPainterPath pathEllipse(qreal x, qreal y, qreal w, qreal h) const; + QPainterPath pathRoundedRect(qreal x, qreal y, qreal w, qreal h, qreal xRadius, qreal yRadius) const; + QPainterPath pathRect(qreal x, qreal y, qreal w, qreal h) const; + private: int TEXT_ALIGN_LEFT() const { return Qt::AlignLeft; } int TEXT_ALIGN_RIGHT() const { return Qt::AlignRight; } @@ -245,6 +415,10 @@ private: int BLEND_SOFTLIGHT() const { return QPainter::CompositionMode_SoftLight; } int BLEND_DIFFERENCE() const { return QPainter::CompositionMode_Difference; } int BLEND_EXCLUSION() const { return QPainter::CompositionMode_Exclusion; } + + int PATH_TYPE_MOVE() const { return QPainterPath::MoveToElement; } + int PATH_TYPE_LINE() const { return QPainterPath::LineToElement; } + int PATH_TYPE_CUBIC() const { return QPainterPath::CurveToElement; } }; void registerCanvasMetaTypes(ScriptEngine *engine); @@ -269,6 +443,11 @@ ScriptValue canvasImageToScriptValue(ScriptEngine* engine, const CanvasImage& im bool canvasImageFromScriptValue(const ScriptValue& object, CanvasImage& img); CanvasImage canvasImageFromScriptValue(const ScriptValue& object); +Q_DECLARE_METATYPE(CanvasPathElement) +ScriptValue canvasPathElementToScriptValue(ScriptEngine* engine, const CanvasPathElement& elem); +bool canvasPathElementFromScriptValue(const ScriptValue& object, CanvasPathElement& elem); +CanvasPathElement canvasPathElementFromScriptValue(const ScriptValue& object); + #endif // hifi_CanvasCommand_h /// @}