Commit 4571e3f4 authored by Adrian Page's avatar Adrian Page

Add support for displaying images using OpenGL, taking advantage of hardware...

Add support for displaying images using OpenGL, taking advantage of hardware acceleration if available. This also opens up the world of shaders, for GPU accelerated rendering algorithms and general purpose computation, the first of which should be real-time adjustment of exposure for high dynamic range images.

OpenGL can be enabled/disabled in the settings dialog and it defaults to off for now.

- KisCanvas is no longer a widget, but contains either a QWidget or a QGLWidget. Because of this, a KisCanvasPainter is used to draw on the canvas widget. KisCanvasPainter offers the same API as QPainter, although the OpenGL painter only implements the methods currently used by the tools. This can be filled out as needed. In Qt4, KisCanvasPainter can become a QPainter again as it has gained the ability to paint on OpenGL widgets.
- The image background is no longer compositied into the projection. KisImage::renderToPainter() now takes flags to say whether the background and/or selection should be rendered. This means we now honour the 'transparent' flag in KisDoc::paintContent() for embedded images.
- KisBackground is no longer a KisPaintDevice, but instead contains a QImage with the background pattern.
- The bottom-most layer is now copied into the projection, ignoring the layer's composite op. This is consistent with the gimp and Photoshop.
- Make COMPOSITE_COPY copy transparent pixels and also apply the opacity to the copied data.
- Add multiplyAlpha() and hasHighDynamicRange() methods to the colourspaces.
- Move compositeCopy() from all colorspaces into one in KisAbstractColorSpace.
- Move the painting methods out of KisBoundary (core) into KisBoundaryPainter (ui).
- Make the overview zoom slider zoom the image.


svn path=/trunk/koffice/; revision=475547
parent 649da61c
......@@ -495,17 +495,6 @@ void KisCmykU16ColorSpace::compositeErase(Q_UINT8 *dst,
}
}
void KisCmykU16ColorSpace::compositeCopy(Q_UINT8 *dstRowStart, Q_INT32 dstRowStride, const Q_UINT8 *srcRowStart, Q_INT32 srcRowStride,
const Q_UINT8 */*maskRowStart*/, Q_INT32 /*maskRowStride*/, Q_INT32 rows, Q_INT32 numColumns, Q_UINT16 /*opacity*/)
{
while (rows > 0) {
memcpy(dstRowStart, srcRowStart, numColumns * sizeof(Pixel));
--rows;
srcRowStart += srcRowStride;
dstRowStart += dstRowStride;
}
}
void KisCmykU16ColorSpace::bitBlt(Q_UINT8 *dst,
Q_INT32 dstRowStride,
const Q_UINT8 *src,
......@@ -562,7 +551,7 @@ void KisCmykU16ColorSpace::bitBlt(Q_UINT8 *dst,
//compositeBumpmap(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
break;
case COMPOSITE_COPY:
compositeCopy(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, opacity);
compositeCopy(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, U8_opacity);
break;
case COMPOSITE_COPY_CYAN:
//compositeCopyCyan(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
......
......@@ -86,7 +86,6 @@ protected:
void compositeDarken(Q_UINT8 *dst, Q_INT32 dstRowStride, const Q_UINT8 *src, Q_INT32 srcRowStride, const Q_UINT8 *mask, Q_INT32 maskRowStride, Q_INT32 rows, Q_INT32 columns, Q_UINT16 opacity);
void compositeLighten(Q_UINT8 *dst, Q_INT32 dstRowStride, const Q_UINT8 *src, Q_INT32 srcRowStride, const Q_UINT8 *mask, Q_INT32 maskRowStride, Q_INT32 rows, Q_INT32 columns, Q_UINT16 opacity);
void compositeErase(Q_UINT8 *dst, Q_INT32 dstRowStride, const Q_UINT8 *src, Q_INT32 srcRowStride, const Q_UINT8 *mask, Q_INT32 maskRowStride, Q_INT32 rows, Q_INT32 columns, Q_UINT16 opacity);
void compositeCopy(Q_UINT8 *dst, Q_INT32 dstRowStride, const Q_UINT8 *src, Q_INT32 srcRowStride, const Q_UINT8 *mask, Q_INT32 maskRowStride, Q_INT32 rows, Q_INT32 columns, Q_UINT16 opacity);
private:
friend class KisCmykU16ColorSpaceTester;
......
......@@ -460,17 +460,6 @@ void KisGrayU16ColorSpace::compositeErase(Q_UINT8 *dst,
}
}
void KisGrayU16ColorSpace::compositeCopy(Q_UINT8 *dstRowStart, Q_INT32 dstRowStride, const Q_UINT8 *srcRowStart, Q_INT32 srcRowStride,
const Q_UINT8 */*maskRowStart*/, Q_INT32 /*maskRowStride*/, Q_INT32 rows, Q_INT32 numColumns, Q_UINT16 /*opacity*/)
{
while (rows > 0) {
memcpy(dstRowStart, srcRowStart, numColumns * sizeof(Pixel));
--rows;
srcRowStart += srcRowStride;
dstRowStart += dstRowStride;
}
}
void KisGrayU16ColorSpace::bitBlt(Q_UINT8 *dst,
Q_INT32 dstRowStride,
const Q_UINT8 *src,
......@@ -527,7 +516,7 @@ void KisGrayU16ColorSpace::bitBlt(Q_UINT8 *dst,
//compositeBumpmap(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
break;
case COMPOSITE_COPY:
compositeCopy(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, opacity);
compositeCopy(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, U8_opacity);
break;
case COMPOSITE_COPY_RED:
//compositeCopyRed(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
......
......@@ -84,7 +84,6 @@ protected:
void compositeDarken(Q_UINT8 *dst, Q_INT32 dstRowStride, const Q_UINT8 *src, Q_INT32 srcRowStride, const Q_UINT8 *mask, Q_INT32 maskRowStride, Q_INT32 rows, Q_INT32 columns, Q_UINT16 opacity);
void compositeLighten(Q_UINT8 *dst, Q_INT32 dstRowStride, const Q_UINT8 *src, Q_INT32 srcRowStride, const Q_UINT8 *mask, Q_INT32 maskRowStride, Q_INT32 rows, Q_INT32 columns, Q_UINT16 opacity);
void compositeErase(Q_UINT8 *dst, Q_INT32 dstRowStride, const Q_UINT8 *src, Q_INT32 srcRowStride, const Q_UINT8 *mask, Q_INT32 maskRowStride, Q_INT32 rows, Q_INT32 columns, Q_UINT16 opacity);
void compositeCopy(Q_UINT8 *dst, Q_INT32 dstRowStride, const Q_UINT8 *src, Q_INT32 srcRowStride, const Q_UINT8 *mask, Q_INT32 maskRowStride, Q_INT32 rows, Q_INT32 columns, Q_UINT16 opacity);
private:
friend class KisGrayU16ColorSpaceTester;
......
......@@ -737,17 +737,6 @@ void KisRgbF16HalfColorSpace::compositeErase(Q_UINT8 *dst,
}
}
void KisRgbF16HalfColorSpace::compositeCopy(Q_UINT8 *dstRowStart, Q_INT32 dstRowStride, const Q_UINT8 *srcRowStart, Q_INT32 srcRowStride,
const Q_UINT8 */*maskRowStart*/, Q_INT32 /*maskRowStride*/, Q_INT32 rows, Q_INT32 numColumns, half /*opacity*/)
{
while (rows > 0) {
memcpy(dstRowStart, srcRowStart, numColumns * sizeof(Pixel));
--rows;
srcRowStart += srcRowStride;
dstRowStart += dstRowStride;
}
}
void KisRgbF16HalfColorSpace::bitBlt(Q_UINT8 *dst,
Q_INT32 dstRowStride,
const Q_UINT8 *src,
......@@ -804,7 +793,7 @@ void KisRgbF16HalfColorSpace::bitBlt(Q_UINT8 *dst,
//compositeBumpmap(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
break;
case COMPOSITE_COPY:
compositeCopy(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, opacity);
compositeCopy(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, U8_opacity);
break;
case COMPOSITE_COPY_RED:
//compositeCopyRed(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
......
......@@ -95,7 +95,6 @@ protected:
void compositeValue(Q_UINT8 *dst, Q_INT32 dstRowStride, const Q_UINT8 *src, Q_INT32 srcRowStride, const Q_UINT8 *mask, Q_INT32 maskRowStride, Q_INT32 rows, Q_INT32 columns, half opacity);
void compositeColor(Q_UINT8 *dst, Q_INT32 dstRowStride, const Q_UINT8 *src, Q_INT32 srcRowStride, const Q_UINT8 *mask, Q_INT32 maskRowStride, Q_INT32 rows, Q_INT32 columns, half opacity);
void compositeErase(Q_UINT8 *dst, Q_INT32 dstRowStride, const Q_UINT8 *src, Q_INT32 srcRowStride, const Q_UINT8 *mask, Q_INT32 maskRowStride, Q_INT32 rows, Q_INT32 columns, half opacity);
void compositeCopy(Q_UINT8 *dst, Q_INT32 dstRowStride, const Q_UINT8 *src, Q_INT32 srcRowStride, const Q_UINT8 *mask, Q_INT32 maskRowStride, Q_INT32 rows, Q_INT32 columns, half opacity);
private:
friend class KisRgbF16HalfColorSpaceTester;
......
......@@ -736,17 +736,6 @@ void KisRgbF32ColorSpace::compositeErase(Q_UINT8 *dst,
}
}
void KisRgbF32ColorSpace::compositeCopy(Q_UINT8 *dstRowStart, Q_INT32 dstRowStride, const Q_UINT8 *srcRowStart, Q_INT32 srcRowStride,
const Q_UINT8 */*maskRowStart*/, Q_INT32 /*maskRowStride*/, Q_INT32 rows, Q_INT32 numColumns, float /*opacity*/)
{
while (rows > 0) {
memcpy(dstRowStart, srcRowStart, numColumns * sizeof(Pixel));
--rows;
srcRowStart += srcRowStride;
dstRowStart += dstRowStride;
}
}
void KisRgbF32ColorSpace::bitBlt(Q_UINT8 *dst,
Q_INT32 dstRowStride,
const Q_UINT8 *src,
......@@ -803,7 +792,7 @@ void KisRgbF32ColorSpace::bitBlt(Q_UINT8 *dst,
//compositeBumpmap(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
break;
case COMPOSITE_COPY:
compositeCopy(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, opacity);
compositeCopy(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, U8_opacity);
break;
case COMPOSITE_COPY_RED:
//compositeCopyRed(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
......
......@@ -97,8 +97,7 @@ protected:
void compositeValue(Q_UINT8 *dst, Q_INT32 dstRowStride, const Q_UINT8 *src, Q_INT32 srcRowStride, const Q_UINT8 *mask, Q_INT32 maskRowStride, Q_INT32 rows, Q_INT32 columns, float opacity);
void compositeColor(Q_UINT8 *dst, Q_INT32 dstRowStride, const Q_UINT8 *src, Q_INT32 srcRowStride, const Q_UINT8 *mask, Q_INT32 maskRowStride, Q_INT32 rows, Q_INT32 columns, float opacity);
void compositeErase(Q_UINT8 *dst, Q_INT32 dstRowStride, const Q_UINT8 *src, Q_INT32 srcRowStride, const Q_UINT8 *mask, Q_INT32 maskRowStride, Q_INT32 rows, Q_INT32 columns, float opacity);
void compositeCopy(Q_UINT8 *dst, Q_INT32 dstRowStride, const Q_UINT8 *src, Q_INT32 srcRowStride, const Q_UINT8 *mask, Q_INT32 maskRowStride, Q_INT32 rows, Q_INT32 columns, float opacity);
private:
friend class KisRgbF32ColorSpaceTester;
......
......@@ -698,17 +698,6 @@ void KisRgbU16ColorSpace::compositeErase(Q_UINT8 *dst,
}
}
void KisRgbU16ColorSpace::compositeCopy(Q_UINT8 *dstRowStart, Q_INT32 dstRowStride, const Q_UINT8 *srcRowStart, Q_INT32 srcRowStride,
const Q_UINT8 */*maskRowStart*/, Q_INT32 /*maskRowStride*/, Q_INT32 rows, Q_INT32 numColumns, Q_UINT16 /*opacity*/)
{
while (rows > 0) {
memcpy(dstRowStart, srcRowStart, numColumns * sizeof(Pixel));
--rows;
srcRowStart += srcRowStride;
dstRowStart += dstRowStride;
}
}
void KisRgbU16ColorSpace::bitBlt(Q_UINT8 *dst,
Q_INT32 dstRowStride,
const Q_UINT8 *src,
......@@ -765,7 +754,7 @@ void KisRgbU16ColorSpace::bitBlt(Q_UINT8 *dst,
//compositeBumpmap(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
break;
case COMPOSITE_COPY:
compositeCopy(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, opacity);
compositeCopy(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, U8_opacity);
break;
case COMPOSITE_COPY_RED:
//compositeCopyRed(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
......
......@@ -100,7 +100,6 @@ protected:
void compositeValue(Q_UINT8 *dst, Q_INT32 dstRowStride, const Q_UINT8 *src, Q_INT32 srcRowStride, const Q_UINT8 *mask, Q_INT32 maskRowStride, Q_INT32 rows, Q_INT32 columns, Q_UINT16 opacity);
void compositeColor(Q_UINT8 *dst, Q_INT32 dstRowStride, const Q_UINT8 *src, Q_INT32 srcRowStride, const Q_UINT8 *mask, Q_INT32 maskRowStride, Q_INT32 rows, Q_INT32 columns, Q_UINT16 opacity);
void compositeErase(Q_UINT8 *dst, Q_INT32 dstRowStride, const Q_UINT8 *src, Q_INT32 srcRowStride, const Q_UINT8 *mask, Q_INT32 maskRowStride, Q_INT32 rows, Q_INT32 columns, Q_UINT16 opacity);
void compositeCopy(Q_UINT8 *dst, Q_INT32 dstRowStride, const Q_UINT8 *src, Q_INT32 srcRowStride, const Q_UINT8 *mask, Q_INT32 maskRowStride, Q_INT32 rows, Q_INT32 columns, Q_UINT16 opacity);
private:
friend class KisRgbU16ColorSpaceTester;
......
......@@ -1287,7 +1287,6 @@ void KisRgbColorSpace::compositeErase(Q_UINT8 *dst,
}
}
void KisRgbColorSpace::bitBlt(Q_UINT8 *dst,
Q_INT32 dstRowStride,
const Q_UINT8 *src,
......@@ -1343,7 +1342,7 @@ void KisRgbColorSpace::bitBlt(Q_UINT8 *dst,
compositeBumpmap(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
break;
case COMPOSITE_COPY:
compositeCopy(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
compositeCopy(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, opacity);
break;
case COMPOSITE_COPY_RED:
compositeCopyRed(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
......
......@@ -109,9 +109,6 @@ protected:
void compositeValue(Q_UINT8 *dst, Q_INT32 dstRowStride, const Q_UINT8 *src, Q_INT32 srcRowStride, const Q_UINT8 *mask, Q_INT32 maskRowStride, Q_INT32 rows, Q_INT32 columns, Q_UINT8 opacity);
void compositeColor(Q_UINT8 *dst, Q_INT32 dstRowStride, const Q_UINT8 *src, Q_INT32 srcRowStride, const Q_UINT8 *mask, Q_INT32 maskRowStride, Q_INT32 rows, Q_INT32 columns, Q_UINT8 opacity);
void compositeErase(Q_UINT8 *dst, Q_INT32 dstRowStride, const Q_UINT8 *src, Q_INT32 srcRowStride, const Q_UINT8 *mask, Q_INT32 maskRowStride, Q_INT32 rows, Q_INT32 columns, Q_UINT8 opacity);
};
class KisRgbColorSpaceFactory : public KisColorSpaceFactory
......
......@@ -215,6 +215,10 @@ void KisWetColorSpace::setAlpha(Q_UINT8 * pixels, Q_UINT8 alpha, Q_INT32 nPixels
{
}
void KisWetColorSpace::multiplyAlpha(Q_UINT8 * pixels, Q_UINT8 alpha, Q_INT32 nPixels)
{
}
void KisWetColorSpace::applyAlphaU8Mask(Q_UINT8 * pixels, Q_UINT8 * alpha, Q_INT32 nPixels)
{
}
......
......@@ -107,6 +107,7 @@ public:
virtual Q_UINT8 getAlpha(const Q_UINT8 * pixel);
virtual void setAlpha(Q_UINT8 * pixels, Q_UINT8 alpha, Q_INT32 nPixels);
virtual void multiplyAlpha(Q_UINT8 * pixels, Q_UINT8 alpha, Q_INT32 nPixels);
virtual void applyAlphaU8Mask(Q_UINT8 * pixels, Q_UINT8 * alpha, Q_INT32 nPixels);
virtual void applyInverseAlphaU8Mask(Q_UINT8 * pixels, Q_UINT8 * alpha, Q_INT32 nPixels);
......
......@@ -3,7 +3,15 @@ if test -z "$LCMS_LIBS"; then
echo "LittleCMS is missing, Krita will not be built."
echo ""
echo "If you want to compile Krita you should install:"
echo " * lcms 1.12 or newer (http://www.littlecms.com/)"
echo " * lcms 1.12 or newer (http://www.littlecms.com/)"
echo ""
all_tests=bad
else
if test -z "$GLLIB"; then
echo ""
echo "You're missing OpenGL libraries. krita will"
echo "not be able to use OpenGL for hardware"
echo "accelerated rendering."
echo ""
fi
fi
......@@ -80,3 +80,10 @@ AC_MSG_CHECKING([for kunittest])
have_kunittest_header="no"
KDE_CHECK_HEADER(kunittest/tester.h, have_kunittest_header="yes", , )
AM_CONDITIONAL(include_kunittest_tests, test "$have_kunittest_header" = "yes")
# --- OpenGL check ---
AC_HAVE_GL( [], [] )
# --- End of OpenGL check ---
......@@ -17,43 +17,90 @@
*/
#include "kis_global.h"
#include "kis_background.h"
#include "kis_image.h"
#include "kis_iterators_pixel.h"
#include "kis_integer_maths.h"
KisBackground::KisBackground(KisImage *img, Q_INT32 /*width*/, Q_INT32 /*height*/) :
super(img, "background flyweight", OPACITY_OPAQUE)
KisBackground::KisBackground()
: KShared()
{
Q_INT32 y;
Q_UINT8* src = new Q_UINT8[pixelSize()];
Q_UINT32 d = pixelSize();
m_patternTile = QImage(PATTERN_WIDTH, PATTERN_HEIGHT, 32);
m_patternTile.setAlphaBuffer(false);
Q_ASSERT( colorSpace() != 0 );
for (y = 0; y < 64; y++)
for (int y = 0; y < PATTERN_HEIGHT; y++)
{
// This is a little tricky. The background layer doesn't have any pixel
// data written to it yet. So, if we open a read-only iterator, it'll give
// us the default tile, i.e., the empty tile. Fortunately this default tile
// is not shared among all paint devices, because...
KisHLineIteratorPixel hiter = createHLineIterator(0, y, 64, false);
while( ! hiter.isDone())
for (int x = 0; x < PATTERN_WIDTH; x++)
{
Q_UINT8 v = 128 + 63 * ((hiter.x() / 16 + y / 16) % 2);
QColor c(v,v,v);
colorSpace() -> fromQColor(c, OPACITY_OPAQUE, ( Q_UINT8* ) src);
// We cold-bloodedly copy our check pattern bang over the default tile data.
// Now the default tile is checkered. This begs the questions -- should we add
// a setDefaultBackground method to the data manager?
memcpy(hiter.rawData(), src, d);
++hiter;
Q_UINT8 v = 128 + 63 * ((x / 16 + y / 16) % 2);
m_patternTile.setPixel(x, y, qRgb(v, v, v));
}
}
delete [] src;
setExtentIsValid(false);
}
KisBackground::~KisBackground()
{
}
const QImage& KisBackground::patternTile() const
{
return m_patternTile;
}
void KisBackground::paintBackground(QImage image, int imageLeftX, int imageTopY)
{
int patternLeftX;
if (imageLeftX >= 0) {
patternLeftX = imageLeftX % PATTERN_WIDTH;
} else {
patternLeftX = (PATTERN_WIDTH - (-imageLeftX % PATTERN_WIDTH)) % PATTERN_WIDTH;
}
int patternTopY;
if (imageTopY >= 0) {
patternTopY = imageTopY % PATTERN_HEIGHT;
} else {
patternTopY = (PATTERN_HEIGHT - (-imageTopY % PATTERN_HEIGHT)) % PATTERN_HEIGHT;
}
int imageWidth = image.width();
int imageHeight = image.height();
int patternY = patternTopY;
for (int y = 0; y < imageHeight; y++)
{
QRgb *imagePixelPtr = reinterpret_cast<QRgb *>(image.scanLine(y));
const QRgb *patternScanLine = reinterpret_cast<const QRgb *>(m_patternTile.scanLine(patternY));
int patternX = patternLeftX;
for (int x = 0; x < imageWidth; x++)
{
QRgb imagePixel = *imagePixelPtr;
Q_UINT8 imagePixelAlpha = qAlpha(imagePixel);
if (imagePixelAlpha != 255) {
QRgb patternPixel = patternScanLine[patternX];
Q_UINT8 imageRed = UINT8_BLEND(qRed(imagePixel), qRed(patternPixel), imagePixelAlpha);
Q_UINT8 imageGreen = UINT8_BLEND(qGreen(imagePixel), qGreen(patternPixel), imagePixelAlpha);
Q_UINT8 imageBlue = UINT8_BLEND(qBlue(imagePixel), qBlue(patternPixel), imagePixelAlpha);
*imagePixelPtr = qRgba(imageRed, imageGreen, imageBlue, 255);
}
++imagePixelPtr;
++patternX;
if (patternX == PATTERN_WIDTH) {
patternX = 0;
}
}
++patternY;
if (patternY == PATTERN_HEIGHT) {
patternY = 0;
}
}
}
......@@ -18,15 +18,29 @@
#ifndef KIS_BACKGROUND_H_
#define KIS_BACKGROUND_H_
#include "kis_paint_device_impl.h"
#include "kis_layer.h"
#include <qimage.h>
class KisBackground : public KisLayer {
typedef KisLayer super;
#include <ksharedptr.h>
class KisBackground : public KShared {
public:
KisBackground(KisImage *img, Q_INT32 width, Q_INT32 height);
KisBackground();
virtual ~KisBackground();
// Paint the background pattern into the image, 'behind' the image
// contents. The coordinates are for the image's top-left corner
// in image space.
void paintBackground(QImage image, int leftX, int topY);
// Returns the pattern tile.
const QImage& patternTile() const;
protected:
static const int PATTERN_WIDTH = 32;
static const int PATTERN_HEIGHT = 32;
QImage m_patternTile;
};
#endif // KIS_BACKGROUND_H_
......
......@@ -81,57 +81,3 @@ void KisBoundary::generateBoundary(int w, int h) {
}
}
QPixmap KisBoundary::pixmap(int w, int h) {
QPixmap target(w, h);
QPainter painter(&target);
painter.eraseRect(0, 0, w, h);
paint(painter);
painter.end();
return target;
}
void KisBoundary::paint(QPainter& painter) {
QValueList< QValueList<PointPair> >::const_iterator it = m_horSegments.constBegin();
QValueList< QValueList<PointPair> >::const_iterator end = m_horSegments.constEnd();
// Horizontal
while (it != end) {
QValueList<PointPair>::const_iterator lineIt = (*it).constBegin();
QValueList<PointPair>::const_iterator lineEnd = (*it).constEnd();
while (lineIt != lineEnd) {
int x1 = (*lineIt).first.floorX();
int y = (*lineIt).first.floorY();
int x2 = x1 + (*lineIt).second;
painter.drawLine(x1, y, x2, y);
painter.drawPoint(x2, y);
++lineIt;
}
++it;
}
// Vertical
it = m_vertSegments.constBegin();
end = m_vertSegments.constEnd();
while (it != end) {
QValueList<PointPair>::const_iterator lineIt = (*it).constBegin();
QValueList<PointPair>::const_iterator lineEnd = (*it).constEnd();
while (lineIt != lineEnd) {
int x = (*lineIt).first.floorX();
int y1 = (*lineIt).first.floorY();
int y2 = y1 + (*lineIt).second;
painter.drawLine(x, y1, x, y2);
painter.drawPoint(x, y2);
++lineIt;
}
++it;
}
}
......@@ -24,24 +24,20 @@
#include "kis_point.h"
class QPixmap;
class QPainter;
class KisPaintDeviceImpl;
/**
* Generates an 'outline' for a paint device. It should look a bit like the outline of a
* marching ants selection. You can use it to paint the outline of a KisBrush while painting.
* It's not really optimized, so it's not recommended to do big things with it and expect
* it to be fast.
* Usage: construct a KisBoundary, and then run a generateBoundary(w, h) on it. After that,
* you can use the paint method to let it paint the outline, or get a pixmap with the specified
* width and height.
* you can use the KisBoundaryPainter::paint method to let it paint the outline, or get a pixmap.
**/
class KRITACORE_EXPORT KisBoundary {
public:
KisBoundary(KisPaintDeviceImpl* dev);
void generateBoundary(int w, int h);
QPixmap pixmap(int w, int h);
void paint(QPainter& painter);
private:
typedef QPair<KisPoint, int> PointPair; // int -> length
......@@ -49,8 +45,13 @@ private:
KisPaintDeviceImpl* m_device;
int m_fuzzyness;
QValueList< QValueList<PointPair> > m_horSegments;
QValueList< QValueList<PointPair> > m_vertSegments;
typedef QValueList<PointPair> PointPairList;
typedef QValueList< PointPairList > PointPairListList;
PointPairListList m_horSegments;
PointPairListList m_vertSegments;
friend class KisBoundaryPainter;
};
#endif // _KIS_BOUNDARY_H_
......@@ -1123,7 +1123,7 @@ void KisBrush::setHeight(Q_INT32 h)
m_height = h;
}
QImage KisBrush::outline(double pressure) {
/*QImage KisBrush::outline(double pressure) {
KisLayerSP layer = image(KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA",""),""),
KisPaintInformation(pressure));
KisBoundary bounds(layer.data());
......@@ -1135,7 +1135,7 @@ QImage KisBrush::outline(double pressure) {
QImage result;
result = pix;
return result;
}
}*/
void KisBrush::generateBoundary() {
KisLayerSP layer;
......
......@@ -95,7 +95,7 @@ public:
virtual enumBrushType brushType() const;
QImage outline(double pressure = PRESSURE_DEFAULT);
//QImage outline(double pressure = PRESSURE_DEFAULT);
virtual KisBoundary boundary();
/**
......
......@@ -455,7 +455,7 @@ KisImage::KisImage(const KisImage& rhs) : QObject(), KShared(rhs)
m_dirty = rhs.m_dirty;
m_adapter = rhs.m_adapter;
m_bkg = new KisBackground(this, rhs.width(), rhs.height());
m_bkg = new KisBackground();
Q_CHECK_PTR(m_bkg);
m_projection = new KisLayer(this, "projection", OPACITY_OPAQUE);
......@@ -546,7 +546,7 @@ void KisImage::init(KisUndoAdapter *adapter, Q_INT32 width, Q_INT32 height, Kis
m_name = name;
m_colorSpace = colorSpace;
m_bkg = new KisBackground(this, width, height);
m_bkg = new KisBackground();
Q_CHECK_PTR(m_bkg);
m_projection = new KisLayer(this, "projection", OPACITY_OPAQUE);
......@@ -585,9 +585,6 @@ void KisImage::resize(Q_INT32 w, Q_INT32 h, bool cropLayers)
m_projection = new KisLayer(this, "projection", OPACITY_OPAQUE);
Q_CHECK_PTR(m_projection);
m_bkg = new KisBackground(this, w, h);
Q_CHECK_PTR(m_bkg);
if (cropLayers) {
vKisLayerSP_it it;
for ( it = m_layers.begin(); it != m_layers.end(); ++it ) {
......@@ -664,9 +661,6 @@ void KisImage::scale(double sx, double sy, KisProgressDisplayInterface *m_progre
m_projection = new KisLayer(this, "projection", OPACITY_OPAQUE);
Q_CHECK_PTR(m_projection);
<