Commit 48abe885 authored by Halla Rempt's avatar Halla Rempt

Temp fix for Sven's maskblt problem; the real solutions (a base composite

op class for colorspaces without an alpha channel or something like that
is being investigated.)

svn path=/trunk/koffice/; revision=686818
parent 3a3cee14
......@@ -24,10 +24,114 @@
#include "kis_gray_colorspace.h"
#include "compositeops/KoCompositeOpOver.h"
#include "compositeops/KoCompositeOpErase.h"
namespace {
const quint8 PIXEL_GRAY = 0;
class CompositeOver : public KoCompositeOp {
public:
CompositeOver(KoColorSpace * cs)
: KoCompositeOp(cs, COMPOSITE_OVER, i18n("Normal" ) )
{
}
public:
void composite(quint8 *dst,
qint32 dststride,
const quint8 *src,
qint32 srcstride,
const quint8 *maskRowStart,
qint32 maskstride,
qint32 rows,
qint32 cols,
quint8 opacity,
const QBitArray & channelFlags) const
{
Q_UNUSED(channelFlags);
quint8 *d;
const quint8 *s;
qint32 i;
if (rows <= 0 || cols <= 0)
return;
if (opacity == OPACITY_TRANSPARENT)
return;
if (opacity != OPACITY_OPAQUE) {
while (rows-- > 0) {
const quint8 *mask = maskRowStart;
d = dst;
s = src;
for (i = cols; i > 0; i--, d++, s++) {
// If the mask tells us to completely not
// blend this pixel, continue.
if ( mask != 0 ) {
if ( mask[0] == OPACITY_TRANSPARENT ) {
mask++;
continue;
}
mask++;
}
if (s[PIXEL_GRAY] == OPACITY_TRANSPARENT)
continue;
int srcGray = (s[PIXEL_GRAY] * opacity + UINT8_MAX / 2) / UINT8_MAX;
d[PIXEL_GRAY] = (d[PIXEL_GRAY] * (UINT8_MAX - srcGray) + srcGray * UINT8_MAX + UINT8_MAX / 2) / UINT8_MAX;
}
dst += dststride;
src += srcstride;
if(maskRowStart) {
maskRowStart += maskstride;
}
}
}
else {
while (rows-- > 0) {
const quint8 *mask = maskRowStart;
d = dst;
s = src;
for (i = cols; i > 0; i--, d++, s++) {
if ( mask != 0 ) {
// If the mask tells us to completely not
// blend this pixel, continue.
if ( mask[0] == OPACITY_TRANSPARENT ) {
mask++;
continue;
}
mask++;
}
if (s[PIXEL_GRAY] == OPACITY_TRANSPARENT)
continue;
if (d[PIXEL_GRAY] == OPACITY_TRANSPARENT || s[PIXEL_GRAY] == OPACITY_OPAQUE) {
memcpy(d, s, 1);
continue;
}
int srcGray = s[PIXEL_GRAY];
d[PIXEL_GRAY] = (d[PIXEL_GRAY] * (UINT8_MAX - srcGray) + srcGray * UINT8_MAX + UINT8_MAX / 2) / UINT8_MAX;
}
dst += dststride;
src += srcstride;
if(maskRowStart) {
maskRowStart += maskstride;
}
}
}
}
};
}
KisGrayColorSpace ::KisGrayColorSpace(KoColorSpaceRegistry * parent, KoColorProfile *p) :
KoLcmsColorSpace<GrayU8Traits>("GRAYU8", i18n("Grayscale 8-bit integer/channel)"), parent, TYPE_GRAY_8, icSigGrayData, p)
{
......@@ -35,6 +139,6 @@ KisGrayColorSpace ::KisGrayColorSpace(KoColorSpaceRegistry * parent, KoColorProf
init();
addCompositeOp( new KoCompositeOpOver<GrayU8Traits>( this ) );
addCompositeOp( new CompositeOver( this ) );
addCompositeOp( new KoCompositeOpErase<GrayU8Traits>( this ) );
}
......@@ -400,8 +400,6 @@ void KisPainter::bltMask(qint32 dx, qint32 dy,
sw = srcRect.width();
sh = srcRect.height();
addDirtyRect(QRect(dx, dy, sw, sh));
KoColorSpace * srcCs = srcdev->colorSpace();
qint32 dstY = dy;
......@@ -465,6 +463,8 @@ void KisPainter::bltMask(qint32 dx, qint32 dy,
dstY += rows;
rowsRemaining -= rows;
}
addDirtyRect(QRect(dx, dy, sw, sh));
}
void KisPainter::bltMask(QPoint pos, const KisPaintDeviceSP src, KisPaintDeviceSP selMask, QRect srcRect )
......
......@@ -52,7 +52,6 @@ void KisImageTester::mergeTests()
KoColorSpace * colorSpace = reg->colorSpace("RGBA", 0);
KisImageSP image = new KisImage(0, IMAGE_WIDTH, IMAGE_HEIGHT, colorSpace, "merge test");
image->unlock();
KoColor mergedPixel = image->mergedPixel(0, 0);
......@@ -79,11 +78,12 @@ void KisImageTester::mergeTests()
KisPaintLayer * layer2 = new KisPaintLayer(image, "layer 2", OPACITY_OPAQUE / 2);
image->addLayer(layer2, image->rootLayer(), layer);
layer2->setDirty();
layer2->paintDevice()->setPixel(0, 0, QColor(255, 255, 255), OPACITY_OPAQUE);
layer2->setDirty();
image->rootLayer()->projection()->convertToQImage(0).save( "test.png" );
mergedPixel = image->mergedPixel(0, 0);
mergedPixel.toQColor(&color, &opacity);
......
......@@ -148,13 +148,18 @@ void KisPainterTest::testPaintDeviceBltMaskIrregular(KoColorSpace * cs)
img.save( "bla_" + cs->name() + ".png" );
QCOMPARE( dst->exactBounds(), QRect( 10, 10, 10, 10 ) );
QColor c;
quint8 alpha;
dst->pixel( 13, 13, &c, &alpha );
QCOMPARE( alpha, OPACITY_TRANSPARENT );
QCOMPARE( c.red(), 0 );
QCOMPARE( c.blue(), 0 );
QCOMPARE( c.green(), 0 );
foreach ( KoChannelInfo * channel, cs->channels() ) {
// Only compare alpha if there actually is an alpha channel in
// this colorspace
if ( channel->channelType() == KoChannelInfo::ALPHA ) {
QColor c;
quint8 alpha;
dst->pixel( 13, 13, &c, &alpha );
QCOMPARE( ( int ) alpha, ( int ) OPACITY_TRANSPARENT );
}
}
}
......
......@@ -31,6 +31,9 @@ private:
void allCsApplicator(void (KisPainterTest::* funcPtr)( KoColorSpace*cs ) );
void testPaintDeviceBltMask( KoColorSpace * cs );
void testPaintDeviceBltMaskIrregular( KoColorSpace * cs );
private slots:
void testPaintDeviceBltMask(); // Square selection
......
......@@ -52,30 +52,41 @@ namespace {
qint32 dststride,
const quint8 *src,
qint32 srcstride,
const quint8 *mask,
const quint8 *maskRowStart,
qint32 maskstride,
qint32 rows,
qint32 cols,
quint8 opacity,
const QBitArray & channelFlags) const
{
Q_UNUSED(mask);
Q_UNUSED(maskstride);
Q_UNUSED(channelFlags);
quint8 *d;
const quint8 *s;
qint32 i;
if (rows <= 0 || cols <= 0)
return;
if (opacity == OPACITY_TRANSPARENT)
return;
if (opacity != OPACITY_OPAQUE) {
while (rows-- > 0) {
const quint8 *mask = maskRowStart;
d = dst;
s = src;
for (i = cols; i > 0; i--, d++, s++) {
// If the mask tells us to completely not
// blend this pixel, continue.
if ( mask != 0 ) {
if ( mask[0] == OPACITY_TRANSPARENT ) {
mask++;
continue;
}
mask++;
}
if (s[PIXEL_MASK] == OPACITY_TRANSPARENT)
continue;
int srcAlpha = (s[PIXEL_MASK] * opacity + UINT8_MAX / 2) / UINT8_MAX;
......@@ -83,13 +94,29 @@ namespace {
}
dst += dststride;
src += srcstride;
if(maskRowStart) {
maskRowStart += maskstride;
}
}
}
else {
while (rows-- > 0) {
const quint8 *mask = maskRowStart;
d = dst;
s = src;
for (i = cols; i > 0; i--, d++, s++) {
if ( mask != 0 ) {
// If the mask tells us to completely not
// blend this pixel, continue.
if ( mask[0] == OPACITY_TRANSPARENT ) {
mask++;
continue;
}
mask++;
}
if (s[PIXEL_MASK] == OPACITY_TRANSPARENT)
continue;
if (d[PIXEL_MASK] == OPACITY_TRANSPARENT || s[PIXEL_MASK] == OPACITY_OPAQUE) {
......@@ -101,6 +128,9 @@ namespace {
}
dst += dststride;
src += srcstride;
if(maskRowStart) {
maskRowStart += maskstride;
}
}
}
}
......
......@@ -31,9 +31,11 @@
#define NATIVE_OPACITY_TRANSPARENT KoColorSpaceMathsTraits<channels_type>::zeroValue
/**
* A template base class for all composite op that compose color channels values.
* @param _compositeOp this class should define a function with the following signature:
* inline static void composeColorChannels
* A template base class for all composite op that compose color
* channels values for colorspaces that have an alpha channel.
*
* @param _compositeOp this class should define a function with the
* following signature: inline static void composeColorChannels
*/
template<class _CSTraits, class _compositeOp>
class KoCompositeOpAlphaBase : public KoCompositeOp {
......
/*
* Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
* Copyright (c) 2007 Boudewijn Rempt <boud@valdyas.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef _KOCOMPOSITEOPNONALPHABASE_H_
#define _KOCOMPOSITEOPNONALPHABASE_H_
#include <QBitArray>
#include "KoColorSpaceMaths.h"
#include "KoCompositeOp.h"
#define NATIVE_MAX_VALUE KoColorSpaceMathsTraits<channels_type>::max
#define NATIVE_OPACITY_OPAQUE KoColorSpaceMathsTraits<channels_type>::unitValue
#define NATIVE_OPACITY_TRANSPARENT KoColorSpaceMathsTraits<channels_type>::zeroValue
/**
* A template base class for all composite op that compose color
* channels values for colorspaces that do not have an alpha channel.
* This class looks at the mask value and if the mask value is 0, then
* the corresponding src and dst pixels will not be composited.
*
* @param _compositeOp this class should define a function with the
* following signature: inline static void composeColorChannels
*/
template<class _CSTraits, class _compositeOp>
class KoCompositeOpNonAlphaBase : public KoCompositeOp {
typedef typename _CSTraits::channels_type channels_type;
public:
KoCompositeOpNonAlphaBase(KoColorSpace * cs, const QString& id, const QString& description)
: KoCompositeOp(cs, id, description )
{
}
public:
void composite(quint8 *dstRowStart,
qint32 dststride,
const quint8 *srcRowStart,
qint32 srcstride,
const quint8 *maskRowStart,
qint32 maskstride,
qint32 rows,
qint32 cols,
quint8 U8_opacity,
const QBitArray & channelFlags) const
{
Q_UNUSED( channelFlags );
channels_type opacity = KoColorSpaceMaths<quint8, channels_type>::scaleToA(U8_opacity);
qint32 pixelSize = colorSpace()->pixelSize();
while (rows > 0) {
const channels_type *srcN = reinterpret_cast<const channels_type *>(srcRowStart);
channels_type *dstN = reinterpret_cast<channels_type *>(dstRowStart);
const quint8 *mask = maskRowStart;
qint32 columns = cols;
while (columns > 0) {
channels_type srcAlpha = srcN[_CSTraits::alpha_pos];
// Don't blend dst with src if the mask is fully
// transparent
if (mask != 0) {
if (*mask == OPACITY_TRANSPARENT) {
mask++;
columns--;
srcN+=_CSTraits::channels_nb;
dstN+=_CSTraits::channels_nb;
continue;
}
mask++;
}
_compositeOp::composeColorChannels( NATIVE_OPACITY_OPAQUE, srcN, dstN, pixelSize, channelFlags );
columns--;
srcN+=_CSTraits::channels_nb;
dstN+=_CSTraits::channels_nb;
}
rows--;
srcRowStart += srcstride;
dstRowStart += dststride;
if(maskRowStart) {
maskRowStart += maskstride;
}
}
}
};
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment