/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
 * Qwt Widget Library
 * Copyright (C) 1997   Josef Wilgen
 * Copyright (C) 2003   Uwe Rathmann
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the Qwt License, Version 1.0
 *****************************************************************************/

#ifndef QWT_PIXEL_MATRIX_H
#define QWT_PIXEL_MATRIX_H

#include "qwt_global.h"
#include <qbitarray.h>
#include <qrect.h>

/*!
  \brief A bit field corresponding to the pixels of a rectangle

  QwtPixelMatrix is intended to filter out duplicates in an
  unsorted array of points.
*/
class QWT_EXPORT QwtPixelMatrix: public QBitArray
{
public:
    QwtPixelMatrix( const QRect& rect );
    ~QwtPixelMatrix();

    void setRect( const QRect& rect );
    QRect rect() const;

    bool testPixel( int x, int y ) const;
    bool testAndSetPixel( int x, int y, bool on );

    int index( int x, int y ) const;

private:
    QRect d_rect;
};

/*!
  \brief Test if a pixel has been set

  \param x X-coordinate
  \param y Y-coordinate

  \return true, when pos is outside of rect(), or when the pixel
          has already been set.
 */
inline bool QwtPixelMatrix::testPixel( int x, int y ) const
{
    const int idx = index( x, y );
    return ( idx >= 0 ) ? testBit( idx ) : true;
}

/*!
  \brief Set a pixel and test if a pixel has been set before

  \param x X-coordinate
  \param y Y-coordinate
  \param on Set/Clear the pixel

  \return true, when pos is outside of rect(), or when the pixel
          was set before.
 */
inline bool QwtPixelMatrix::testAndSetPixel( int x, int y, bool on )
{
    const int idx = index( x, y );
    if ( idx < 0 )
        return true;

    const bool onBefore = testBit( idx );
    setBit( idx, on );

    return onBefore;
}

/*!
  \brief Calculate the index in the bit field corresponding to a position

  \param x X-coordinate
  \param y Y-coordinate
  \return Index, when rect() contains pos - otherwise -1.
 */
inline int QwtPixelMatrix::index( int x, int y ) const
{
    const int dx = x - d_rect.x();
    if ( dx < 0 || dx >= d_rect.width() )
        return -1;

    const int dy = y - d_rect.y();
    if ( dy < 0 || dy >= d_rect.height() )
        return -1;

    return dy * d_rect.width() + dx;
}

#endif
