示例#1
0
/**
 * The annotation tool has fairly complex needs. Clicking on an existing
 * annotation selects it, otherwise a new annotation is started.
 */
void Annotation::begin(const paintcore::Point& point, float zoom)
{
	m_selectedId = owner.model()->annotations()->annotationAtPos(point.toPoint(), zoom);
	m_p1 = point;
	m_p2 = point;
	m_isNew = m_selectedId==0;

	if(m_selectedId>0) {
		m_handle = owner.model()->annotations()->annotationHandleAt(m_selectedId, point.toPoint(), zoom);

		owner.setActiveAnnotation(m_selectedId);

	} else {
		// No annotation, start creating a new one

		// I don't want to create a new preview item just for annotations,
		// so we create the preview annotation directly in the model. Since this
		// doesn't affect the other annotations, it shouldn't case any problems.
		// Also, we use a special ID for the preview object that is outside the protocol range.
		m_selectedId = PREVIEW_ID;

		owner.model()->annotations()->changeAnnotation(canvas::Annotation {
			m_selectedId,
			QString(),
			QRect(m_p1.toPoint(), m_p1.toPoint() + QPoint(5,5)),
			QColor(Qt::transparent)
			}
		);
		m_handle = canvas::Annotation::RS_BOTTOMRIGHT;
	}
}
示例#2
0
/**
 * Convert a dpcore::Point to network format. The
 * reverse operation for this is in statetracker.cpp
 * @param p
 * @return
 */
protocol::PenPoint pointToProtocol(const paintcore::Point &point)
{
	int32_t x = point.x() * 4.0;
	int32_t y = point.y() * 4.0;
	uint16_t p = point.pressure() * 0xffff;

	return protocol::PenPoint(x, y, p);
}
示例#3
0
void ColorPicker::motion(const paintcore::Point& point, bool constrain, bool center)
{
	Q_UNUSED(constrain);
	Q_UNUSED(center);
	int layer=0;
	if(settings().getColorPickerSettings()->pickFromLayer()) {
		layer = this->layer();
	}
	scene().pickColor(point.x(), point.y(), layer, _bg);
}
示例#4
0
void ColorPicker::motion(const paintcore::Point& point, bool constrain, bool center)
{
    Q_UNUSED(constrain);
    Q_UNUSED(center);
    int layer=0;
    if(owner.toolSettings()->getColorPickerSettings()->pickFromLayer()) {
        layer = owner.activeLayer();
    }
    int size = owner.toolSettings()->getColorPickerSettings()->getSize();

    owner.model()->pickColor(point.x(), point.y(), layer, size);
}
示例#5
0
void FloodFill::begin(const paintcore::Point &point, float zoom)
{
	// TODO do this in the layer thread?
	Q_UNUSED(zoom);
	FillSettings *ts = owner.toolSettings()->getFillSettings();
	QColor color = owner.toolSettings()->foregroundColor();

	QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));

	owner.model()->layerStack()->lock();
	paintcore::FillResult fill = paintcore::floodfill(
		owner.model()->layerStack(),
		QPoint(point.x(), point.y()),
		color,
		ts->fillTolerance(),
		owner.activeLayer(),
		ts->sampleMerged()
	);
	owner.model()->layerStack()->unlock();

	fill = paintcore::expandFill(fill, ts->fillExpansion(), color);

	if(fill.image.isNull()) {
		QApplication::restoreOverrideCursor();
		return;
	}

	// If the target area is transparent, use the BEHIND compositing mode.
	// This results in nice smooth blending with soft outlines, when the
	// outline has different color than the fill.
	paintcore::BlendMode::Mode mode = paintcore::BlendMode::MODE_NORMAL;
	if(ts->underFill() && (fill.layerSeedColor & 0xff000000) == 0)
		mode = paintcore::BlendMode::MODE_BEHIND;

	// Flood fill is implemented using PutImage rather than a native command.
	// This has the following advantages:
	// - backward and forward compatibility: changes in the algorithm can be made freely
	// - tolerates out-of-sync canvases (shouldn't normally happen, but...)
	// - bugs don't crash/freeze other clients
	//
	// The disadvantage is increased bandwith consumption. However, this is not as bad
	// as one might think: the effective bit-depth of the bitmap is 1bpp and most fills
	// consist of large solid areas, meaning they should compress ridiculously well.
	QList<protocol::MessagePtr> msgs;
	msgs << protocol::MessagePtr(new protocol::UndoPoint(0));
	msgs << net::command::putQImage(0, owner.activeLayer(), fill.x, fill.y, fill.image, mode);
	owner.client()->sendMessages(msgs);

	QApplication::restoreOverrideCursor();
}
示例#6
0
void CanvasView::onPenDown(const paintcore::Point &p, bool right)
{
	if(_scene->hasImage() && !_locked) {

		if(_specialpenmode) {
			// quick color pick mode
			_scene->pickColor(p.x(), p.y(), 0, right);
		} else {
			if(_smoothing>0 && _current_tool->allowSmoothing())
				_smoother.addPoint(p);
			else
				_current_tool->begin(p, right, _zoom);
		}
	}
}
示例#7
0
void CanvasView::onPenMove(const paintcore::Point &p, bool right, bool shift, bool alt)
{
	if(_scene->hasImage() && !_locked) {
		if(_specialpenmode) {
			// quick color pick mode
			_scene->pickColor(p.x(), p.y(), 0, right);
		} else {
			if(_smoothing>0 && _current_tool->allowSmoothing()) {
				_smoother.addPoint(p);
				if(_smoother.hasSmoothPoint()) {
					if(_smoother.isFirstSmoothPoint())
						_current_tool->begin(_smoother.smoothPoint(), right, _zoom);
					else
						_current_tool->motion(_smoother.smoothPoint(), shift, alt);
				}
			} else {
				_current_tool->motion(p, shift, alt);
			}
		}
	}
}
示例#8
0
void CanvasView::updateOutline(paintcore::Point point) {
	if(!_subpixeloutline) {
		point.setX(qFloor(point.x()));
		point.setY(qFloor(point.y()));
	}
	if(_enableoutline && _showoutline && !_locked && !point.roughlySame(_prevoutlinepoint)) {
		QList<QRectF> rect;
		rect.append(QRectF(_prevoutlinepoint.x() - _outlinesize,
					_prevoutlinepoint.y() - _outlinesize, _dia, _dia));
		rect.append(QRectF(point.x() - _outlinesize,
					point.y() - _outlinesize, _dia, _dia));
		updateScene(rect);
		_prevoutlinepoint = point;
	}
}