From 0fb62d6952a855880b44cfa1d34285e810f5a7cb Mon Sep 17 00:00:00 2001 From: Ada Date: Sat, 1 Mar 2025 09:33:33 +1000 Subject: [PATCH] CanvasCommands working well --- .../entities/src/CanvasEntityItem.cpp.in | 72 ++--- libraries/script-engine/src/CanvasCommand.cpp | 233 ++++++++-------- libraries/script-engine/src/CanvasCommand.h | 252 +++++++----------- .../src/v8/ScriptEngineV8_cast.cpp | 6 +- 4 files changed, 228 insertions(+), 335 deletions(-) diff --git a/libraries/entities/src/CanvasEntityItem.cpp.in b/libraries/entities/src/CanvasEntityItem.cpp.in index e09cfbbf93..f80dde2b99 100644 --- a/libraries/entities/src/CanvasEntityItem.cpp.in +++ b/libraries/entities/src/CanvasEntityItem.cpp.in @@ -14,6 +14,7 @@ #include "EntitiesLogging.h" #include "EntityItemProperties.h" #include "EntityTreeElement.h" +#include "gpu/Texture.h" EntityItemPointer CanvasEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { std::shared_ptr entity(new CanvasEntityItem(entityID), [](CanvasEntityItem* ptr) { ptr->deleteLater(); }); @@ -108,7 +109,6 @@ void CanvasEntityItem::setImageData(const CanvasImage& image) { } void CanvasEntityItem::paintCommands(const QVector& queue) { - using namespace canvas_cmd; using V = CanvasCommand::Variant; using Hint = CanvasCommand::RenderHint; @@ -121,21 +121,19 @@ void CanvasEntityItem::paintCommands(const QVector& queue) { for (int i = 0; i < queue.length(); i++) { auto cmd = queue[i]; - switch (cmd.kind()) { + switch (cmd.kind) { case V::Invalid: qCCritical(entities) << "CanvasEntityItem::paintCommands: Invalid command at index " << i; break; case V::SetStrokeWidth: { - auto props = dynamic_cast(cmd); - pen.setWidthF(props.width); + pen.setWidthF(cmd._float[0]); p.setPen(pen); break; } case V::SetColor: { - auto props = dynamic_cast(cmd); - auto color = QColor(props.color[0], props.color[1], props.color[2], 255); + auto color = QColor(cmd._color[0], cmd._color[1], cmd._color[2], 255); pen.setColor(color); brush.setColor(color); p.setPen(pen); @@ -144,107 +142,91 @@ void CanvasEntityItem::paintCommands(const QVector& queue) { } case V::SetHints: { - auto props = dynamic_cast(cmd); - p.setRenderHint(QPainter::Antialiasing, (props.hints & Hint::PrimitiveAntialiasing) != 0); - p.setRenderHint(QPainter::TextAntialiasing, (props.hints & Hint::TextAntialiasing) != 0); - p.setRenderHint(QPainter::SmoothPixmapTransform, (props.hints & Hint::BilinearImageScaling) != 0); + p.setRenderHint(QPainter::Antialiasing, (cmd._int[0] & Hint::PrimitiveAntialiasing) != 0); + p.setRenderHint(QPainter::TextAntialiasing, (cmd._int[0] & Hint::TextAntialiasing) != 0); + p.setRenderHint(QPainter::SmoothPixmapTransform, (cmd._int[0] & Hint::BilinearImageScaling) != 0); break; } case V::SetBlendMode: { - auto props = dynamic_cast(cmd); - p.setCompositionMode(props.mode); + p.setCompositionMode(static_cast(cmd._int[0])); break; } case V::SetFont: { - auto props = dynamic_cast(cmd); - p.setFont(QFont(props.family, props.size, props.weight, props.italic)); + p.setFont(QFont(cmd._text, cmd._int[0], cmd._int[1], cmd._int[2])); break; } case V::ClearRect: { - auto props = dynamic_cast(cmd); - p.eraseRect(props.rect); + p.eraseRect(QRect(cmd._int[0], cmd._int[1], cmd._int[2], cmd._int[3])); break; } case V::FillPath: { - auto props = dynamic_cast(cmd); - p.fillPath(props.path, brush); + p.fillPath(cmd._paintPath, brush); break; } case V::FillRect: { - auto props = dynamic_cast(cmd); - p.fillRect(props.rect, brush); + p.fillRect(cmd._rect, brush); break; } case V::FillEllipse: { - auto props = dynamic_cast(cmd); auto pathHack = QPainterPath(); - pathHack.addEllipse(props.rect); + pathHack.addEllipse(cmd._rect); p.fillPath(pathHack, brush); break; } case V::FillText: { - auto props = dynamic_cast(cmd); - // unbounded text - if (props.rect.width() == 0.0 && props.rect.height() == 0.0) { - p.drawText(QPointF(props.rect.x(), props.rect.y()), props.text); + if (cmd._rect.width() == 0.0 && cmd._rect.height() == 0.0) { + p.drawText(QPointF(cmd._rect.x(), cmd._rect.y()), cmd._text); } else { - p.drawText(props.rect, props.flag, props.text); + p.drawText(cmd._rect, cmd._int[0], cmd._text); } break; } case V::StrokePath: { - auto props = dynamic_cast(cmd); - p.strokePath(props.path, pen); + p.strokePath(cmd._paintPath, pen); break; } case V::StrokeRect: { - auto props = dynamic_cast(cmd); - p.drawRect(props.rect); + p.drawRect(cmd._rect); break; } case V::StrokeArc: { - auto props = dynamic_cast(cmd); - p.drawArc(props.rect, props.startAngle * 16, props.spanAngle * 16); + p.drawArc(cmd._rect, cmd._float[0] * 16, cmd._float[1] * 16); break; } case V::StrokeEllipse: { - auto props = dynamic_cast(cmd); - p.drawEllipse(props.rect); + p.drawEllipse(cmd._rect); break; } case V::Point: { - auto props = dynamic_cast(cmd); - p.drawPoint(props.point); + p.drawPoint(cmd._point); break; } case V::Line: { - auto props = dynamic_cast(cmd); - p.drawLine(props.line); + p.drawLine(cmd._line); break; } case V::ImageCopy: { - auto props = dynamic_cast(cmd); - if (props.image.buffer.length() != static_cast(4 * props.image.width * props.image.height)) { - qCCritical(entities) << "CanvasEntityItem::paintCommands: Source CanvasImage buffer has incorrect size, expected " << (4 * props.image.width * props.image.height) << ", got " << props.image.buffer.length(); + if (cmd._image.buffer.length() != static_cast(4 * cmd._image.width * cmd._image.height)) { + qCCritical(entities) << "CanvasEntityItem::paintCommands: Source CanvasImage buffer has incorrect size, expected " << (4 * cmd._image.width * cmd._image.height) << ", got " << cmd._image.buffer.length(); break; } - auto img = QImage(reinterpret_cast(props.image.buffer.constData()), props.image.width, props.image.height, QImage::Format_RGBA8888); - p.drawImage(props.dst, img, props.src); + auto img = QImage(reinterpret_cast(cmd._image.buffer.constData()), cmd._image.width, cmd._image.height, QImage::Format_RGBA8888); + p.drawImage(cmd._rect2, img, cmd._rect); break; } } @@ -259,7 +241,7 @@ void CanvasEntityItem::commit() { _commandQueue.clear(); } - auto texture = gpu::Texture::createStrict(gpu::Element::COLOR_SRGBA_32, _width, _height); + auto texture = gpu::Texture::createStrict(gpu::Element::COLOR_SRGBA_32, _width, _height, 1, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR)); texture->setStoredMipFormat(gpu::Element::COLOR_SRGBA_32); texture->setAutoGenerateMips(false); texture->assignStoredMip(0, _imageData.length(), reinterpret_cast(_imageData.constData())); diff --git a/libraries/script-engine/src/CanvasCommand.cpp b/libraries/script-engine/src/CanvasCommand.cpp index f4d19eff40..3d27cec949 100644 --- a/libraries/script-engine/src/CanvasCommand.cpp +++ b/libraries/script-engine/src/CanvasCommand.cpp @@ -38,152 +38,134 @@ const QString IMG_BUFFER_PROP_NAME = "buffer"; ScriptValue canvasCommandToScriptValue(ScriptEngine* engine, const CanvasCommand& cmd) { using Variant = CanvasCommand::Variant; - using namespace canvas_cmd; ScriptValue obj = engine->newObject(); - obj.setProperty(CMD_TYPE_PROP_NAME, cmd.kind()); + obj.setProperty(CMD_TYPE_PROP_NAME, cmd.kind); - switch (cmd.kind()) { + switch (cmd.kind) { case Variant::SetStrokeWidth: { - auto props = dynamic_cast(cmd); - obj.setProperty("width", props.width); + obj.setProperty("width", cmd._float[0]); return obj; } case Variant::SetColor: { - auto props = dynamic_cast(cmd); - obj.setProperty("color", u8vec3ColorToScriptValue(engine, props.color)); + obj.setProperty("color", u8vec3ColorToScriptValue(engine, cmd._color)); return obj; } case Variant::SetHints: { - auto props = dynamic_cast(cmd); - obj.setProperty("hints", props.hints); + obj.setProperty("hints", cmd._int[0]); return obj; } case Variant::SetBlendMode: { - auto props = dynamic_cast(cmd); - obj.setProperty("mode", props.mode); + obj.setProperty("mode", cmd._int[0]); return obj; } case Variant::SetFont: { - auto props = dynamic_cast(cmd); - obj.setProperty("family", props.family); - obj.setProperty("size", props.size); - obj.setProperty("weight", props.weight); - obj.setProperty("italic", props.italic); + obj.setProperty("family", cmd._text); + obj.setProperty("size", cmd._int[0]); + obj.setProperty("weight", cmd._int[1]); + obj.setProperty("italic", cmd._int[2]); return obj; } case Variant::ClearRect: { - auto props = dynamic_cast(cmd); - obj.setProperty("x", props.rect.x()); - obj.setProperty("y", props.rect.y()); - obj.setProperty("w", props.rect.width()); - obj.setProperty("h", props.rect.height()); + obj.setProperty("x", cmd._rect.x()); + obj.setProperty("y", cmd._rect.y()); + obj.setProperty("w", cmd._rect.width()); + obj.setProperty("h", cmd._rect.height()); return obj; } case Variant::FillPath: { - auto props = dynamic_cast(cmd); - obj.setProperty("path", qPainterPathToScriptValue(engine, props.path)); + obj.setProperty("path", qPainterPathToScriptValue(engine, cmd._paintPath)); return obj; } case Variant::FillRect: { - auto props = dynamic_cast(cmd); - obj.setProperty("x", props.rect.x()); - obj.setProperty("y", props.rect.y()); - obj.setProperty("w", props.rect.width()); - obj.setProperty("h", props.rect.height()); + obj.setProperty("x", cmd._rect.x()); + obj.setProperty("y", cmd._rect.y()); + obj.setProperty("w", cmd._rect.width()); + obj.setProperty("h", cmd._rect.height()); return obj; } case Variant::FillEllipse: { - auto props = dynamic_cast(cmd); - obj.setProperty("x", props.rect.x()); - obj.setProperty("y", props.rect.y()); - obj.setProperty("w", props.rect.width()); - obj.setProperty("h", props.rect.height()); + obj.setProperty("x", cmd._rect.x()); + obj.setProperty("y", cmd._rect.y()); + obj.setProperty("w", cmd._rect.width()); + obj.setProperty("h", cmd._rect.height()); return obj; } case Variant::FillText: { - auto props = dynamic_cast(cmd); - obj.setProperty("x", props.rect.x()); - obj.setProperty("y", props.rect.y()); - obj.setProperty("w", props.rect.width()); - obj.setProperty("h", props.rect.height()); - obj.setProperty("text", props.text); - obj.setProperty("flag", static_cast(props.flag)); + obj.setProperty("x", cmd._rect.x()); + obj.setProperty("y", cmd._rect.y()); + obj.setProperty("w", cmd._rect.width()); + obj.setProperty("h", cmd._rect.height()); + obj.setProperty("text", cmd._text); + obj.setProperty("flag", cmd._int[0]); return obj; } case Variant::StrokePath: { - auto props = dynamic_cast(cmd); - obj.setProperty("path", qPainterPathToScriptValue(engine, props.path)); + obj.setProperty("path", qPainterPathToScriptValue(engine, cmd._paintPath)); return obj; } case Variant::StrokeRect: { - auto props = dynamic_cast(cmd); - obj.setProperty("x", props.rect.x()); - obj.setProperty("y", props.rect.y()); - obj.setProperty("w", props.rect.width()); - obj.setProperty("h", props.rect.height()); + obj.setProperty("x", cmd._rect.x()); + obj.setProperty("y", cmd._rect.y()); + obj.setProperty("w", cmd._rect.width()); + obj.setProperty("h", cmd._rect.height()); return obj; } case Variant::StrokeArc: { - auto props = dynamic_cast(cmd); - obj.setProperty("x", props.rect.x()); - obj.setProperty("y", props.rect.y()); - obj.setProperty("w", props.rect.width()); - obj.setProperty("h", props.rect.height()); - obj.setProperty("startAngle", props.startAngle); - obj.setProperty("spanAngle", props.spanAngle); + obj.setProperty("x", cmd._rect.x()); + obj.setProperty("y", cmd._rect.y()); + obj.setProperty("w", cmd._rect.width()); + obj.setProperty("h", cmd._rect.height()); + obj.setProperty("startAngle", cmd._float[0]); + obj.setProperty("spanAngle", cmd._float[1]); return obj; } case Variant::StrokeEllipse: { - auto props = dynamic_cast(cmd); - obj.setProperty("x", props.rect.x()); - obj.setProperty("y", props.rect.y()); - obj.setProperty("w", props.rect.width()); - obj.setProperty("h", props.rect.height()); + obj.setProperty("x", cmd._rect.x()); + obj.setProperty("y", cmd._rect.y()); + obj.setProperty("w", cmd._rect.width()); + obj.setProperty("h", cmd._rect.height()); return obj; } case Variant::Point: { - auto props = dynamic_cast(cmd); - obj.setProperty("x", props.point.x()); - obj.setProperty("y", props.point.y()); + obj.setProperty("x", cmd._point.x()); + obj.setProperty("y", cmd._point.y()); return obj; } case Variant::Line: { - auto props = dynamic_cast(cmd); - obj.setProperty("x1", props.line.x1()); - obj.setProperty("y1", props.line.y1()); - obj.setProperty("x2", props.line.x2()); - obj.setProperty("y2", props.line.y2()); + obj.setProperty("x1", cmd._line.x1()); + obj.setProperty("y1", cmd._line.y1()); + obj.setProperty("x2", cmd._line.x2()); + obj.setProperty("y2", cmd._line.y2()); return obj; } case Variant::ImageCopy: { - auto props = dynamic_cast(cmd); - obj.setProperty("srcX", props.src.x()); - obj.setProperty("srcY", props.src.y()); - obj.setProperty("srcW", props.src.width()); - obj.setProperty("srcH", props.src.height()); - obj.setProperty("destX", props.dst.x()); - obj.setProperty("destY", props.dst.y()); - obj.setProperty("destW", props.dst.width()); - obj.setProperty("destH", props.dst.height()); - obj.setProperty("image", canvasImageToScriptValue(engine, props.image)); + obj.setProperty("srcX", cmd._rect.x()); + obj.setProperty("srcY", cmd._rect.y()); + obj.setProperty("srcW", cmd._rect.width()); + obj.setProperty("srcH", cmd._rect.height()); + obj.setProperty("destX", cmd._rect2.x()); + obj.setProperty("destY", cmd._rect2.y()); + obj.setProperty("destW", cmd._rect2.width()); + obj.setProperty("destH", cmd._rect2.height()); + obj.setProperty("image", canvasImageToScriptValue(engine, cmd._image)); return obj; } @@ -195,74 +177,73 @@ ScriptValue canvasCommandToScriptValue(ScriptEngine* engine, const CanvasCommand bool canvasCommandFromScriptValue(const ScriptValue& object, CanvasCommand& cmd) { using Variant = CanvasCommand::Variant; - using namespace canvas_cmd; uint type = object.property(CMD_TYPE_PROP_NAME).toInt32(); if (type == Variant::SetStrokeWidth) { - cmd = SetStrokeWidth { object.property("width").toNumber() }; + cmd = CanvasCommand::setStrokeWidth(object.property("width").toNumber()); } else if (type == Variant::SetColor) { glm::u8vec3 c; if (!u8vec3FromScriptValue(object.property("color"), c)) { return false; } // FIXME: we have a script RGB color type but not an RGBA one - cmd = SetColor(c); + cmd = CanvasCommand::setColor(c); } else if (type == Variant::SetHints) { - cmd = SetHints(object.property("hints").toUInt32()); + cmd = CanvasCommand::setHints(object.property("hints").toInt32()); } else if (type == Variant::SetBlendMode) { - cmd = SetBlendMode(object.property("mode").toUInt32()); + cmd = CanvasCommand::setBlendMode(object.property("mode").toInt32()); } else if (type == Variant::SetFont) { - cmd = SetFont( + cmd = CanvasCommand::setFont( object.property("family").toString(), object.property("size").toInt32(), object.property("weight").toInt32(), object.property("italic").toBool() ); } else if (type == Variant::ClearRect) { - cmd = ClearRect(QRect( + cmd = CanvasCommand::clearRect( object.property("x").toInt32(), object.property("y").toInt32(), object.property("w").toInt32(), object.property("h").toInt32() - )); + ); } else if (type == Variant::FillPath) { - cmd = FillPath(qPainterPathFromScriptValue(object.property("path"))); + cmd = CanvasCommand::fillPath(qPainterPathFromScriptValue(object.property("path"))); } else if (type == Variant::FillRect) { - cmd = FillRect(QRectF( + cmd = CanvasCommand::fillRect(QRectF( object.property("x").toNumber(), object.property("y").toNumber(), object.property("w").toNumber(), object.property("h").toNumber() )); } else if (type == Variant::FillEllipse) { - cmd = FillEllipse(QRectF( + cmd = CanvasCommand::fillEllipse(QRectF( object.property("x").toNumber(), object.property("y").toNumber(), object.property("w").toNumber(), object.property("h").toNumber() )); } else if (type == Variant::FillText) { - cmd = FillText( + cmd = CanvasCommand::fillText( + object.property("text").toString(), QRectF( object.property("x").toNumber(), object.property("y").toNumber(), object.property("w").toNumber(), object.property("h").toNumber() ), - object.property("text").toString(), object.property("flag").toInt32() ); } else if (type == Variant::StrokePath) { - cmd = StrokePath(qPainterPathFromScriptValue(object.property("path"))); + cmd = CanvasCommand::strokePath(qPainterPathFromScriptValue(object.property("path"))); } else if (type == Variant::StrokeRect) { - cmd = StrokeRect(QRectF( + cmd = CanvasCommand::strokeRect(QRectF( object.property("x").toNumber(), object.property("y").toNumber(), object.property("w").toNumber(), object.property("h").toNumber() )); } else if (type == Variant::StrokeArc) { - cmd = StrokeArc( + cmd = CanvasCommand::strokeArc( QRectF( object.property("x").toNumber(), object.property("y").toNumber(), @@ -273,26 +254,26 @@ bool canvasCommandFromScriptValue(const ScriptValue& object, CanvasCommand& cmd) object.property("spanAngle").toNumber() ); } else if (type == Variant::StrokeEllipse) { - cmd = StrokeEllipse(QRectF( + cmd = CanvasCommand::strokeEllipse(QRectF( object.property("x").toNumber(), object.property("y").toNumber(), object.property("w").toNumber(), object.property("h").toNumber() )); } else if (type == Variant::Point) { - cmd = Point( + cmd = CanvasCommand::point( object.property("x").toNumber(), object.property("y").toNumber() ); } else if (type == Variant::Line) { - cmd = Line( + cmd = CanvasCommand::line( object.property("x1").toNumber(), object.property("y1").toNumber(), object.property("x2").toNumber(), object.property("y2").toNumber() ); } else if (type == Variant::ImageCopy) { - cmd = ImageCopy( + cmd = CanvasCommand::imageCopy( canvasImageFromScriptValue(object.property("image")), QRectF( object.property("srcX").toNumber(), @@ -308,7 +289,7 @@ bool canvasCommandFromScriptValue(const ScriptValue& object, CanvasCommand& cmd) ) ); } else { - cmd = Invalid(); + cmd = CanvasCommand {}; } return true; @@ -355,8 +336,8 @@ ScriptValue canvasImageToScriptValue(ScriptEngine* engine, const CanvasImage& im } bool canvasImageFromScriptValue(const ScriptValue& object, CanvasImage& img) { - img.width = object.property(IMG_WIDTH_PROP_NAME).toUInt32(); - img.height = object.property(IMG_HEIGHT_PROP_NAME).toUInt32(); + img.width = object.property(IMG_WIDTH_PROP_NAME).toInt32(); + img.height = object.property(IMG_HEIGHT_PROP_NAME).toInt32(); return qBytearrayFromScriptValue(object.property(IMG_BUFFER_PROP_NAME), img.buffer); } @@ -427,72 +408,70 @@ QPainterPath qPainterPathFromScriptValue(const ScriptValue& object) { return p; } -using namespace canvas_cmd; - CanvasCommand CanvasCommandInterface::setStrokeWidth(qreal width) const { - return SetStrokeWidth(width); + return CanvasCommand::setStrokeWidth(width); } CanvasCommand CanvasCommandInterface::setColor(const glm::u8vec3& color) const { - return SetColor(color); + return CanvasCommand::setColor(color); } CanvasCommand CanvasCommandInterface::setHints(int hints) const { - return SetHints(hints); + return CanvasCommand::setHints(hints); } CanvasCommand CanvasCommandInterface::setBlendMode(int mode) const { - return SetBlendMode(mode); + return CanvasCommand::setBlendMode(mode); } CanvasCommand CanvasCommandInterface::setFont(const QString& family, int size, int weight, bool italic) const { - return SetFont(family, size, weight, italic); + return CanvasCommand::setFont(family, size, weight, italic); } -CanvasCommand CanvasCommandInterface::clearRect(const QRect& rect) const { - return ClearRect(rect); +CanvasCommand CanvasCommandInterface::clearRect(int x, int y, int w, int h) const { + return CanvasCommand::clearRect(x, y, w, h); } CanvasCommand CanvasCommandInterface::fillPath(const QPainterPath& path) const { - return FillPath(path); + return CanvasCommand::fillPath(path); } -CanvasCommand CanvasCommandInterface::fillRect(const QRectF& rect) const { - return FillRect(rect); +CanvasCommand CanvasCommandInterface::fillRect(qreal x, qreal y, qreal w, qreal h) const { + return CanvasCommand::fillRect(QRectF(x, y, w, h)); } -CanvasCommand CanvasCommandInterface::fillEllipse(const QRectF& rect) const { - return FillEllipse(rect); +CanvasCommand CanvasCommandInterface::fillEllipse(qreal x, qreal y, qreal w, qreal h) const { + return CanvasCommand::fillEllipse(QRectF(x, y, w, h)); } -CanvasCommand CanvasCommandInterface::fillText(const QString& text, const QRectF& rect, int flag) const { - return FillText(rect, text, flag); +CanvasCommand CanvasCommandInterface::fillText(const QString& text, qreal x, qreal y, qreal w, qreal h, int flag) const { + return CanvasCommand::fillText(text, QRectF(x, y, w, h), flag); } CanvasCommand CanvasCommandInterface::strokePath(const QPainterPath& path) const { - return StrokePath(path); + return CanvasCommand::strokePath(path); } -CanvasCommand CanvasCommandInterface::strokeRect(const QRectF& rect) const { - return StrokeRect(rect); +CanvasCommand CanvasCommandInterface::strokeRect(qreal x, qreal y, qreal w, qreal h) const { + return CanvasCommand::strokeRect(QRectF(x, y, w, h)); } -CanvasCommand CanvasCommandInterface::strokeArc(const QRectF& rect, qreal startAngle, qreal spanAngle) const { - return StrokeArc(rect, startAngle, spanAngle); +CanvasCommand CanvasCommandInterface::strokeArc(qreal x, qreal y, qreal w, qreal h, qreal startAngle, qreal spanAngle) const { + return CanvasCommand::strokeArc(QRectF(x, y, w, h), startAngle, spanAngle); } -CanvasCommand CanvasCommandInterface::strokeEllipse(const QRectF& rect) const { - return StrokeEllipse(rect); +CanvasCommand CanvasCommandInterface::strokeEllipse(qreal x, qreal y, qreal w, qreal h) const { + return CanvasCommand::strokeEllipse(QRectF(x, y, w, h)); } CanvasCommand CanvasCommandInterface::point(qreal x, qreal y) const { - return Point(x, y); + return CanvasCommand::point(x, y); } CanvasCommand CanvasCommandInterface::line(qreal x1, qreal y1, qreal x2, qreal y2) const { - return Line(x1, y1, x2, y2); + return CanvasCommand::line(x1, y1, x2, y2); } -CanvasCommand CanvasCommandInterface::imageCopy(const CanvasImage& image, const QRectF& src, const QRectF& dest) const { - return ImageCopy(image, src, dest); +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)); } diff --git a/libraries/script-engine/src/CanvasCommand.h b/libraries/script-engine/src/CanvasCommand.h index 8ffd321ae2..e603e514fd 100644 --- a/libraries/script-engine/src/CanvasCommand.h +++ b/libraries/script-engine/src/CanvasCommand.h @@ -20,7 +20,6 @@ #include "ScriptValueUtils.h" #include "Scriptable.h" -#include #include #include @@ -62,159 +61,92 @@ struct CanvasCommand { BilinearImageScaling = (1 << 2), }; - virtual Variant kind() const { return Variant::Invalid; } + static CanvasCommand none() { + return CanvasCommand {}; + } + + static CanvasCommand setStrokeWidth(qreal width) { + return CanvasCommand { .kind = Variant::SetStrokeWidth, ._float = {width} }; + } + + static CanvasCommand setColor(const glm::u8vec3& color) { + return CanvasCommand { .kind = Variant::SetColor, ._color = color }; + } + + static CanvasCommand setHints(int hints) { + return CanvasCommand { .kind = Variant::SetHints, ._int = {hints} }; + } + + static CanvasCommand setBlendMode(int mode) { + return CanvasCommand { .kind = Variant::SetBlendMode, ._int = {mode} }; + } + + static CanvasCommand setFont(const QString& family, int size, int weight, bool italic) { + return CanvasCommand { .kind = Variant::SetFont, ._text = family, ._int = {size, weight, italic} }; + } + + static CanvasCommand clearRect(int x, int y, int w, int h) { + return CanvasCommand { .kind = Variant::ClearRect, ._int = {x, y, w, h} }; + } + + static CanvasCommand fillPath(const QPainterPath& path) { + return CanvasCommand { .kind = Variant::FillPath, ._paintPath = path }; + } + + static CanvasCommand fillRect(const QRectF& rect) { + return CanvasCommand { .kind = Variant::FillRect, ._rect = rect }; + } + + static CanvasCommand fillEllipse(const QRectF& rect) { + return CanvasCommand { .kind = Variant::FillEllipse, ._rect = rect }; + } + + static CanvasCommand fillText(const QString& text, const QRectF& rect, int flag) { + return CanvasCommand { .kind = Variant::FillText, ._rect = rect, ._text = text, ._int = {flag} }; + } + + static CanvasCommand strokePath(const QPainterPath& path) { + return CanvasCommand { .kind = Variant::StrokePath, ._paintPath = path }; + } + + static CanvasCommand strokeRect(const QRectF& rect) { + return CanvasCommand { .kind = Variant::StrokeRect, ._rect = rect }; + } + + static CanvasCommand strokeArc(const QRectF& rect, qreal startAngle, qreal spanAngle) { + return CanvasCommand { .kind = Variant::StrokeArc, ._rect = rect, ._float = {startAngle, spanAngle} }; + } + + static CanvasCommand strokeEllipse(const QRectF& rect) { + return CanvasCommand { .kind = Variant::StrokeEllipse, ._rect = rect }; + } + + static CanvasCommand point(qreal x, qreal y) { + return CanvasCommand { .kind = Variant::Point, ._point = QPointF(x, y) }; + } + + static CanvasCommand line(qreal x1, qreal y1, qreal x2, qreal y2) { + return CanvasCommand { .kind = Variant::Line, ._line = QLineF(x1, y1, x2, y2) }; + } + + static CanvasCommand imageCopy(const CanvasImage& image, const QRectF& src, const QRectF& dst) { + return CanvasCommand { .kind = Variant::ImageCopy, ._rect = src, ._rect2 = dst, ._image = image }; + } + + Variant kind = Variant::Invalid; + + QRectF _rect = QRectF(); + QRectF _rect2 = QRectF(); + QString _text = QString(); + QPointF _point = QPointF(); + QLineF _line = QLineF(); + qreal _float[4] = {}; + int _int[4] = {}; + glm::u8vec3 _color = {}; + QPainterPath _paintPath = QPainterPath(); + CanvasImage _image = {}; }; -namespace canvas_cmd { -struct Invalid : public CanvasCommand { - virtual Variant kind() const override { return Variant::Invalid; } -}; - -struct SetStrokeWidth : public CanvasCommand { - virtual Variant kind() const override { return Variant::SetStrokeWidth; } - - SetStrokeWidth(qreal width) : width(width) {} - - qreal width; -}; - -struct SetColor : public CanvasCommand { - virtual Variant kind() const override { return Variant::SetColor; } - - SetColor(const glm::u8vec3& color) : color(color) {} - - glm::u8vec3 color; -}; - -struct SetHints : public CanvasCommand { - virtual Variant kind() const override { return Variant::SetHints; } - - SetHints(int hints) : hints(static_cast(hints)) {} - - CanvasCommand::RenderHint hints; -}; - -struct SetBlendMode : public CanvasCommand { - virtual Variant kind() const override { return Variant::SetBlendMode; } - - SetBlendMode(int mode) : mode(static_cast(mode)) {} - - QPainter::CompositionMode mode; -}; - -struct SetFont : public CanvasCommand { - virtual Variant kind() const override { return Variant::SetFont; } - - SetFont(const QString& family, int size = 12, int weight = 400, bool italic = false) : family(family), size(size), weight(weight), italic(italic) {} - - QString family; - int size; - int weight; - bool italic; -}; - -struct ClearRect : public CanvasCommand { - virtual Variant kind() const override { return Variant::ClearRect; } - - ClearRect(const QRect& rect) : rect(rect) {} - - QRect rect; -}; - -struct FillPath : public CanvasCommand { - virtual Variant kind() const override { return Variant::FillPath; } - - FillPath(const QPainterPath& path) : path(path) {} - - QPainterPath path; -}; - -struct FillRect : public CanvasCommand { - virtual Variant kind() const override { return Variant::FillRect; } - - FillRect(const QRectF& rect) : rect(rect) {} - - QRectF rect; -}; - -struct FillEllipse : public CanvasCommand { - virtual Variant kind() const override { return Variant::FillEllipse; } - - FillEllipse(const QRectF& rect) : rect(rect) {} - - QRectF rect; -}; - -struct FillText : public CanvasCommand { - virtual Variant kind() const override { return Variant::FillText; } - - FillText(const QRectF& rect, const QString& text, int flag = 0) : rect(rect), text(text), flag(static_cast(flag)) {} - - QRectF rect; - QString text; - Qt::AlignmentFlag flag; -}; - -struct StrokePath : public CanvasCommand { - virtual Variant kind() const override { return Variant::StrokePath; } - - StrokePath(const QPainterPath& path) : path(path) {} - - QPainterPath path; -}; - -struct StrokeRect : public CanvasCommand { - virtual Variant kind() const override { return Variant::StrokeRect; } - - StrokeRect(const QRectF& rect) : rect(rect) {} - - QRectF rect; -}; - -struct StrokeArc : public CanvasCommand { - virtual Variant kind() const override { return Variant::StrokeArc; } - - StrokeArc(const QRectF& rect, qreal startAngle, qreal spanAngle) : rect(rect), startAngle(startAngle), spanAngle(spanAngle) {} - - QRectF rect; - qreal startAngle, spanAngle; -}; - -struct StrokeEllipse : public CanvasCommand { - virtual Variant kind() const override { return Variant::StrokeEllipse; } - - StrokeEllipse(const QRectF& rect) : rect(rect) {} - - QRectF rect; -}; - -struct Point : public CanvasCommand { - virtual Variant kind() const override { return Variant::Point; } - - Point(qreal x, qreal y) : point(QPointF(x, y)) {} - - QPointF point; -}; - -struct Line : public CanvasCommand { - virtual Variant kind() const override { return Variant::Line; } - - Line(qreal x1, qreal y1, qreal x2, qreal y2) : line(QLineF(x1, y1, x2, y2)) {} - - QLineF line; -}; - -struct ImageCopy : public CanvasCommand { - virtual Variant kind() const override { return Variant::ImageCopy; } - - ImageCopy(const CanvasImage& image, const QRectF& src, const QRectF& dst) : src(src), dst(dst), image(image) {} - - QRectF src; - QRectF dst; - CanvasImage image; -}; -} - class CanvasCommandInterface : public QObject, protected Scriptable { Q_OBJECT @@ -262,18 +194,18 @@ public slots: CanvasCommand setHints(int hints) const; CanvasCommand setBlendMode(int mode) const; CanvasCommand setFont(const QString& family, int size = 12, int weight = QFont::Normal, bool italic = false) const; - CanvasCommand clearRect(const QRect& rect) const; + CanvasCommand clearRect(int x, int y, int w, int h) const; CanvasCommand fillPath(const QPainterPath& path) const; - CanvasCommand fillRect(const QRectF& rect) const; - CanvasCommand fillEllipse(const QRectF& rect) const; - CanvasCommand fillText(const QString& text, const QRectF& rect, int flag = 0) const; + CanvasCommand fillRect(qreal x, qreal y, qreal w, qreal h) const; + CanvasCommand fillEllipse(qreal x, qreal y, qreal w, qreal h) const; + CanvasCommand fillText(const QString& text, qreal x, qreal y, qreal w = 0, qreal h = 0, int flag = 0) const; CanvasCommand strokePath(const QPainterPath& path) const; - CanvasCommand strokeRect(const QRectF& rect) const; - CanvasCommand strokeArc(const QRectF& rect, qreal startAngle, qreal spanAngle) const; - CanvasCommand strokeEllipse(const QRectF& rect) const; + CanvasCommand strokeRect(qreal x, qreal y, qreal w, qreal h) const; + CanvasCommand strokeArc(qreal x, qreal y, qreal w, qreal h, qreal startAngle, qreal spanAngle) const; + CanvasCommand strokeEllipse(qreal x, qreal y, qreal w, qreal h) const; CanvasCommand point(qreal x, qreal y) const; CanvasCommand line(qreal x1, qreal y1, qreal x2, qreal y2) const; - CanvasCommand imageCopy(const CanvasImage& image, const QRectF& src, const QRectF& dest) const; + CanvasCommand imageCopy(const CanvasImage& image, qreal sx, qreal sy, qreal sw, qreal sh, qreal dx, qreal dy, qreal dw, qreal dh) const; private: int TEXT_ALIGN_LEFT() const { return Qt::AlignLeft; } diff --git a/libraries/script-engine/src/v8/ScriptEngineV8_cast.cpp b/libraries/script-engine/src/v8/ScriptEngineV8_cast.cpp index 211da7582f..f8262e8d2d 100644 --- a/libraries/script-engine/src/v8/ScriptEngineV8_cast.cpp +++ b/libraries/script-engine/src/v8/ScriptEngineV8_cast.cpp @@ -525,9 +525,9 @@ bool ScriptEngineV8::castValueToVariant(const V8ScriptValue& v8Val, QVariant& de } // check if it's a pointer to QVariant { - QVariant var = *ScriptVariantV8Proxy::unwrapQVariantPointer(_v8Isolate, v8Val.constGet()); - if (var.isValid()) { - dest = var; + QVariant *varPtr = ScriptVariantV8Proxy::unwrapQVariantPointer(_v8Isolate, v8Val.constGet()); + if (varPtr && varPtr->isValid()) { + dest = *varPtr; break; } }