Bug 73781
Boudewijn Rempt
boud at valdyas.org
Mon Feb 9 21:55:45 CET 2004
I've been trying to speed up Krita's drawing a bit, first by implementing the
big overlay layer idea. However, this both doesn't give much of a speedup,
and doesn't work correctly, and gives extra problems with compositing of brush
strokes. Here's the code I've been working with:
In kis_painter.cc, I added a buffered transaction that creates a temporary,
visible layer, and blits the contents of that layer onto the target layer
when the transaction is ended::
void KisPainter::beginBufferedTransaction(const QString & customName) {
m_dab = new KisLayer(m_device -> width(),
m_device -> height(),
m_device -> typeWithAlpha(),
"temporary layer");
m_dab -> setOpacity(OPACITY_TRANSPARENT);
m_dab -> visible(true);
beginTransaction(customName);
}
KCommand *KisPainter::endBufferedTransaction()
{
bitBlt( m_dirtyRect.x(), m_dirtyRect.y(),
COMPOSITE_NORMAL,
m_dab.data(), m_dirtyRect.x(), m_dirtyRect.y(), m_dirtyRect.width(),
m_dirtyRect.height() );
delete m_dab;
m_dab = 0;
return endTransaction();
}
And a buffered paintLine and paintAt that now calls setPixel on the temporary
layer directly:
void KisPainter::paintBufferedAt(const QPoint & pos,
const Q_INT32 pressure,
const Q_INT32 /*xTilt*/,
const Q_INT32 /*yTilt*/)
{
Q_INT32 x1 = pos.x() - m_hotSpotX;
Q_INT32 y1 = pos.y() - m_hotSpotY;
Q_INT32 calibratedPressure = pressure / 2;
KisAlphaMask * mask = m_brush -> mask(calibratedPressure);
m_brushWidth = mask -> width();
m_brushHeight = mask -> height();
for (int y = 0; y < mask -> height(); y++) {
for (int x = 0; x < mask -> width(); x++) {
m_dab -> setPixel(x1 + x, y1 + y, m_paintColor, mask -> alphaAt(x, y));
}
}
m_dirtyRect = QRect(x1,
y1,
m_brushWidth,
m_brushHeight);
}
In the paint tool, kis_tool_brush.cc, I call these methods just like I did
with the unbuffered methods before, e.g:
void KisToolBrush::mousePress(QMouseEvent *e)
{
if (!m_subject) return;
if (!m_subject->currentBrush()) return;
if (e->button() == QMouseEvent::LeftButton) {
m_mode = PAINT;
initPaint(e -> pos());
m_painter -> paintBufferedAt(e->pos(), 128, 0, 0);
// XXX: get the rect that should be notified
m_currentImage -> notify( m_painter -> dirtyRect() );
}
}
void KisToolBrush::initPaint(const QPoint & pos)
{
m_dragStart = pos;
m_dragDist = 0;
// Create painter
KisPaintDeviceSP device;
if (m_currentImage && (device = m_currentImage -> activeDevice())) {
if (m_painter)
delete m_painter;
m_painter = new KisPainter( device );
m_painter -> beginBufferedTransaction(i18n("brush"));
}
m_painter -> setPaintColor(m_subject -> fgColor());
m_painter -> setBrush(m_subject -> currentBrush());
}
void KisToolBrush::endPaint()
{
m_mode = HOVER;
KisPaintDeviceSP device;
if (m_currentImage && (device = m_currentImage -> activeDevice())) {
KisUndoAdapter *adapter = m_currentImage -> undoAdapter();
if (adapter && m_painter) {
// If painting in mouse release, make sure painter
// is destructed or end()ed
adapter -> addCommand(m_painter->endBufferedTransaction());
}
delete m_painter;
m_painter = 0;
}
}
void KisToolBrush::mouseRelease(QMouseEvent* e)
{
if (e->button() == QMouseEvent::LeftButton && m_mode == PAINT) {
endPaint();
}
}
void KisToolBrush::mouseMove(QMouseEvent *e)
{
if (m_mode == PAINT) {
paintLine(m_dragStart, e -> pos(), 128, 0, 0);
}
}
void KisToolBrush::paintLine(const QPoint & pos1,
const QPoint & pos2,
const Q_INT32 pressure,
const Q_INT32 xtilt,
const Q_INT32 ytilt)
{
m_dragDist = m_painter -> paintBufferedLine(pos1, pos2, pressure, xtilt,
ytilt, m_dragDist);
m_currentImage -> notify();// m_painter -> dirtyRect() );
m_dragStart = pos2;
}
However, I don't see anything appearing on screen unless I move the layer
about a bit, which means that there's something wrong with updating the
display -- and I get corrupted tiles here and there, and besides, the circles
are hardly any better...
So, unless someone else has a bright idea, I'll call it a day for this idea,
and will go back to the small dabs.
--
Boudewijn Rempt | http://www.valdyas.org/fading/index.cgi
More information about the kimageshop
mailing list