62
62
WbItem::WbItem(SxeSession* session, QSvgRenderer* renderer, QDomElement node, WbScene* scene, WbWidget* widget) : QGraphicsSvgItem() {
63
// Store a pointer to the underlying session, scene and node
69
// qDebug() << QString("constructing %1.").arg(id()).toAscii();
72
qDebug("Trying to create a WbItem from a null QDomNode.");
77
// Make the item selectable and movable
78
setFlag(QGraphicsItem::ItemIsSelectable);
79
setFlag(QGraphicsItem::ItemIsMovable);
84
// Don't cache the SVG
85
setCachingEnabled(false);
87
// Set the renderer for the item
88
setSharedRenderer(renderer);
90
// add the new item to the scene
63
// Store a pointer to the underlying session, scene and node
69
// qDebug() << QString("constructing %1.").arg(id()).toAscii();
72
qDebug("Trying to create a WbItem from a null QDomNode.");
77
// Make the item selectable and movable
78
setFlag(QGraphicsItem::ItemIsSelectable);
79
setFlag(QGraphicsItem::ItemIsMovable);
84
// Don't cache the SVG
85
setCachingEnabled(false);
87
// Set the renderer for the item
88
setSharedRenderer(renderer);
90
// add the new item to the scene
94
94
WbItem::~WbItem() {
95
// qDebug() << QString("destructing %1.").arg(id()).toAscii();
95
// qDebug() << QString("destructing %1.").arg(id()).toAscii();
98
98
QString WbItem::id() {
99
return node_.toElement().attribute("id");
99
return node_.toElement().attribute("id");
102
102
QDomNode WbItem::node() {
106
106
void WbItem::contextMenuEvent (QGraphicsSceneContextMenuEvent * event) {
107
constructContextMenu()->exec(event->screenPos());
107
constructContextMenu()->exec(event->screenPos());
110
110
void WbItem::mouseMoveEvent(QGraphicsSceneMouseEvent * event) {
114
if(widget_->mode() == WbWidget::Translate) {
116
// Translate each selected item
117
foreach(QGraphicsItem* graphicsitem, scene()->selectedItems()) {
118
if (!graphicsitem->parentItem() || !graphicsitem->parentItem()->isSelected()) {
119
QPointF d = graphicsitem->mapFromScene(event->scenePos()) - graphicsitem->mapFromScene(event->lastScenePos());
120
graphicsitem->translate(d.x(), d.y());
121
// qDebug() QString("Translated %1 by %2 %3").arg((unsigned int) graphicsitem).arg(d.x()).arg(d.y()).toAscii();
123
// Regenerate the SVG transformation matrix later
124
WbItem* wbitem = dynamic_cast<WbItem*>(graphicsitem);
126
scene_->queueTransformationRegeneration(wbitem);
130
} else if(widget_->mode() == WbWidget::Rotate) {
132
// Rotate each selected item
133
// get center coordinates of selected items in scene coordinates
134
QPointF scenePivot = scene_->selectionCenter();
135
// Determine the direction relative to the center
136
// Divide the sum by two to reduce the "speed" of rotation
137
QPointF difference = event->scenePos() - event->lastScenePos();
138
// qDebug() << QString("d: %1 %2 = %3 %4 + %5 %6").arg(difference.x()).arg(difference.y()).arg(event->scenePos().x()).arg(event->scenePos().y()).arg(event->lastScenePos().x()).arg(event->lastScenePos().y());
139
QPointF p = event->scenePos();
141
if(p.x() >= scenePivot.x() && p.y() >= scenePivot.y()) {
142
delta.rotate((-difference.x() + difference.y()) / 2);
143
} else if(p.x() < scenePivot.x() && p.y() >= scenePivot.y()) {
144
delta.rotate((-difference.x() - difference.y()) / 2);
145
} else if(p.x() < scenePivot.x() && p.y() < scenePivot.y()) {
146
delta.rotate((difference.x() - difference.y()) / 2);
147
} else if(p.x() >= scenePivot.x() && p.y() < scenePivot.y()) {
148
delta.rotate((difference.x() + difference.y()) / 2);
151
foreach(QGraphicsItem* graphicsitem, scene()->selectedItems()) {
152
if (!graphicsitem->parentItem() || !graphicsitem->parentItem()->isSelected()) {
154
// get center coordinates of selected items in item coordinates
155
QPointF itemPivot = graphicsitem->mapFromScene(scenePivot);
156
// translates the the item's center to the origin of the item coordinates
157
translation.translate(-itemPivot.x(), -itemPivot.y());
159
graphicsitem->setTransform(QTransform(translation * delta * translation.inverted()), true);
161
// Regenerate the SVG transformation matrix later
162
WbItem* wbitem = dynamic_cast<WbItem*>(graphicsitem);
164
scene_->queueTransformationRegeneration(wbitem);
168
} else if(widget_->mode() == WbWidget::Scale) {
170
// Scale each selected item
171
foreach(QGraphicsItem* graphicsitem, scene()->selectedItems()) {
172
if (!graphicsitem->parentItem() || !graphicsitem->parentItem()->isSelected()) {
174
// get center coordinates in item coordinates
175
QPointF c = center();
176
QMatrix translation, delta;
177
// translates the the item's center to the origin of the item coordinates
178
translation.translate(-c.x(), -c.y());
180
// Moving mouse up enlarges, down shrinks, y axis.
181
// Moving mouse right enlarges, left shrinks, x axis.
182
QPointF difference = event->scenePos() - event->lastScenePos();
183
// Note: the y axis points downwards in scene coordinates
184
delta.scale(1 + difference.x()/50, 1 - difference.y()/50);
186
setTransform(QTransform(translation * delta * translation.inverted()), true);
114
if(widget_->mode() == WbWidget::Translate) {
116
// Translate each selected item
117
foreach(QGraphicsItem* graphicsitem, scene()->selectedItems()) {
118
if (!graphicsitem->parentItem() || !graphicsitem->parentItem()->isSelected()) {
119
QPointF d = graphicsitem->mapFromScene(event->scenePos()) - graphicsitem->mapFromScene(event->lastScenePos());
120
graphicsitem->translate(d.x(), d.y());
121
// qDebug() QString("Translated %1 by %2 %3").arg((unsigned int) graphicsitem).arg(d.x()).arg(d.y()).toAscii();
123
// Regenerate the SVG transformation matrix later
124
WbItem* wbitem = dynamic_cast<WbItem*>(graphicsitem);
126
scene_->queueTransformationRegeneration(wbitem);
130
} else if(widget_->mode() == WbWidget::Rotate) {
132
// Rotate each selected item
133
// get center coordinates of selected items in scene coordinates
134
QPointF scenePivot = scene_->selectionCenter();
135
// Determine the direction relative to the center
136
// Divide the sum by two to reduce the "speed" of rotation
137
QPointF difference = event->scenePos() - event->lastScenePos();
138
// qDebug() << QString("d: %1 %2 = %3 %4 + %5 %6").arg(difference.x()).arg(difference.y()).arg(event->scenePos().x()).arg(event->scenePos().y()).arg(event->lastScenePos().x()).arg(event->lastScenePos().y());
139
QPointF p = event->scenePos();
141
if(p.x() >= scenePivot.x() && p.y() >= scenePivot.y()) {
142
delta.rotate((-difference.x() + difference.y()) / 2);
143
} else if(p.x() < scenePivot.x() && p.y() >= scenePivot.y()) {
144
delta.rotate((-difference.x() - difference.y()) / 2);
145
} else if(p.x() < scenePivot.x() && p.y() < scenePivot.y()) {
146
delta.rotate((difference.x() - difference.y()) / 2);
147
} else if(p.x() >= scenePivot.x() && p.y() < scenePivot.y()) {
148
delta.rotate((difference.x() + difference.y()) / 2);
151
foreach(QGraphicsItem* graphicsitem, scene()->selectedItems()) {
152
if (!graphicsitem->parentItem() || !graphicsitem->parentItem()->isSelected()) {
154
// get center coordinates of selected items in item coordinates
155
QPointF itemPivot = graphicsitem->mapFromScene(scenePivot);
156
// translates the the item's center to the origin of the item coordinates
157
translation.translate(-itemPivot.x(), -itemPivot.y());
159
graphicsitem->setTransform(QTransform(translation * delta * translation.inverted()), true);
161
// Regenerate the SVG transformation matrix later
162
WbItem* wbitem = dynamic_cast<WbItem*>(graphicsitem);
164
scene_->queueTransformationRegeneration(wbitem);
168
} else if(widget_->mode() == WbWidget::Scale) {
170
// Scale each selected item
171
foreach(QGraphicsItem* graphicsitem, scene()->selectedItems()) {
172
if (!graphicsitem->parentItem() || !graphicsitem->parentItem()->isSelected()) {
174
// get center coordinates in item coordinates
175
QPointF c = center();
176
QMatrix translation, delta;
177
// translates the the item's center to the origin of the item coordinates
178
translation.translate(-c.x(), -c.y());
180
// Moving mouse up enlarges, down shrinks, y axis.
181
// Moving mouse right enlarges, left shrinks, x axis.
182
QPointF difference = event->scenePos() - event->lastScenePos();
183
// Note: the y axis points downwards in scene coordinates
184
delta.scale(1 + difference.x()/50, 1 - difference.y()/50);
186
setTransform(QTransform(translation * delta * translation.inverted()), true);
188
// Regenerate the SVG transformation matrix later
189
scene_->queueTransformationRegeneration(dynamic_cast<WbItem*>(graphicsitem));
188
// Regenerate the SVG transformation matrix later
189
scene_->queueTransformationRegeneration(dynamic_cast<WbItem*>(graphicsitem));
198
198
void WbItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) {
199
QGraphicsSvgItem::mouseReleaseEvent(event);
199
QGraphicsSvgItem::mouseReleaseEvent(event);
201
scene_->regenerateTransformations();
201
scene_->regenerateTransformations();
204
204
QMatrix WbItem::parseSvgTransform(QString string) {
205
string = string.trimmed();
205
string = string.trimmed();
209
return parseTransformationMatrix(string);
209
return parseTransformationMatrix(string);
212
212
QString WbItem::toSvgTransform(const QMatrix &m) {
213
return QString("matrix(%1 %2 %3 %4 %5 %6)").arg(m.m11()).arg(m.m12()).arg(m.m21()).arg(m.m22()).arg(m.dx()).arg(m.dy());
213
return QString("matrix(%1 %2 %3 %4 %5 %6)").arg(m.m11()).arg(m.m12()).arg(m.m21()).arg(m.m22()).arg(m.dx()).arg(m.dy());
216
216
void WbItem::regenerateTransform() {
217
// Replace the QGraphicsItem transformation with an SVG transformation.
218
// Possible as long as no perspective transformations have been applied.
220
// delta is the new transformation to be applied
221
QMatrix delta = transform().toAffine();
222
if(delta.isIdentity())
225
// get the existing SVG transformation
226
QString oldValue = node_.attribute("transform");
227
QMatrix oldTransform = parseSvgTransform(oldValue);
229
// construct a translation that translates the item to (0,0) in scene coordinates
231
// translates the the item's center to the origin of the item coordinates
232
translation.translate(-pos().x(), -pos().y());
234
// generate the string representation
235
QString newValue = toSvgTransform(oldTransform * translation * delta * translation.inverted());
237
if(newValue != oldValue) {
239
session_->setAttribute(node_, "transform", newValue);
217
// Replace the QGraphicsItem transformation with an SVG transformation.
218
// Possible as long as no perspective transformations have been applied.
220
// delta is the new transformation to be applied
221
QMatrix delta = transform().toAffine();
222
if(delta.isIdentity())
225
// get the existing SVG transformation
226
QString oldValue = node_.attribute("transform");
227
QMatrix oldTransform = parseSvgTransform(oldValue);
229
// construct a translation that translates the item to (0,0) in scene coordinates
231
// translates the the item's center to the origin of the item coordinates
232
translation.translate(-pos().x(), -pos().y());
234
// generate the string representation
235
QString newValue = toSvgTransform(oldTransform * translation * delta * translation.inverted());
237
if(newValue != oldValue) {
239
session_->setAttribute(node_, "transform", newValue);
243
243
void WbItem::addToScene() {
244
// qDebug() << QString("adding %1 to scene.").arg(id()).toAscii();
246
// Do nothing if already added and id matches
248
&& node_.hasAttribute("id")
249
&& node_.attribute("id") == elementId())
252
// Read or generate an xml:id for the node
254
if(node_.hasAttribute("id"))
255
id = node_.attribute("id");
257
id = "e" + SxeSession::generateUUID();
258
// qDebug() << QString("Setting new id to %1").arg(id).toAscii();
259
session_->setAttribute(node_, "id", id);
263
// Only render the indicated item
269
scene_->addItem(this);
244
// qDebug() << QString("adding %1 to scene.").arg(id()).toAscii();
246
// Do nothing if already added and id matches
248
&& node_.hasAttribute("id")
249
&& node_.attribute("id") == elementId())
254
// Read or generate an xml:id for the node
256
if(node_.hasAttribute("id")) {
257
id = node_.attribute("id");
260
id = "e" + SxeSession::generateUUID();
261
// qDebug() << QString("Setting new id to %1").arg(id).toAscii();
262
session_->setAttribute(node_, "id", id);
266
// Only render the indicated item
272
scene_->addItem(this);
272
275
void WbItem::removeFromScene() {
273
// qDebug() << QString("removing %1 from scene.").arg(id()).toAscii();
275
scene_->removeItem(this);
277
setElementId(QString());
276
// qDebug() << QString("removing %1 from scene.").arg(id()).toAscii();
278
scene_->removeItem(this);
280
setElementId(QString());
280
283
void WbItem::resetPos() {
281
// set the x & y approriately;
282
setPos(renderer()->boundsOnElement(id()).topLeft());
284
// set the drawing order
287
QDomNodeList children = node_.parentNode().childNodes();
288
while(children.at(i) != node_)
284
// set the x & y approriately;
285
setPos(renderer()->boundsOnElement(id()).topLeft());
287
// set the drawing order
290
QDomNodeList children = node_.parentNode().childNodes();
291
while(children.at(i) != node_) {
294
298
WbItemMenu* WbItem::constructContextMenu() {
295
WbItemMenu* menu = new WbItemMenu(0);
298
// Add the default actions
303
// group = new QActionGroup(0);
305
// pixmap.fill(QColor(Qt::black));
306
// qaction = new QAction(QIcon(pixmap), tr("Thin stroke"), group);
307
// qaction->setData(QVariant(1));
308
// pixmap = QPixmap(6, 6);
309
// pixmap.fill(QColor(Qt::black));
310
// qaction = new QAction(QIcon(pixmap), tr("Medium stroke"), group);
311
// qaction->setData(QVariant(3));
312
// pixmap = QPixmap(12, 12);
313
// pixmap.fill(QColor(Qt::black));
314
// qaction = new QAction(QIcon(pixmap), tr("Thick stroke"), group);
315
// qaction->setData(QVariant(6));
316
// connect(group, SIGNAL(triggered(QAction*)), wbscene, SLOT(setStrokeWidth(QAction*)));
317
// menu->addActionGroup(group);
319
// menu->addSeparator();
320
// group = new QActionGroup(0);
321
// pixmap = QPixmap(16, 16);
322
// pixmap.fill(QColor(Qt::darkCyan));
323
// qaction = new QAction(QIcon(pixmap), tr("Change stroke color"), group);
324
// connect(qaction, SIGNAL(triggered()), wbscene, SLOT(setStrokeColor()));
325
// pixmap.fill(QColor(Qt::darkYellow));
326
// qaction = new QAction(QIcon(pixmap), tr("Change fill color"), group);
327
// connect(qaction, SIGNAL(triggered()), wbscene, SLOT(setFillColor()));
328
// menu->addActionGroup(group);
330
// menu->addSeparator();
331
group = new QActionGroup(0);
332
IconAction* action = new IconAction(tr("Bring forward"), "psi/bringForwards", tr("Bring forward"), 0, group);
333
connect(action, SIGNAL(triggered()), scene_, SLOT(bringForward()));
334
action = new IconAction(tr("Bring to front"), "psi/bringToFront", tr("Bring to front"), 0, group);
335
connect(action, SIGNAL(triggered()), scene_, SLOT(bringToFront()));
336
action = new IconAction(tr("Send backwards"), "psi/sendBackwards", tr("Send backwards"), 0, group);
337
connect(action, SIGNAL(triggered()), scene_, SLOT(sendBackwards()));
338
action = new IconAction(tr("Send to back"), "psi/sendToBack", tr("Send to back"), 0, group);
339
connect(action, SIGNAL(triggered()), scene_, SLOT(sendToBack()));
340
menu->addActionGroup(group);
342
menu->addSeparator();
343
group = new QActionGroup(0);
344
action = new IconAction(tr("Group"), "psi/group", tr("Group"), 0, group);
345
connect(action, SIGNAL(triggered()), scene_, SLOT(group()));
346
action = new IconAction(tr("Ungroup"), "psi/ungroup", tr("Ungroup"), 0, group);
347
connect(action, SIGNAL(triggered()), scene_, SLOT(ungroup()));
348
menu->addActionGroup(group);
299
WbItemMenu* menu = new WbItemMenu(0);
302
// Add the default actions
307
// group = new QActionGroup(0);
309
// pixmap.fill(QColor(Qt::black));
310
// qaction = new QAction(QIcon(pixmap), tr("Thin stroke"), group);
311
// qaction->setData(QVariant(1));
312
// pixmap = QPixmap(6, 6);
313
// pixmap.fill(QColor(Qt::black));
314
// qaction = new QAction(QIcon(pixmap), tr("Medium stroke"), group);
315
// qaction->setData(QVariant(3));
316
// pixmap = QPixmap(12, 12);
317
// pixmap.fill(QColor(Qt::black));
318
// qaction = new QAction(QIcon(pixmap), tr("Thick stroke"), group);
319
// qaction->setData(QVariant(6));
320
// connect(group, SIGNAL(triggered(QAction*)), wbscene, SLOT(setStrokeWidth(QAction*)));
321
// menu->addActionGroup(group);
323
// menu->addSeparator();
324
// group = new QActionGroup(0);
325
// pixmap = QPixmap(16, 16);
326
// pixmap.fill(QColor(Qt::darkCyan));
327
// qaction = new QAction(QIcon(pixmap), tr("Change stroke color"), group);
328
// connect(qaction, SIGNAL(triggered()), wbscene, SLOT(setStrokeColor()));
329
// pixmap.fill(QColor(Qt::darkYellow));
330
// qaction = new QAction(QIcon(pixmap), tr("Change fill color"), group);
331
// connect(qaction, SIGNAL(triggered()), wbscene, SLOT(setFillColor()));
332
// menu->addActionGroup(group);
334
// menu->addSeparator();
335
group = new QActionGroup(0);
336
IconAction* action = new IconAction(tr("Bring forward"), "psi/bringForwards", tr("Bring forward"), 0, group);
337
connect(action, SIGNAL(triggered()), scene_, SLOT(bringForward()));
338
action = new IconAction(tr("Bring to front"), "psi/bringToFront", tr("Bring to front"), 0, group);
339
connect(action, SIGNAL(triggered()), scene_, SLOT(bringToFront()));
340
action = new IconAction(tr("Send backwards"), "psi/sendBackwards", tr("Send backwards"), 0, group);
341
connect(action, SIGNAL(triggered()), scene_, SLOT(sendBackwards()));
342
action = new IconAction(tr("Send to back"), "psi/sendToBack", tr("Send to back"), 0, group);
343
connect(action, SIGNAL(triggered()), scene_, SLOT(sendToBack()));
344
menu->addActionGroup(group);
346
menu->addSeparator();
347
group = new QActionGroup(0);
348
action = new IconAction(tr("Group"), "psi/group", tr("Group"), 0, group);
349
connect(action, SIGNAL(triggered()), scene_, SLOT(group()));
350
action = new IconAction(tr("Ungroup"), "psi/ungroup", tr("Ungroup"), 0, group);
351
connect(action, SIGNAL(triggered()), scene_, SLOT(ungroup()));
352
menu->addActionGroup(group);
354
358
QPointF WbItem::center() {
355
// Determine the center of the item in item coordinates before transformation
356
QRectF r = boundingRect();
357
QPointF c(r.x() + r.width()/2, r.y() + r.height()/2);
358
// qDebug() << QString("center: %1 + %2 %3 + %4").arg(r.x()).arg(r.width()/2).arg(r.y()).arg(r.height()/2);
359
// return the center with transformation applied
360
return transform().map(c);
359
// Determine the center of the item in item coordinates before transformation
360
QRectF r = boundingRect();
361
QPointF c(r.x() + r.width()/2, r.y() + r.height()/2);
362
// qDebug() << QString("center: %1 + %2 %3 + %4").arg(r.x()).arg(r.width()/2).arg(r.y()).arg(r.height()/2);
363
// return the center with transformation applied
364
return transform().map(c);
407
411
static qreal toDouble(const QChar *&str)
409
const int maxLen = 255;//technically doubles can go til 308+ but whatever
413
if (*str == QLatin1Char('-')) {
416
} else if (*str == QLatin1Char('+')) {
419
while (*str >= QLatin1Char('0') && *str <= QLatin1Char('9') && pos < maxLen) {
420
temp[pos++] = str->toLatin1();
423
if (*str == QLatin1Char('.') && pos < maxLen) {
427
while (*str >= QLatin1Char('0') && *str <= QLatin1Char('9') && pos < maxLen) {
428
temp[pos++] = str->toLatin1();
431
bool exponent = false;
432
if (*str == QLatin1Char('e') && pos < maxLen) {
436
if ((*str == QLatin1Char('-') || *str == QLatin1Char('+')) && pos < maxLen) {
437
temp[pos++] = str->toLatin1();
440
while (*str >= QLatin1Char('0') && *str <= QLatin1Char('9') && pos < maxLen) {
441
temp[pos++] = str->toLatin1();
448
if (!exponent && pos < 10) {
450
const char *t = temp;
456
while(*t && *t != '.') {
470
val = ((qreal)ival)/((qreal)div);
413
const int maxLen = 255;//technically doubles can go til 308+ but whatever
417
if (*str == QLatin1Char('-')) {
421
else if (*str == QLatin1Char('+')) {
424
while (*str >= QLatin1Char('0') && *str <= QLatin1Char('9') && pos < maxLen) {
425
temp[pos++] = str->toLatin1();
428
if (*str == QLatin1Char('.') && pos < maxLen) {
432
while (*str >= QLatin1Char('0') && *str <= QLatin1Char('9') && pos < maxLen) {
433
temp[pos++] = str->toLatin1();
436
bool exponent = false;
437
if (*str == QLatin1Char('e') && pos < maxLen) {
441
if ((*str == QLatin1Char('-') || *str == QLatin1Char('+')) && pos < maxLen) {
442
temp[pos++] = str->toLatin1();
445
while (*str >= QLatin1Char('0') && *str <= QLatin1Char('9') && pos < maxLen) {
446
temp[pos++] = str->toLatin1();
453
if (!exponent && pos < 10) {
455
const char *t = temp;
461
while(*t && *t != '.') {
475
val = ((qreal)ival)/((qreal)div);
478
if(sizeof(qreal) == sizeof(float))
479
val = strtof(temp, 0);
484
if(sizeof(qreal) == sizeof(float))
485
val = strtof(temp, 0);
484
val = qstrtod(temp, 0, &ok);
490
val = qstrtod(temp, 0, &ok);
491
497
static QVector<qreal> parseNumbersList(const QChar *&str)
493
QVector<qreal> points;
498
while (*str == QLatin1Char(' '))
500
while ((*str >= QLatin1Char('0') && *str <= QLatin1Char('9')) ||
501
*str == QLatin1Char('-') || *str == QLatin1Char('+') ||
502
*str == QLatin1Char('.')) {
504
points.append(::toDouble(str));
506
while (*str == QLatin1Char(' '))
508
if (*str == QLatin1Char(','))
511
//eat the rest of space
512
while (*str == QLatin1Char(' '))
499
QVector<qreal> points;
504
while (*str == QLatin1Char(' ')) {
507
while ((*str >= QLatin1Char('0') && *str <= QLatin1Char('9')) ||
508
*str == QLatin1Char('-') || *str == QLatin1Char('+') ||
509
*str == QLatin1Char('.')) {
511
points.append(::toDouble(str));
513
while (*str == QLatin1Char(' ')) {
516
if (*str == QLatin1Char(',')) {
520
//eat the rest of space
521
while (*str == QLatin1Char(' ')) {
519
529
static QMatrix parseTransformationMatrix(const QString &value)
522
const QChar *str = value.constData();
524
while (*str != QLatin1Char(0)) {
525
if (str->isSpace() || *str == QLatin1Char(',')) {
537
State state = Matrix;
538
if (*str == QLatin1Char('m')) { //matrix
539
const char *ident = "atrix";
540
for (int i = 0; i < 5; ++i)
541
if (*(++str) != QLatin1Char(ident[i]))
545
} else if (*str == QLatin1Char('t')) { //translate
546
const char *ident = "ranslate";
547
for (int i = 0; i < 8; ++i)
548
if (*(++str) != QLatin1Char(ident[i]))
552
} else if (*str == QLatin1Char('r')) { //rotate
553
const char *ident = "otate";
554
for (int i = 0; i < 5; ++i)
555
if (*(++str) != QLatin1Char(ident[i]))
559
} else if (*str == QLatin1Char('s')) { //scale, skewX, skewY
561
if (*str == QLatin1Char('c')) {
562
const char *ident = "ale";
563
for (int i = 0; i < 3; ++i)
564
if (*(++str) != QLatin1Char(ident[i]))
568
} else if (*str == QLatin1Char('k')) {
569
if (*(++str) != QLatin1Char('e'))
571
if (*(++str) != QLatin1Char('w'))
574
if (*str == QLatin1Char('X'))
576
else if (*str == QLatin1Char('Y'))
589
while (str->isSpace())
591
if (*str != QLatin1Char('('))
594
QVector<qreal> points = parseNumbersList(str);
595
if (*str != QLatin1Char(')'))
599
if(state == Matrix) {
600
if(points.count() != 6)
602
matrix = matrix * QMatrix(points[0], points[1],
603
points[2], points[3],
604
points[4], points[5]);
605
} else if (state == Translate) {
606
if (points.count() == 1)
607
matrix.translate(points[0], 0);
608
else if (points.count() == 2)
609
matrix.translate(points[0], points[1]);
612
} else if (state == Rotate) {
613
if(points.count() == 1) {
614
matrix.rotate(points[0]);
615
} else if (points.count() == 3) {
616
matrix.translate(points[1], points[2]);
617
matrix.rotate(points[0]);
618
matrix.translate(-points[1], -points[2]);
622
} else if (state == Scale) {
623
if (points.count() < 1 || points.count() > 2)
625
qreal sx = points[0];
627
if(points.count() == 2)
629
matrix.scale(sx, sy);
630
} else if (state == SkewX) {
631
if (points.count() != 1)
633
const qreal deg2rad = qreal(0.017453292519943295769);
634
matrix.shear(tan(points[0]*deg2rad), 0);
635
} else if (state == SkewY) {
636
if (points.count() != 1)
638
const qreal deg2rad = qreal(0.017453292519943295769);
639
matrix.shear(0, tan(points[0]*deg2rad));
532
const QChar *str = value.constData();
534
while (*str != QLatin1Char(0)) {
535
if (str->isSpace() || *str == QLatin1Char(',')) {
547
State state = Matrix;
548
if (*str == QLatin1Char('m')) { //matrix
549
const char *ident = "atrix";
550
for (int i = 0; i < 5; ++i) {
551
if (*(++str) != QLatin1Char(ident[i])) {
558
else if (*str == QLatin1Char('t')) { //translate
559
const char *ident = "ranslate";
560
for (int i = 0; i < 8; ++i)
561
if (*(++str) != QLatin1Char(ident[i]))
566
else if (*str == QLatin1Char('r')) { //rotate
567
const char *ident = "otate";
568
for (int i = 0; i < 5; ++i)
569
if (*(++str) != QLatin1Char(ident[i]))
574
else if (*str == QLatin1Char('s')) { //scale, skewX, skewY
576
if (*str == QLatin1Char('c')) {
577
const char *ident = "ale";
578
for (int i = 0; i < 3; ++i)
579
if (*(++str) != QLatin1Char(ident[i]))
583
} else if (*str == QLatin1Char('k')) {
584
if (*(++str) != QLatin1Char('e'))
586
if (*(++str) != QLatin1Char('w'))
589
if (*str == QLatin1Char('X'))
591
else if (*str == QLatin1Char('Y'))
605
while (str->isSpace()) {
608
if (*str != QLatin1Char('(')) {
612
QVector<qreal> points = parseNumbersList(str);
613
if (*str != QLatin1Char(')')) {
618
if(state == Matrix) {
619
if(points.count() != 6) {
622
matrix = matrix * QMatrix(points[0], points[1],
623
points[2], points[3],
624
points[4], points[5]);
626
else if (state == Translate) {
627
if (points.count() == 1)
628
matrix.translate(points[0], 0);
629
else if (points.count() == 2)
630
matrix.translate(points[0], points[1]);
634
else if (state == Rotate) {
635
if(points.count() == 1) {
636
matrix.rotate(points[0]);
637
} else if (points.count() == 3) {
638
matrix.translate(points[1], points[2]);
639
matrix.rotate(points[0]);
640
matrix.translate(-points[1], -points[2]);
645
else if (state == Scale) {
646
if (points.count() < 1 || points.count() > 2)
648
qreal sx = points[0];
650
if(points.count() == 2)
652
matrix.scale(sx, sy);
654
else if (state == SkewX) {
655
if (points.count() != 1)
657
const qreal deg2rad = qreal(0.017453292519943295769);
658
matrix.shear(tan(points[0]*deg2rad), 0);
660
else if (state == SkewY) {
661
if (points.count() != 1)
663
const qreal deg2rad = qreal(0.017453292519943295769);
664
matrix.shear(0, tan(points[0]*deg2rad));