CanvasCommands working well

This commit is contained in:
Ada 2025-03-01 09:33:33 +10:00
parent 6ae0aca81e
commit 0fb62d6952
4 changed files with 228 additions and 335 deletions

View file

@ -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<CanvasEntityItem> entity(new CanvasEntityItem(entityID), [](CanvasEntityItem* ptr) { ptr->deleteLater(); });
@ -108,7 +109,6 @@ void CanvasEntityItem::setImageData(const CanvasImage& image) {
}
void CanvasEntityItem::paintCommands(const QVector<CanvasCommand>& queue) {
using namespace canvas_cmd;
using V = CanvasCommand::Variant;
using Hint = CanvasCommand::RenderHint;
@ -121,21 +121,19 @@ void CanvasEntityItem::paintCommands(const QVector<CanvasCommand>& 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<const SetStrokeWidth&>(cmd);
pen.setWidthF(props.width);
pen.setWidthF(cmd._float[0]);
p.setPen(pen);
break;
}
case V::SetColor: {
auto props = dynamic_cast<const SetColor&>(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<CanvasCommand>& queue) {
}
case V::SetHints: {
auto props = dynamic_cast<const SetHints&>(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<const SetBlendMode&>(cmd);
p.setCompositionMode(props.mode);
p.setCompositionMode(static_cast<QPainter::CompositionMode>(cmd._int[0]));
break;
}
case V::SetFont: {
auto props = dynamic_cast<const SetFont&>(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<const ClearRect&>(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<const FillPath&>(cmd);
p.fillPath(props.path, brush);
p.fillPath(cmd._paintPath, brush);
break;
}
case V::FillRect: {
auto props = dynamic_cast<const FillRect&>(cmd);
p.fillRect(props.rect, brush);
p.fillRect(cmd._rect, brush);
break;
}
case V::FillEllipse: {
auto props = dynamic_cast<const FillEllipse&>(cmd);
auto pathHack = QPainterPath();
pathHack.addEllipse(props.rect);
pathHack.addEllipse(cmd._rect);
p.fillPath(pathHack, brush);
break;
}
case V::FillText: {
auto props = dynamic_cast<const FillText&>(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<const StrokePath&>(cmd);
p.strokePath(props.path, pen);
p.strokePath(cmd._paintPath, pen);
break;
}
case V::StrokeRect: {
auto props = dynamic_cast<const StrokeRect&>(cmd);
p.drawRect(props.rect);
p.drawRect(cmd._rect);
break;
}
case V::StrokeArc: {
auto props = dynamic_cast<const StrokeArc&>(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<const StrokeEllipse&>(cmd);
p.drawEllipse(props.rect);
p.drawEllipse(cmd._rect);
break;
}
case V::Point: {
auto props = dynamic_cast<const Point&>(cmd);
p.drawPoint(props.point);
p.drawPoint(cmd._point);
break;
}
case V::Line: {
auto props = dynamic_cast<const Line&>(cmd);
p.drawLine(props.line);
p.drawLine(cmd._line);
break;
}
case V::ImageCopy: {
auto props = dynamic_cast<const ImageCopy&>(cmd);
if (props.image.buffer.length() != static_cast<int>(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<int>(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<const uint8_t*>(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<const uint8_t*>(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<const uint8_t*>(_imageData.constData()));

View file

@ -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<const SetStrokeWidth&>(cmd);
obj.setProperty("width", props.width);
obj.setProperty("width", cmd._float[0]);
return obj;
}
case Variant::SetColor: {
auto props = dynamic_cast<const SetColor&>(cmd);
obj.setProperty("color", u8vec3ColorToScriptValue(engine, props.color));
obj.setProperty("color", u8vec3ColorToScriptValue(engine, cmd._color));
return obj;
}
case Variant::SetHints: {
auto props = dynamic_cast<const SetHints&>(cmd);
obj.setProperty("hints", props.hints);
obj.setProperty("hints", cmd._int[0]);
return obj;
}
case Variant::SetBlendMode: {
auto props = dynamic_cast<const SetBlendMode&>(cmd);
obj.setProperty("mode", props.mode);
obj.setProperty("mode", cmd._int[0]);
return obj;
}
case Variant::SetFont: {
auto props = dynamic_cast<const SetFont&>(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<const ClearRect&>(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<const FillPath&>(cmd);
obj.setProperty("path", qPainterPathToScriptValue(engine, props.path));
obj.setProperty("path", qPainterPathToScriptValue(engine, cmd._paintPath));
return obj;
}
case Variant::FillRect: {
auto props = dynamic_cast<const FillRect&>(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<const FillEllipse&>(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<const FillText&>(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<uint>(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<const StrokePath&>(cmd);
obj.setProperty("path", qPainterPathToScriptValue(engine, props.path));
obj.setProperty("path", qPainterPathToScriptValue(engine, cmd._paintPath));
return obj;
}
case Variant::StrokeRect: {
auto props = dynamic_cast<const StrokeRect&>(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<const StrokeArc&>(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<const StrokeEllipse&>(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<const Point&>(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<const Line&>(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<const ImageCopy&>(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));
}

View file

@ -20,7 +20,6 @@
#include "ScriptValueUtils.h"
#include "Scriptable.h"
#include <QColor>
#include <QPainter>
#include <QPainterPath>
@ -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<CanvasCommand::RenderHint>(hints)) {}
CanvasCommand::RenderHint hints;
};
struct SetBlendMode : public CanvasCommand {
virtual Variant kind() const override { return Variant::SetBlendMode; }
SetBlendMode(int mode) : mode(static_cast<QPainter::CompositionMode>(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<Qt::AlignmentFlag>(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; }

View file

@ -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;
}
}