/*
 * Copyright (c) 1987, 1988, 1989, 1990, 1991 Stanford University
 * Copyright (c) 1991 Silicon Graphics, Inc.
 *
 * Permission to use, copy, modify, distribute, and sell this software and 
 * its documentation for any purpose is hereby granted without fee, provided
 * that (i) the above copyright notices and this permission notice appear in
 * all copies of the software and related documentation, and (ii) the names of
 * Stanford and Silicon Graphics may not be used in any advertising or
 * publicity relating to the software without the specific, prior written
 * permission of Stanford and Silicon Graphics.
 * 
 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
 *
 * IN NO EVENT SHALL STANFORD OR SILICON GRAPHICS BE LIABLE FOR
 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
 * OF THIS SOFTWARE.
 */

/*
 * Raster - rasterized image
 */

/* bmarsch: 10 Nov 94: poke and peek are now fast and the raster is
                       dithered on pseudocolor visuals              */

#ifndef iv_raster_h
#define iv_raster_h

#include <InterViews/color.h>
#include <InterViews/coord.h>
#include <InterViews/resource.h>

class Canvas;
class Color;
class RasterRep;


//
// bmarsch: 14 Nov 94
//
//<class>
//
// Name:         Raster
//
// Purpose:      interface of class Raster
//
//
// Public Interface: (only changed and new members)
//
//   Raster(unsigned int width, unsigned int height, boolean dither = true)
//     image size is unsigned int instead of unsigned long (since RasterRep only store
//     unsigned int...); dithering can be switch on/off
//
//
//   virtual void peek(
//     unsigned int x, unsigned int y,
//     unsigned char& red, unsigned char& green, unsigned char& blue) const;
//     This (new) peek returns unsigned char instead of float (ColorIntensity).
//
//   virtual void poke(
//     unsigned int x, unsigned int y,
//     unsigned char red, unsigned char green, unsigned char blue);
//     This (new) poke uses unsigned char instead of float (ColorIntensity).
//
//
// Description:
//   speeds of InterViews' Raster and allows dithering on pseudocolor visuals
//
//</class>



class Raster : public Resource {
public:
  Raster(unsigned long width, unsigned long height, boolean dither = true);
  Raster(const Raster&);
  virtual ~Raster();

  virtual Coord width() const;
  virtual Coord height() const;

  virtual unsigned long pwidth() const;
  virtual unsigned long pheight() const;

  virtual Coord left_bearing() const;
  virtual Coord right_bearing() const;
  virtual Coord ascent() const;
  virtual Coord descent() const;

  virtual void peek(
    unsigned long x, unsigned long y,
    ColorIntensity& red, ColorIntensity& green, ColorIntensity& blue,
    float& alpha) const;

  virtual void poke(
    unsigned long x, unsigned long y,
    ColorIntensity red, ColorIntensity green, ColorIntensity blue,
    float alpha);

  virtual void flush() const;

  RasterRep* rep() const;

  // bmarsch/mpichler, 19941123: peek and poke also with unsigned char
  virtual void peekChr (
    unsigned long x, unsigned long y,
    unsigned char& red, unsigned char& green, unsigned char& blue,
    unsigned char& alpha) const;

  virtual void pokeChr (
    unsigned long x, unsigned long y,
    unsigned char red, unsigned char green, unsigned char blue,
    unsigned char alpha = 255);

  // bmarsch: 20 Dec 94: support transparency
  void useAlphaTransparency();

  // bmarsch: 09 Jan 95: return data array
  const unsigned char* getRGBarray();
  void freeRGBarray();
  const unsigned char* getRGBAarray();
  void freeRGBAarray();

protected:
  Raster(RasterRep*);

private:
  // bmarsch, 19941114: dithering algorithms
  void ditherImage() const;
  void trueColorDither() const;
  void noDither() const;
  void fsDither() const;

  RasterRep* rep_;
  boolean doDither_;

  /* anachronisms */
public:
  unsigned int Width() const;
  unsigned int Height() const;
};

inline RasterRep* Raster::rep() const {
  return rep_;
}

inline unsigned int Raster::Width() const { return (unsigned int)pwidth(); }
inline unsigned int Raster::Height() const { return (unsigned int)pheight(); }


//
// bmarsch: 14 Nov 94
//
//<class>
//
// Name:         RasterAction
//
// Purpose:      interface of class RasterAction
//
//
// Public Interface:
//
//   virtual int progress(float)
//   gives progress of decoding (in [0;1]); if the return value is nonzero, decoding
//   is aborted.
//
//
// Description:
//   used to tell the application about the progress of decoding and allowing it 
//   to abort decoding.
//
//</class>


class RasterAction : public Resource {
public:
  virtual int progress(float p) = 0;

protected:
  RasterAction() {};
  virtual ~RasterAction() {};
};


#if defined(__STDC__) || defined(__ANSI_CPP__)
#define __RasterCallback(T) T##_RasterCallback
#define RasterCallback(T) __RasterCallback(T)
#define __RasterMemberFunction(T) T##_RasterMemberFunction
#define RasterMemberFunction(T) __RasterMemberFunction(T)
#else
#define __RasterCallback(T) T/**/_RasterCallback
#define RasterCallback(T) __RasterCallback(T)
#define __RasterMemberFunction(T) T/**/_RasterMemberFunction
#define RasterMemberFunction(T) __RasterMemberFunction(T)
#endif


#define declareRasterCallback(T) \
typedef int (T::*RasterMemberFunction(T))(float); \
class RasterCallback(T) : public RasterAction { \
public: \
    RasterCallback(T)( \
	T*, RasterMemberFunction(T) progress \
    ); \
    virtual ~RasterCallback(T)(); \
\
    virtual int progress(float); \
private: \
    T* obj_; \
    RasterMemberFunction(T) progress_; \
};

#define implementRasterCallback(T) \
RasterCallback(T)::RasterCallback(T)( \
    T* obj, \
    RasterMemberFunction(T) progress \
) { \
    obj_ = obj; \
    progress_ = progress; \
} \
\
RasterCallback(T)::~RasterCallback(T)() { } \
\
int RasterCallback(T)::progress(float p) \
{ \
    if (progress_ != nil) return (obj_->*progress_)(p); \
    else return 0; \
} 

// note: cxx needs explicit comparison with nil for member functions


#endif
