Proposed change to KisPainter, fix for bug 246639
Dmitry Kazakov
dimula73 at gmail.com
Fri Sep 3 20:38:35 CEST 2010
I'll take a look at this tomorrow morning =)
On Thu, Sep 2, 2010 at 3:31 PM, JL VT <> wrote:
> https://bugs.kde.org/show_bug.cgi?id=246639
>
> This bug had a basic solution which was mostly a workaround I did in
> the Smudge Brush and Hatching Brush.
> Slangkamp proposed that I generalized the solution. Much discussion
> was had and me and DmitryK concluded that the right solution was to
> change bitBltFixedSelection in KisPainter. This function is used only
> by 3 classes in all of Krita (SmudgeOp, HatchingOp, DuplicateOp), all
> of them were coded "believing" that the function fused the mask with
> the canvas selection, but such was not the case, only the mask was
> used.
> This patch changes this behavior and causes
> KisPainter::bitBltFixedSelection to first check if there is a
> selection in the canvas, if there is none, it works exactly as it used
> to (minus a memory leak it had); but if there is one, it fuses the
> canvas selection with the mask in the relevant area before blitting,
> thus respecting selections.
>
> Were this change accepted, I'd follow it by restoring the Hatching
> Brush and Smudge Brush to simply use KisPainter::bitBltFixedSelection
> without the bug workaround.
>
> Below is the new KisPainter::bitBltFixedSelection.
>
> PS: excuse the poor excuse of a "patch" to review, I haven't setup my
> system for SVN contributions, but I didn't want to waste the chance to
> let people review the code while I'm off reinstalling it and then
> sleeping.
>
>
> void KisPainter::bitBltFixedSelection(qint32 dx, qint32 dy, const
> KisPaintDeviceSP srcdev, const KisFixedPaintDeviceSP selection, qint32
> sx, qint32 sy, qint32 sw, qint32 sh)
> {
> if (sw == 0 || sh == 0) return;
> if (srcdev.isNull()) return;
> if (d->device.isNull()) return;
>
> Q_ASSERT(srcdev->pixelSize() == d->pixelSize);
> Q_ASSERT(selection->colorSpace() ==
> KoColorSpaceRegistry::instance()->alpha8());
>
> QRect srcRect = QRect(sx, sy, sw, sh);
> QRect dstRect = QRect(dx, dy, sw, sh);
>
> bool selectedness;
>
> // Check if there is a selection
> if (d->selection.isNull())
> selectedness = false;
> else if (d->selection->isDeselected())
> selectedness = false;
> else
> selectedness = true;
>
> // In case of COMPOSITE_COPY restricting bitblt to extent can
> // have unexpected behavior since it would reduce the area that
> // is copied.
> if (d->compositeOp->id() != COMPOSITE_COPY)
> srcRect &= srcdev->extent();
>
> if (srcRect.isEmpty())
> return;
>
> dx += srcRect.x() - sx;
> dy += srcRect.y() - sy;
>
> sx = srcRect.x();
> sy = srcRect.y();
> sw = srcRect.width();
> sh = srcRect.height();
>
> quint8 * srcBytes = new quint8[ sw * sh * srcdev->pixelSize() ];
> srcdev->readBytes(srcBytes, sx, sy, sw, sh);
>
> quint8 * dstBytes = new quint8[ sw * sh * d->device->pixelSize() ];
> d->device->readBytes(dstBytes, dx, dy, sw, sh);
>
> quint8 * mergedSelectionBytes = new quint8[ sw * sh *
> selection->pixelSize() ];
>
> if (!selectedness) {
> selection->readBytes(mergedSelectionBytes, 0, 0, sw, sh);
> }
> else {
> if (selection->pixelSize() != d->selection->pixelSize())
> qWarning("Error while performing
> KisPainter::bitBltFixedSelection, selection and mask had different
> pixel size, no merge performed");
> else {
> // Here selection->pixelSize() is known to be the same as
> d->selection->pixelSize(), both should be equal to 1
> quint32 totalPixels = sw * sh * selection->pixelSize();
>
> quint8 * selectionBytes = new quint8[ totalPixels ];
> d->selection->readBytes(selectionBytes, dx, dy, sw, sh);
>
> quint8 * maskBytes = new quint8[ totalPixels ];
> selection->readBytes(maskBytes, 0, 0, sw, sh);
>
> /* Some algebra-fu happens here, basically:
> z = x * y (conditional x * y < 1)
> But that's only valid when all numbers are between 0 and 1.
> For values between 0 and 255:
> z/255 = x/255 * y/255
> Conditional:
> x/255 * y/255 < 1 applying *255 on both sides results in
> x * y/255 < 255
> That explains the simplified formula used below.
> 255 is replaced by MAX_SELECTED
> z is replaced by mergedSelectionBytes
> and x and y by selectionBytes and maskBytes
> */
> for (quint32 i = 0; i < totalPixels; ++i) {
> if (selectionBytes[i] * maskBytes[i] / MAX_SELECTED <
> MAX_SELECTED )
> mergedSelectionBytes[i] = selectionBytes[i] *
> maskBytes[i] / MAX_SELECTED;
> else
> mergedSelectionBytes[i] = MAX_SELECTED;
> }
>
> delete [] selectionBytes;
> delete [] maskBytes;
> }
> }
>
> d->colorSpace->bitBlt(dstBytes,
> sw * d->device->pixelSize(),
> srcdev->colorSpace(),
> srcBytes,
> sw * srcdev->colorSpace()->pixelSize(),
> mergedSelectionBytes,
> sw * selection->pixelSize(),
> d->opacity,
> sh,
> sw,
> d->compositeOp,
> d->channelFlags);
>
> d->device->writeBytes(dstBytes, dx, dy, sw, sh);
>
> delete [] srcBytes;
> delete [] dstBytes;
> delete [] mergedSelectionBytes;
>
> addDirtyRect(QRect(dx, dy, sw, sh));
> }
> _______________________________________________
> kimageshop mailing list
> kimageshop at kde.org
> https://mail.kde.org/mailman/listinfo/kimageshop
>
--
Dmitry Kazakov
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.kde.org/pipermail/kimageshop/attachments/20100903/9b92df19/attachment.htm
More information about the kimageshop
mailing list