#include <QPainter> #include "MergeEditor.h" MergeEditor::MergeEditor(void) { mouseCoord = QPoint( -1, -1 ); eraserSize = brushSize = 30; mode = None; } MergeEditor::~MergeEditor(void) { } void MergeEditor::leaveEvent( QEvent* e ) { ImageProjector::leaveEvent( e ); mouseCoord = QPoint( -1, -1 ); update(); } void MergeEditor::mouseMoveEvent( QMouseEvent* e ) { mouseCoord = e->pos(); if ( mode == Paint || mode == Erase ) update(); if ( e->buttons() ) mousePressEvent( e ); } void MergeEditor::mousePressEvent( QMouseEvent* e ) { if ( mode == None ) return; int mx = e->pos().x(); int my = e->pos().y(); mx -= ( contentsRect().width() - displayWidth ) / 2; my -= ( contentsRect().height() - displayHeight ) / 2; mx /= scale; my /= scale; switch( mode ) { case Paint: paintImage( mx, my ); break; case Erase: eraseImage( mx, my ); break; } update(); } void MergeEditor::paintEvent( QPaintEvent* e ) { ImageProjector::paintEvent( e ); if ( mouseCoord == QPoint( -1, -1 ) || mode == None || mode == Spray ) return; QPainter p( this ); p.setClipRect( ( contentsRect().width() - displayWidth ) / 2, ( contentsRect().height() - displayHeight ) / 2, displayWidth, displayHeight ); switch( mode ) { case Paint: p.setPen( brushColor ); p.setRenderHint( QPainter::Antialiasing ); p.drawEllipse ( mouseCoord.x() - brushSize * scale / 2.0, mouseCoord.y() - brushSize * scale / 2.0, brushSize * scale, brushSize * scale ); break; case Erase: QPen pen; pen.setColor( QColor( eraserColor.rgb() ) ); if ( eraserColor.alpha() < 255 ) pen.setStyle( Qt::DashLine ); p.setPen( pen ); p.drawRect ( mouseCoord.x() - eraserSize * scale / 2.0, mouseCoord.y() - eraserSize * scale / 2.0, eraserSize * scale, eraserSize * scale ); break; } } void MergeEditor::eraseImage( int mx, int my ) { if ( maskOn && stencil.isEmpty() ) return; mx -= eraserSize / 2; my -= eraserSize / 2; QPainter p( image ); if ( maskOn ) p.setClipRegion( stencil ); p.setPen( Qt::NoPen ); p.setBrush( eraserColor ); p.setCompositionMode( QPainter::CompositionMode_Source ); p.drawRect( mx, my, eraserSize, eraserSize ); emit imageEdited(); } void MergeEditor::paintImage( int mx, int my ) { if ( maskOn && stencil.isEmpty() ) return; mx -= brushSize / 2; my -= brushSize / 2; QPainter p; p.begin( image ); if ( maskOn ) p.setClipRegion( stencil ); p.setPen( Qt::NoPen ); p.setBrush( QBrush( texture ) ); if ( brushSize < 3 ) p.drawRect( mx, my, brushSize, brushSize ); else p.drawEllipse( mx, my, brushSize, brushSize ); p.end(); emit imageEdited(); } void MergeEditor::sprayImage() { if ( maskOn && stencil.isEmpty() ) return; QPainter p( image ); if ( maskOn ) p.setClipRegion( stencil ); p.setPen( Qt::NoPen ); p.fillRect( image->rect(), QBrush( texture ) ); update(); emit imageEdited(); } void MergeEditor::setMask( QBitmap* m ) { ImageProjector::setMask( m ); QRegion r( *m ); QRegion a( image->rect() ); stencil = a.subtract( r ); } void MergeEditor::setTheirs( QImage* t ) { theirs = t; scratch = QImage( theirs->size(), QImage::Format_ARGB32_Premultiplied ); s_alpha = QImage( theirs->size(), QImage::Format_Indexed8 ); QVector<QRgb> colors(256); for ( int i = 0 ; i < 256 ; i++ ) { colors[i] = qRgb( i, i, i ); } s_alpha.setColorTable( colors ); texture = QPixmap( theirs->size() ); QPainter p( &scratch ); p.drawImage( 0, 0, *theirs ); } void MergeEditor::setBlend( int alpha ) { brushColor = QColor( 64, 255 - alpha, alpha ); s_alpha.fill( alpha ); QPainter p1; p1.begin( &scratch ); p1.drawImage( 0, 0, *theirs ); p1.end(); scratch.setAlphaChannel( s_alpha ); QPainter p; p.begin( &texture ); p.drawImage( 0, 0, *yours ); p.drawImage( 0, 0, scratch ); p.end(); if ( mode == Spray ) sprayImage(); } void MergeEditor::setBrushSize( int px ) { brushSize = px; } void MergeEditor::setEraserSize( int px ) { eraserSize = px; } void MergeEditor::setMode( EditMode m ) { mode = m; setMouseTracking( m == Paint || m == Erase ); if ( hasMouseTracking() ) setCursor( QCursor( Qt::CrossCursor ) ); else setCursor( QCursor( Qt::ArrowCursor ) ); }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#7 | 5549 | Sam Stafford |
Fix another edge case bug where Qt's behavior is the opposite of what I'd expect - when an empty clip region is set, the clip region is cleared entirely, as if a FULL clip region had been set. The resulting bug was that any image which had zero conflicts would show up as one gigantic conflict - ack! The code now checks for this case and bails out of any painting operation that's about to use an empty clip region. |
||
#6 | 5539 | Sam Stafford | Kick off another window to merge alpha channels, if present. | ||
#5 | 5534 | Sam Stafford |
A brand new help file, a bit of cosmetic sprucing, one critical bug fix, and a partridge in a pear tree. |
||
#4 | 5524 | Sam Stafford | Eraser and spraypaint tools, and "Save" command. | ||
#3 | 5520 | Sam Stafford |
Configurable brush sizes, complete with procedurally generated icons. Spiffy. |
||
#2 | 5519 | Sam Stafford |
Added the paintbrush tool. Now we're getting somewhere. |
||
#1 | 5516 | Sam Stafford | The M is for Merge. |