Beispiel #1
0
void BrushPreview::updatePreview()
{
#ifndef DESIGNER_PLUGIN
	if(!m_preview) {
		m_preview = new paintcore::LayerStack;
		m_previewCache = new paintcore::LayerStackPixmapCacheObserver(this);
		m_previewCache->attachToLayerStack(m_preview);
	}

	auto layerstack = m_preview->editor(0);

	if(m_preview->width() == 0) {
		const QSize size = contentsRect().size();
		layerstack.resize(0, size.width(), size.height(), 0);
		layerstack.createLayer(0, 0, QColor(0,0,0), false, false, QString());

	} else if(m_preview->width() != contentsRect().width() || m_preview->height() != contentsRect().height()) {
		layerstack.resize(0, contentsRect().width() - m_preview->width(), contentsRect().height() - m_preview->height(), 0);
	}

	QRectF previewRect(
		m_preview->width()/8,
		m_preview->height()/4,
		m_preview->width()-m_preview->width()/4,
		m_preview->height()-m_preview->height()/2
	);
	paintcore::PointVector pointvector;

	switch(_shape) {
	case Stroke: pointvector = brushes::shapes::sampleStroke(previewRect); break;
	case Line:
		pointvector
			<< paintcore::Point(previewRect.left(), previewRect.top(), 1.0)
			<< paintcore::Point(previewRect.right(), previewRect.bottom(), 1.0);
		break;
	case Rectangle: pointvector = brushes::shapes::rectangle(previewRect); break;
	case Ellipse: pointvector = brushes::shapes::ellipse(previewRect); break;
	case FloodFill:
	case FloodErase: pointvector = brushes::shapes::sampleBlob(previewRect); break;
	}

	QColor bgcolor = m_bg;

	brushes::ClassicBrush brush = m_brush;
	// Special handling for some blending modes
	// TODO this could be implemented in some less ad-hoc way
	if(brush.blendingMode() == paintcore::BlendMode::MODE_BEHIND) {
		// "behind" mode needs a transparent layer for anything to show up
		brush.setBlendingMode(paintcore::BlendMode::MODE_NORMAL);

	} else if(brush.blendingMode() == paintcore::BlendMode::MODE_COLORERASE) {
		// Color-erase mode: use fg color as background
		bgcolor = m_color;
	}

	if(_shape == FloodFill) {
		brush.setColor(bgcolor);
	}

	auto layer = layerstack.getEditableLayerByIndex(0);
	layer.putTile(0, 0, 99999, isTransparentBackground() ? paintcore::Tile() : paintcore::Tile(bgcolor));

	brushes::BrushEngine brushengine;
	brushengine.setBrush(1, 1, brush);

	for(int i=0;i<pointvector.size();++i)
		brushengine.strokeTo(pointvector[i], layer.layer());
	brushengine.endStroke();

	const auto dabs = brushengine.takeDabs();
	for(int i=0;i<dabs.size();++i)
		brushes::drawBrushDabsDirect(*dabs.at(i), layer);

	layer.mergeSublayer(1);

	if(_shape == FloodFill || _shape == FloodErase) {
		paintcore::FillResult fr = paintcore::floodfill(m_preview, previewRect.center().toPoint(), _shape == FloodFill ? m_color : QColor(), _fillTolerance, 0, false, 360000);
		if(_fillExpansion>0)
			fr = paintcore::expandFill(fr, _fillExpansion, m_color);
		if(!fr.image.isNull())
			layer.putImage(fr.x, fr.y, fr.image, _shape == FloodFill ? (_underFill ? paintcore::BlendMode::MODE_BEHIND : paintcore::BlendMode::MODE_NORMAL) : paintcore::BlendMode::MODE_ERASE);
	}

	m_needupdate=false;
#endif
}
void BrushPreview::updatePreview()
{
	if(!m_preview) {
		m_preview = new paintcore::LayerStack;
		QSize size = contentsRect().size();
		m_preview->resize(0, size.width(), size.height(), 0);
		m_preview->createLayer(0, 0, QColor(0,0,0), false, false, QString());
	} else if(m_preview->width() != contentsRect().width() || m_preview->height() != contentsRect().height()) {
		m_preview->resize(0, contentsRect().width() - m_preview->width(), contentsRect().height() - m_preview->height(), 0);
	}

	QRectF previewRect(
		m_preview->width()/8,
		m_preview->height()/4,
		m_preview->width()-m_preview->width()/4,
		m_preview->height()-m_preview->height()/2
	);
	paintcore::PointVector pointvector;

	switch(_shape) {
	case Stroke: pointvector = paintcore::shapes::sampleStroke(previewRect); break;
	case Line:
		pointvector
			<< paintcore::Point(previewRect.left(), previewRect.top(), 1.0)
			<< paintcore::Point(previewRect.right(), previewRect.bottom(), 1.0);
		break;
	case Rectangle: pointvector = paintcore::shapes::rectangle(previewRect); break;
	case Ellipse: pointvector = paintcore::shapes::ellipse(previewRect); break;
	case FloodFill: pointvector = paintcore::shapes::sampleBlob(previewRect); break;
	}

	QColor bgcolor = m_bg;

	paintcore::Brush brush = m_brush;
	// Special handling for some blending modes
	// TODO this could be implemented in some less ad-hoc way
	if(brush.blendingMode() == 11) {
		// "behind" mode needs a transparent layer for anything to show up
		brush.setBlendingMode(paintcore::BlendMode::MODE_NORMAL);

	} else if(brush.blendingMode() == 12) {
		// Color-erase mode: use fg color as background
		bgcolor = m_color;
	}

	if(_shape == FloodFill) {
		brush.setColor(bgcolor);
	}

	paintcore::Layer *layer = m_preview->getLayerByIndex(0);
	layer->fillRect(QRect(0, 0, layer->width(), layer->height()), isTransparentBackground() ? QColor(Qt::transparent) : bgcolor, paintcore::BlendMode::MODE_REPLACE);

	paintcore::StrokeState ss(brush);
	for(int i=1;i<pointvector.size();++i)
		layer->drawLine(0, brush, pointvector[i-1], pointvector[i], ss);

	layer->mergeSublayer(0);

	if(_shape == FloodFill) {
		paintcore::FillResult fr = paintcore::floodfill(m_preview, previewRect.center().toPoint(), m_color, _fillTolerance, 0, false);
		if(_fillExpansion>0)
			fr = paintcore::expandFill(fr, _fillExpansion, m_color);
		layer->putImage(fr.x, fr.y, fr.image, _underFill ? paintcore::BlendMode::MODE_BEHIND : paintcore::BlendMode::MODE_NORMAL);
	}

	m_needupdate=false;
}