#include "DoodlePch.h" namespace JusDoodle { DoodlePage::DoodlePage(int pageId, QWidget *parent) : QWidget(parent) , _pageId(pageId) , _color(Qt::transparent) , _width(0.0) , _erase(false) , _background(NULL) , _lines() , _track(NULL) , _clear(false) , _redraw(true) , drawFlag(false) { } DoodlePage::~DoodlePage() { delete _background; delete _track; } void DoodlePage::setBackground(const QString &imagePath) { QImage *newImage = new QImage(imagePath); if (newImage->isNull()) { DOODLE_LOG_ERROR("load <%s>.", imagePath.toUtf8().data()); delete newImage; return; } delete _background; _background = newImage; _redraw = true; update(); } void DoodlePage::setColor(const QColor &color) { _color = color; } void DoodlePage::setWidth(double width) { _width = width; } void DoodlePage::setMode(bool erase) { _erase = erase; } void DoodlePage::draw(const QPoint &from, const QPoint &to, const QColor &color, double width) { } void DoodlePage::draw(const Path &path, const QColor &color, double width) { _lines.push_back(Line(color, width, false, path)); update(); } void DoodlePage::erase(const QPoint &from, const QPoint &to, double width) { } void DoodlePage::erase(const Path &path, double width) { _lines.push_back(Line(Qt::transparent, width, true, path)); update(); } void DoodlePage::clear() { _clear = true; update(); } void DoodlePage::onColorChanged(const QColor &color) { setColor(color); } void DoodlePage::setDrawFlag(bool flag) { drawFlag = flag; } void DoodlePage::onWidthChanged(double width) { setWidth(width); } void DoodlePage::onModeChanged(bool erase) { setMode(erase); } void DoodlePage::resizeEvent(QResizeEvent *event) { _redraw = true; update(); } void DoodlePage::moveEvent(QMoveEvent *event) { _redraw = true; update(); } void DoodlePage::showEvent(QShowEvent *event) { _redraw = true; update(); } void DoodlePage::paintEvent(QPaintEvent *event) { QPainter painter; painter.begin(this); painter.setRenderHint(QPainter::Antialiasing); // clean content if (_clear || _redraw) { painter.setCompositionMode(QPainter::CompositionMode_Clear); painter.setPen(Qt::NoPen); painter.setBrush(Qt::white); painter.drawRect(rect()); } if (_clear) { // delete history _clear = false; _lines.clear(); } else { // paint lines paintLines(&painter); } // draw background image paintBackground(&painter); } void DoodlePage::mousePressEvent(QMouseEvent *event) { trackStart(event->pos()); } void DoodlePage::mouseMoveEvent(QMouseEvent *event) { trackPoint(event->pos()); } void DoodlePage::mouseReleaseEvent(QMouseEvent *event) { trackStop(event->pos()); } void DoodlePage::paintBackground(QPainter *painter) { painter->setCompositionMode(QPainter::CompositionMode_DestinationOver); painter->setPen(Qt::NoPen); if (!_background) painter->setBrush(Qt::lightGray); else painter->setBrush(_background->scaled(size(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); painter->drawRect(rect()); } void DoodlePage::paintLines(QPainter *painter) { // paint history std::list::iterator it; for (it = _lines.begin(); it != _lines.end(); it++) { paintLine(painter, *it); } // paint current if (_track) { paintLine(painter, *_track); } } void DoodlePage::paintLine(QPainter *painter, const Line &line) { Path::const_iterator it = line._path.begin(); if (it == line._path.end()) return; // format path QPainterPath path; QPointF toPoint, controlPoint, nextControlPoint; it->toQPointF(size(), controlPoint); path.moveTo(controlPoint); for (it++ ; it != line._path.end(); it++) { it->toQPointF(size(), nextControlPoint); toPoint.setX((nextControlPoint.x() + controlPoint.x()) / 2); toPoint.setY((nextControlPoint.y() + controlPoint.y()) / 2); path.quadTo(controlPoint, toPoint); controlPoint = nextControlPoint; } qreal width = line._width * size().rwidth(); QPen pen; if (line._erase) { pen = QPen(Qt::transparent, width, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin); painter->setCompositionMode(QPainter::CompositionMode_SourceOut); } else { pen = QPen(line._color, width, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin); painter->setCompositionMode(QPainter::CompositionMode_SourceOver); } painter->strokePath(path, pen); } void DoodlePage::trackStart(const QPointF &point) { if(!drawFlag) return; if (_erase) _track = new Line(_color, WIDTH_ERASE, _erase, size(), true); else _track = new Line(_color, _width, _erase, size(), true); _track->addPoint(point); } void DoodlePage::trackPoint(const QPointF &point) { if (!_track) return; QRectF rect(rect()); if (!rect.contains(point.x(), point.y())) { trackStop(QPointF()); } else { _track->addPoint(point); update(); } } void DoodlePage::trackStop(const QPointF &point) { if (!_track) return; if (!point.isNull()) _track->addPoint(point); if (_track->_path.size() > 2) { if (_track->_erase) { emit notifyErasePath(_pageId, _track->_path, _track->_width); } else { emit notifyDrawPath(_pageId, _track->_path, _track->_color, _track->_width); } _lines.push_back(*_track); } delete _track; _track = NULL; update(); } }