Download raw (22.9 KB)
#include "command.h" #include <QColor> #include <QPen> #include <QBrush> #include <QDebug> #include <QFont> #include <QFile> #include <QSvgRenderer> #include <cmath> #include <QLineF> Command * Command::instance = 0; Command::Command(): QObject(0) { coordAbsolute = true; commands.insert("move", 2); commands.insert("line", 2); commands.insert("cubic", 6); commands.insert("stroke", 4); commands.insert("fill", 3); commands.insert("close", 0); commands.insert("end", 0); commands.insert("transform", 6); commands.insert("change", 2); commands.insert("font", 4); commands.insert("text", 1); commands.insert("textblock", 3); commands.insert("image", 1); commands.insert("absolute", 1); commands.insert("svg", 1); commands.insert("svg-effect", 4); commands.insert("svg-effect2", 5); commands.insert("page-size", 2); commands.insert("turn", 2); commands.insert("var", 2); commands.insert("rotate", 1); commands.insert("save",0); commands.insert("restore",0); clearAlias(); connect(&imgWatcher, SIGNAL(fileChanged(QString)), this, SLOT(updateImgCache(QString))); } Command * Command::getInstance() { if(!instance) instance = new Command; return instance; } void Command::clearAlias() { alias.clear(); foreach(QString c, commands.keys()) alias.insert(c,c); } void Command::clearImageCache() { foreach(QString i, imgCache.keys()) imgWatcher.removePath(i); imgCache.clear(); } void Command::setAlias(const QString &key, const QString &val) { if(alias.contains(key)) alias[key] = val; } QString Command::getFromAlias(const QString &a) const { foreach(const QString& s, alias.keys()) { QString av(alias.value(s)); // qDebug()<<"ALIAS"<<av << a; if(av == a) return s; } return QString(); } bool Command::checkVars(const QVariantList &vars) { if(vars.isEmpty()) return false; QString command(getFromAlias(vars.first().toString())); if(commands.contains(command) && vars.count() - 1 >= commands.value(command)) return true; return false; } void Command::highlightPre(QPointF& point) { QColor hcol(Qt::green); painter->drawPath(painterPath); point = painterPath.currentPosition(); painterPath = QPainterPath(); painterPath.moveTo(point); painter->setPen(hcol); painter->setBrush(QBrush(hcol)); } void Command::highlightPost(QPointF& point) { painter->drawPath(painterPath); point = painterPath.currentPosition(); painterPath = QPainterPath(); painterPath.moveTo(point); } double Command::number(QVariant v) const { if(varMap.contains(v.toString())) return varMap.value(v.toString()); return v.toDouble(); } void Command::Draw(const QVariantList &vars, bool higlight) { if(!checkVars(vars)) return; QString command(getFromAlias(vars.first().toString())); const QPointF curPos(painterPath.currentPosition()); if(command == QString("var")) { varMap.insert(vars.at(1).toString(), number(vars.at(2))); } else if(command == QString("move")) { QPointF target(number(vars.at(1)), number(vars.at(2))); if(!coordAbsolute) target = curPos + target; if(higlight) { QPointF p0(curPos); QPointF p1(target); QLineF r(p0,p1); foreach(QTransform t, transforms) { r = t.map(r); } highlightPath->moveTo(r.x1(),r.y1()); highlightPath->lineTo(r.x2(),r.y2()); QRectF targetRect(r.x2() - 4, r.y2() - 4, 8 , 8); highlightPath->addEllipse(targetRect); } painterPath.moveTo(target); } else if(command == QString("line")) { QPointF target(number(vars.at(1)), number(vars.at(2))); if(!coordAbsolute) target = curPos + target; if(higlight) { QPointF p0(curPos); QPointF p1(target); QLineF r(p0,p1); foreach(QTransform t, transforms) { r = t.map(r); } highlightPath->moveTo(r.x1(),r.y1()); highlightPath->lineTo(r.x2(),r.y2()); } painterPath.lineTo(target); } else if(command == QString("turn")) { QString angleStr(vars.at(1).toString()); double distance( number(vars.at(2)) ); int ec(painterPath.elementCount()); QPointF curPosMinus1(curPos); if(ec > 1) // we want at least 2 points { curPosMinus1 = QPointF(painterPath.elementAt(ec - 2).x, painterPath.elementAt(ec - 2).y); } QLineF l1(curPosMinus1, curPos); double startAngle(l1.angle()); double extra(0); if(vars.count() > 3) extra = number(vars.at(3)); bool process(true); double angle(0); if(angleStr == QString("s")) angle = startAngle + extra; else if(angleStr == QString("r")) angle = startAngle + 270 + extra; else if(angleStr == QString("b")) angle = startAngle + 180 + extra; else if(angleStr == QString("l")) angle = startAngle + 90 + extra; else process = false; if(process) { QLineF l2(curPos, QPointF(curPos.x() +1, 0)); l2.setLength(distance); l2.setAngle(angle); painterPath.lineTo(l2.p2()); } } else if(command == QString("cubic")) { QPointF target(number(vars.at(5)), number(vars.at(6))); QPointF c1(number(vars.at(1)), number(vars.at(2))); QPointF c2(number(vars.at(3)), number(vars.at(4))); if(!coordAbsolute) { target = curPos + target; c1 = c1 + curPos; c2 = c2 + curPos; } if(higlight) { QPainterPath path; path.moveTo(curPos); path.lineTo(c1); path.moveTo(curPos); path.cubicTo(c1,c2,target); // path.moveTo(p1); path.lineTo(c2); foreach(QTransform t, transforms) { path = t.map(path); } highlightPath->addPath(path); } painterPath.cubicTo(c1,c2,target); } else if(command == QString("fill")) { painter->drawPath(painterPath); painterPath = QPainterPath(); painterPath.moveTo(curPos); QColor c(vars.at(1).toInt(), vars.at(2).toInt(), vars.at(3).toInt()); if(vars.count() == 5) c.setAlpha(vars.at(4).toInt()); painter->setBrush(c); } else if(command == QString("stroke")) { painter->drawPath(painterPath); painterPath = QPainterPath(); painterPath.moveTo(curPos); QColor c(vars.at(1).toInt(), vars.at(2).toInt(), vars.at(3).toInt()); if(vars.count() == 6) c.setAlpha(vars.at(5).toInt()); double width(number(vars.at(4))); painter->setPen(QPen(QBrush(c), width)); } else if(command == QString("transform")) { painter->drawPath(painterPath); painterPath = QPainterPath(); painterPath.moveTo(curPos); QTransform t(number(vars.at(1)), number(vars.at(2)), number(vars.at(3)), number(vars.at(4)), number(vars.at(5)), number(vars.at(6))); painter->setWorldTransform(t, true); transforms << t; } else if(command == QString("rotate")) { painter->drawPath(painterPath); painterPath = QPainterPath(); painterPath.moveTo(curPos); QTransform t; t.rotate(number(vars.at(1))); painter->setWorldTransform(t, true); transforms << t; } else if(command == QString("end")) { painter->drawPath(painterPath); painterPath = QPainterPath(); } else if(command == QString("close")) { painterPath.closeSubpath(); } else if(command == QString("change")) { setAlias(vars.at(1).toString(), vars.at(2).toString()); emit namesChanged(); } else if(command == QString("font")) { QStringList familyName; for(int i(4); i < vars.count(); ++i) { familyName << vars.at(i).toString(); } QFont f(familyName.join(" ")); f.setPointSizeF(number(vars.at(1))); f.setWeight(vars.at(2).toInt()); f.setItalic(vars.at(3).toBool()); painter->setFont(f); } else if(command == QString("text")) { QRect res; QString text; bool first(true); for(int i(1); i < vars.count(); ++i) { if(first) { first = false; text += vars.at(i).toString(); } else text += QString(" ") + vars.at(i).toString(); } painter->drawText(qRound(curPos.x()), qRound(curPos.y()), 99999, 99999, Qt::AlignLeft | Qt::AlignTop ,text , &res ); if(higlight) { QRectF r(res); foreach(QTransform t, transforms) { r = t.mapRect(r); } highlightPath->addRect(r); } painterPath.moveTo(curPos.x(), res.bottom()); } else if(command == QString("textblock")) { int width(number(vars.at(1))); Qt::Alignment align(Qt::AlignLeft); QString ua(vars.at(2).toString()); if(ua == QString("right")) align = Qt::AlignRight; else if(ua == QString("center")) align = Qt::AlignCenter; else if(ua == QString("justify")) align = Qt::AlignJustify; QRect res; QString text; bool first(true); for(int i(3); i < vars.count(); ++i) { if(first) { first = false; text += vars.at(i).toString(); } else text += QString(" ") + vars.at(i).toString(); } painter->drawText(qRound(curPos.x()), qRound(curPos.y()), width, 99999, align | Qt::AlignTop | Qt::TextWordWrap , text , &res ); if(higlight) { QRectF r(res); foreach(QTransform t, transforms) { r = t.mapRect(r); } highlightPath->addRect(r); } painterPath.moveTo(curPos.x(), res.bottom()); } else if(command == QString("image") && !skipImages) { QString imgFile(vars.at(1).toString()); if(QFile::exists(imgFile)) { QImage img; if(imgCache.contains(imgFile)) img = imgCache.value(imgFile); else { img.load(imgFile); if(!img.isNull()) { imgCache.insert(imgFile, img); if(!imgWatcher.files().contains(imgFile)) imgWatcher.addPath(imgFile); } } if(!img.isNull()) { if(vars.count() >= 4) { painter->drawImage(painterPath.currentPosition(), img.scaled(vars.at(2).toInt(),vars.at(3).toInt())); } else painter->drawImage(painterPath.currentPosition(), img); if(higlight) { QRectF r; QPointF curPos = painterPath.currentPosition(); if(vars.count() >= 4) { QImage simg(img.scaled(vars.at(2).toInt(),vars.at(3).toInt())); r = QRectF(curPos.x(),curPos.y(), simg.width(), simg.height()); } else r = QRectF(curPos.x(),curPos.y(), img.width(), img.height()); foreach(QTransform t, transforms) { r = t.mapRect(r); } highlightPath->addRect(r); } } } } else if(command == QString("absolute")) { coordAbsolute = vars.at(1).toBool(); } else if(command == QString("page-size")) { emit changeSceneRect(number(vars.at(1)), number(vars.at(2))); } else if(command == QString("svg")) { QString svgfile(vars.at(1).toString()); if(QFile::exists(svgfile)) { QSvgRenderer svgRdr(svgfile); QRectF r(svgRdr.viewBoxF()); r.moveTo(curPos); svgRdr.render(painter, r); } } else if(command == QString("svg-effect")) { // @1 svg file // @2 raster file // @3 effect: rotate;... QString svgfile(vars.at(1).toString()); QString effectfile(vars.at(2).toString()); QString effect(vars.at(3).toString()); bool meanIsReallyMean(false); // qDebug()<<"Vars"<<vars.count(); if(vars.count() > 5) { int tmpMIRM(vars.at(5).toInt()); // qDebug()<<"tmp"<<vars.at(5)<<tmpMIRM; if( tmpMIRM > 0) meanIsReallyMean = true; } bool eRotate(effect == QString("r") || effect == QString("R")); bool eScale(effect == QString("s") || effect == QString("S")); bool eScaleAndRotate(effect == QString("w") || effect == QString("W")); bool eInvert(effect == QString("R") || effect == QString("S") || effect == QString("W")); ColorComponent cc(NoColorComponent); QString ccString(vars.at(4).toString()); if(ccString == QString("r") || ccString == QString("R")) cc = Red; else if(ccString == QString("g") || ccString == QString("G")) cc = Green; else if(ccString == QString("b") || ccString == QString("B")) cc = Blue; else if(ccString == QString("h") || ccString == QString("H")) cc = Hue; else if(ccString == QString("s") || ccString == QString("S")) cc = Saturation; else if(ccString == QString("l") || ccString == QString("L")) cc = Lightness; if(QFile::exists(svgfile) && QFile::exists(effectfile) && (eRotate || eScale || eScaleAndRotate) && cc != NoColorComponent) { if(!imgCache.contains(svgfile)) { imgCache.insert(svgfile, QImage()); if(!imgWatcher.files().contains(svgfile)) imgWatcher.addPath(svgfile); } QImage img; if(imgCache.contains(effectfile)) img = imgCache.value(effectfile); else { img.load(effectfile); if(!img.isNull()) { imgCache.insert(effectfile, img); if(!imgWatcher.files().contains(effectfile)) imgWatcher.addPath(effectfile); } } QSvgRenderer svgRdr(svgfile); QRectF r(svgRdr.viewBoxF()); int cols(qRound(img.width() / r.width())); int rows(qRound(img.height() / r.height())); if(cols == 0 || rows == 0) return; // qDebug()<< "E"<<cols<<rows; for(int y(0); y < rows; ++y) { for(int x(0); x < cols; ++x) { // qDebug()<<"I"<<x<<y; int cxOrigin(x * r.width()); int cyOrigin(y * r.height()); int cRight(qMin(qRound(r.width()) + cxOrigin, img.width())); int cBottom(qMin(qRound(r.height()) + cyOrigin, img.height())); double val(0); double nVal(0); double cMean(0); if(meanIsReallyMean) { for(int cy(cyOrigin); cy < cBottom; ++cy) { for(int cx(cxOrigin); cx < cRight; ++cx) { QColor ccolor(img.pixel(cx,cy)); if(cc == Red) val += ccolor.redF(); else if(cc == Green) val += ccolor.greenF(); else if(cc == Blue) val += ccolor.blueF(); else if(cc == Hue) val += ccolor.hslHueF(); else if(cc == Saturation) val += ccolor.hslSaturationF(); else if(cc == Lightness) val += ccolor.lightnessF(); ++nVal; } } cMean = val / nVal; // qDebug()<<val<<cMean<<nVal; } else { QColor ccolor(img.pixel(cxOrigin + (r.width()/2),cyOrigin + (r.height()/2))); if(cc == Red) cMean = ccolor.redF(); else if(cc == Green) cMean = ccolor.greenF(); else if(cc == Blue) cMean = ccolor.blueF(); else if(cc == Hue) cMean = ccolor.hslHueF(); else if(cc == Saturation) cMean = ccolor.hslSaturationF(); else if(cc == Lightness) cMean = ccolor.lightnessF(); } if(eInvert) cMean = 1 - cMean; if(cMean == 0) continue; double tx((x * r.width()) + curPos.x()); double ty(y * r.height() + curPos.y()); double hW(r.width() / 2.0); double hH(r.height() / 2.0); painter->save(); painter->translate(tx, ty); if(eRotate) { double rotVal(cMean * 360.0); painter->setTransform(QTransform().translate(hW, hH).rotate(rotVal).translate(-hW, -hH), true); } else if(eScale) { // painter->scale(cMean, cMean); painter->setTransform(QTransform().translate(hW, hH).scale(cMean, cMean).translate(-hW, -hH), true); } else if(eScaleAndRotate) { double rotVal(cMean * 360.0); QTransform srTrans(QTransform().translate(hW, hH).scale(cMean, cMean).rotate(rotVal).translate(-hW, -hH)); // qDebug()<<srTrans; painter->setTransform(srTrans, true); } svgRdr.render(painter, r); painter->restore(); } } } } else if(command == QString("svg-effect2")) { // @1 svg file // @2 raster file for rotate effect // @3 rotate color component // @4 raster file for scale effect // @5 scale color component // @6 inverse flag QString svgfile(vars.at(1).toString()); QString effectfileRotate(vars.at(2).toString()); QString ccOptionRotate(vars.at(3).toString()); QString effectfileScale(vars.at(4).toString()); QString ccOptionScale(vars.at(5).toString()); bool eInvert(false); if (vars.count() > 6) { double invertOption(number(vars.at(6))); eInvert = invertOption > 0.0; } ColorComponent ccRotate(NoColorComponent); ColorComponent ccScale(NoColorComponent); if(ccOptionRotate == QString("r") || ccOptionRotate == QString("R")) ccRotate = Red; else if(ccOptionRotate == QString("g") || ccOptionRotate == QString("G")) ccRotate = Green; else if(ccOptionRotate == QString("b") || ccOptionRotate == QString("B")) ccRotate = Blue; else if(ccOptionRotate == QString("h") || ccOptionRotate == QString("H")) ccRotate = Hue; else if(ccOptionRotate == QString("s") || ccOptionRotate == QString("S")) ccRotate = Saturation; else if(ccOptionRotate == QString("l") || ccOptionRotate == QString("L")) ccRotate = Lightness; if(ccOptionScale == QString("r") || ccOptionScale == QString("R")) ccScale = Red; else if(ccOptionScale == QString("g") || ccOptionScale == QString("G")) ccScale = Green; else if(ccOptionScale == QString("b") || ccOptionScale == QString("B")) ccScale = Blue; else if(ccOptionScale == QString("h") || ccOptionScale == QString("H")) ccScale = Hue; else if(ccOptionScale == QString("s") || ccOptionScale == QString("S")) ccScale = Saturation; else if(ccOptionScale == QString("l") || ccOptionScale == QString("L")) ccScale = Lightness; if(QFile::exists(svgfile) && QFile::exists(effectfileRotate) && QFile::exists(effectfileScale) && ccRotate != NoColorComponent && ccScale != NoColorComponent) { if(!imgCache.contains(svgfile)) { imgCache.insert(svgfile, QImage()); if(!imgWatcher.files().contains(svgfile)) imgWatcher.addPath(svgfile); } QImage imgRotate, imgScale; if(imgCache.contains(effectfileRotate)) imgRotate = imgCache.value(effectfileRotate); else { imgRotate.load(effectfileRotate); if(!imgRotate.isNull()) { imgCache.insert(effectfileRotate, imgRotate); if(!imgWatcher.files().contains(effectfileRotate)) imgWatcher.addPath(effectfileRotate); } } if(imgCache.contains(effectfileScale)) imgScale = imgCache.value(effectfileScale); else { imgScale.load(effectfileScale); if(!imgScale.isNull()) { imgCache.insert(effectfileScale, imgScale); if(!imgWatcher.files().contains(effectfileScale)) imgWatcher.addPath(effectfileScale); } } if ((imgScale.width() != imgRotate.width()) || (imgScale.height() != imgRotate.height())) { imgScale = imgScale.scaled(imgRotate.width(), imgRotate.height()); } QSvgRenderer svgRdr(svgfile); QRectF r(svgRdr.viewBoxF()); int cols(qRound(imgRotate.width() / r.width())); int rows(qRound(imgRotate.height() / r.height())); if(cols == 0 || rows == 0) return; for(int y(0); y < rows; ++y) { for(int x(0); x < cols; ++x) { // qDebug()<<"I"<<x<<y; int cxOrigin(x * r.width()); int cyOrigin(y * r.height()); int cRight(qMin(qRound(r.width()) + cxOrigin, imgRotate.width())); int cBottom(qMin(qRound(r.height()) + cyOrigin, imgRotate.height())); double valRotate(0); double nValRotate(0); double cMeanRotate(0); double valScale(0); double nValScale(0); double cMeanScale(0); { for(int cy(cyOrigin); cy < cBottom; ++cy) { for(int cx(cxOrigin); cx < cRight; ++cx) { QColor ccolorScale(imgScale.pixel(cx,cy)); if(ccScale == Red) valScale += ccolorScale.redF(); else if(ccScale == Green) valScale += ccolorScale.greenF(); else if(ccScale == Blue) valScale += ccolorScale.blueF(); else if(ccScale == Hue) valScale += ccolorScale.hslHueF(); else if(ccScale == Saturation) valScale += ccolorScale.hslSaturationF(); else if(ccScale == Lightness) valScale += ccolorScale.lightnessF(); ++nValScale; } for(int cx(cxOrigin); cx < cRight; ++cx) { QColor ccolorRotate(imgRotate.pixel(cx,cy)); if(ccRotate == Red) valRotate += ccolorRotate.redF(); else if(ccRotate == Green) valRotate += ccolorRotate.greenF(); else if(ccRotate == Blue) valRotate += ccolorRotate.blueF(); else if(ccRotate == Hue) valRotate += ccolorRotate.hslHueF(); else if(ccRotate == Saturation) valRotate += ccolorRotate.hslSaturationF(); else if(ccRotate == Lightness) valRotate += ccolorRotate.lightnessF(); ++nValRotate; } } cMeanRotate = valRotate / nValRotate; cMeanScale = valScale / nValScale; } if(eInvert) { cMeanScale = 1 - cMeanScale; cMeanRotate = 1 - cMeanRotate; } double tx((x * r.width()) + curPos.x()); double ty(y * r.height() + curPos.y()); double hW(r.width() / 2.0); double hH(r.height() / 2.0); painter->save(); painter->translate(tx, ty); double rotVal(cMeanRotate * 360.0); QTransform srTrans(QTransform().translate(hW, hH).scale(cMeanScale, cMeanScale).rotate(rotVal).translate(-hW, -hH)); painter->setTransform(srTrans, true); svgRdr.render(painter, r); painter->restore(); } } } } else if(command == QString("save")) { painter->save(); } else if(command == QString("restore")) { painter->restore(); } } void Command::endDraw() { if(painter) painter->drawPath(painterPath); } void Command::updateImgCache(const QString &fn) { qDebug()<<"updateImgCache"<<fn; imgCache.remove(fn); // imgWatcher.removePath(fn); emit imageChanged(); }