/****************************************************************************
**
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
**
** This file is part of the painting module of the Qt Toolkit.
**
** This file may be distributed under the terms of the Q Public License
** as defined by Trolltech AS of Norway and appearing in the file
** LICENSE.QPL included in the packaging of this file.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
**   information about Qt Commercial License Agreements.
** See http://www.trolltech.com/qpl/ for QPL licensing information.
** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
**/

#ifndef QPAINTENGINE_RASTER_P_H
#define QPAINTENGINE_RASTER_P_H

//
//  W A R N I N G
//  -------------
//
// This file is not part of the Qt API.  It exists for the convenience
// of other Qt classes.  This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//

#include <QtGui/qpaintengine.h>
#include <QtGui/qpainterpath.h>

#include <private/qpaintengine_p.h>
#include <private/qdatabuffer_p.h>
#include <private/qdrawhelper_p.h>

class QFTOutlineMapper;
class QRasterPaintEnginePrivate;
class QRasterBuffer;

struct FillData;
struct SolidFillData;
struct TextureFillData;
struct LinearGradientData;
struct RadialGradientData;
struct ConicalGradientData;

/*******************************************************************************
 * QRasterPaintEngine
 */
class QRasterPaintEngine : public QPaintEngine
{
    Q_DECLARE_PRIVATE(QRasterPaintEngine)
public:
    QRasterPaintEngine();
    ~QRasterPaintEngine();
    bool begin(QPaintDevice *device);
    bool end();

    void updatePen(const QPen &pen);
    void updateBrush(const QBrush &brush, const QPointF &origin);
    void updateFont(const QFont &font);
    void updateBackground(Qt::BGMode bgmode, const QBrush &bgBrush);
    void updateMatrix(const QMatrix &matrix);
    void updateClipRegion(const QRegion &region, Qt::ClipOperation op);
    void updateRenderHints(QPainter::RenderHints hints);
    void updateClipPath(const QPainterPath &path, Qt::ClipOperation op);

    void drawPath(const QPainterPath &path);

    void fillPath(const QPainterPath &path, FillData *fillData);

    void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr,
                    Qt::PixmapDrawingMode mode = Qt::ComposePixmap);
    void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr,
                   Qt::ImageConversionFlags flags = Qt::AutoColor);
    void drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &sr,
                         Qt::PixmapDrawingMode mode = Qt::ComposePixmap);
    void drawTextItem(const QPointF &p, const QTextItem &textItem);

    void drawRect(const QRectF &rect);
    void drawLine(const QLineF &line);

    void setFlushOnEnd(bool flush);
    void flush(QPaintDevice *device);

#ifdef Q_WS_WIN
    HDC getDC() const;
    void releaseDC(HDC hdc) const;
#endif

    Type type() const { return Raster; }

    QPoint coordinateOffset() const;
};


/*******************************************************************************
 * QRasterPaintEnginePrivate
 */
class QRasterPaintEnginePrivate : public QPaintEnginePrivate
{
    Q_DECLARE_PUBLIC(QRasterPaintEngine)
public:

    enum RasterOperation {
        SourceCopy,
        SourceOverComposite
    };

    void fillForBrush(const QBrush &brush, FillData *data, const QPainterPath *path);
    void updateClip_helper(const QPainterPath &path, Qt::ClipOperation);

    QImage *colorizeBitmap(const QImage *image, const QColor &color);

    qreal *gradientStopPoints(const QGradient *gradient);
    ARGB *gradientStopColors(const QGradient *gradient);

    ARGB mapColor(const QColor &color) const;

    QBrush brush;
    QBrush bgBrush;
    QPen pen;
    QMatrix matrix;
    QMatrix brushMatrix;
    QMatrix penMatrix;

    QPaintDevice *device;
    QFTOutlineMapper *outlineMapper;
    QRasterBuffer *rasterBuffer;
    QRasterBuffer *fontRasterBuffer;

    QDataBuffer<qreal> stopPoints;
    QDataBuffer<ARGB> stopColors;

    QPainterPath baseClip;
    QRect deviceRect;

    FillData *fillData;
    SolidFillData *solidFillData;
    TextureFillData *textureFillData;
    LinearGradientData *linearGradientData;
    RadialGradientData *radialGradientData;
    ConicalGradientData *conicalGradientData;

    DrawHelper *drawHelper;

    QImage tempImage;

    RasterOperation rasterOperation;

    int deviceDepth;

    uint txop;

    uint opaqueBackground : 1;
    uint clipEnabled : 1;
    uint antialiased : 1;
    uint bilinear : 1;
    uint flushOnEnd : 1;
};

/*******************************************************************************
 * QRasterBuffer
 */
class QRasterBuffer
{
public:
#if defined(Q_WS_WIN)
    QRasterBuffer() : m_hdc(0), m_bitmap(0), m_buffer(0), m_width(0), m_height(0) { init(); }

    HDC hdc() const { return m_hdc; }
#elif defined(Q_WS_X11)
    QRasterBuffer() : m_width(0), m_height(0), m_buffer(0) { init(); }
#elif defined(Q_WS_MAC)
    QRasterBuffer() : m_data(0), m_width(0), m_height(0), m_buffer(0) { init(); }
# if defined(QMAC_NO_COREGRAPHICS)
    GWorldPtr m_data;
# else
    CGImageRef m_data;
#endif
#endif
    ~QRasterBuffer();

    void init();

    void prepare(QImage *image);
    void prepare(int w, int h);
    void prepareBuffer(int w, int h);
    void prepareClip(int w, int h);

    void resetBuffer(int val=0);
    void resetClip();

    void resizeClipSpan(int y, int size);
    void appendClipSpan(int x, int y, int len, int coverage);
    void replaceClipSpans(int y, QSpan *spans, int spanCount);
    void resetClipSpans(int y, int count);

    ARGB *scanLine(int y) { Q_ASSERT(y>=0); Q_ASSERT(y<m_height); return m_buffer + y * m_width; }

#ifndef QT_NO_DEBUG
    QImage clipImage() const;
#endif

    QSpan *clipSpans(int y) const { Q_ASSERT(y >= 0 && y <= m_height); return m_clipSpans[y]; }
    int clipSpanCount(int y) const { Q_ASSERT(y >= 0 && y <= m_height); return m_clipSpanCount[y]; }

    int width() const { return m_width; }
    int height() const { return m_height; }

    ARGB *buffer() const { return m_buffer; }

private:
#if defined(Q_WS_WIN)
    HDC m_hdc;
    HBITMAP m_bitmap;
#endif

    int m_width;
    int m_height;
    ARGB *m_buffer;

    int *m_clipSpanCount;
    int *m_clipSpanCapacity;
    QSpan **m_clipSpans;
};

#endif // QPAINTENGINE_RASTER_P_H
