Initial import of Dillo
This commit is contained in:
233
dw/imgbuf.hh
Normal file
233
dw/imgbuf.hh
Normal file
@ -0,0 +1,233 @@
|
||||
#ifndef __DW_IMGBUF_HH__
|
||||
#define __DW_IMGBUF_HH__
|
||||
|
||||
#ifndef __INCLUDED_FROM_DW_CORE_HH__
|
||||
# error Do not include this file directly, use "core.hh" instead.
|
||||
#endif
|
||||
|
||||
#include "../lout/debug.hh"
|
||||
|
||||
namespace dw {
|
||||
namespace core {
|
||||
|
||||
/**
|
||||
* \brief The platform independent interface for image buffers.
|
||||
*
|
||||
* %Image buffers depend on the platform (see \ref dw-images-and-backgrounds),
|
||||
* but have this general, platform independent interface. The purpose of
|
||||
* an image buffer is
|
||||
*
|
||||
* <ol>
|
||||
* <li> storing the image data,
|
||||
* <li> handling scaled versions of this buffer, and
|
||||
* <li> drawing.
|
||||
* </ol>
|
||||
*
|
||||
* The latter must be done independently from the window.
|
||||
*
|
||||
* <h3>Creating</h3>
|
||||
*
|
||||
* %Image buffers are created by calling dw::core::Platform::createImgbuf.
|
||||
*
|
||||
* <h3>Storing %Image Data</h3>
|
||||
*
|
||||
* dw::core::Imgbuf supports five image types, which are listed in the table
|
||||
* below. The representation defines, how the colors are stored within
|
||||
* the data, which is passed to dw::core::Imgbuf::copyRow.
|
||||
*
|
||||
* <table>
|
||||
* <tr><th>Type (dw::core::Imgbuf::Type) <th>Bytes per
|
||||
* Pixel <th>Representation
|
||||
* <tr><td>dw::core::Imgbuf::RGB <td>3 <td>red, green, blue
|
||||
* <tr><td>dw::core::Imgbuf::RGBA <td>4 <td>red, green, blue, alpha
|
||||
* <tr><td>dw::core::Imgbuf::GRAY <td>1 <td>gray value
|
||||
* <tr><td>dw::core::Imgbuf::INDEXED <td>1 <td>index to colormap
|
||||
* <tr><td>dw::core::Imgbuf::INDEXED_ALPHA <td>1 <td>index to colormap
|
||||
* </table>
|
||||
*
|
||||
* The last two types need a colormap, which is set by
|
||||
* dw::core::Imgbuf::setCMap, which must be called before
|
||||
* dw::core::Imgbuf::copyRow. This function expects the colors as 32 bit
|
||||
* unsigned integers, which have the format 0xrrbbgg (for indexed
|
||||
* images), or 0xaarrggbb (for indexed alpha), respectively.
|
||||
*
|
||||
*
|
||||
* <h3>Scaling</h3>
|
||||
*
|
||||
* The buffer with the original size, which was created by
|
||||
* dw::core::Platform::createImgbuf, is called root buffer. Imgbuf provides
|
||||
* the ability to scale buffers. Generally, both root buffers, as well as
|
||||
* scaled buffers, may be shared, memory management is done by reference
|
||||
* counters.
|
||||
*
|
||||
* Via dw::core::Imgbuf::getScaledBuf, you can retrieve a scaled buffer.
|
||||
* Generally, something like this must work always, in an efficient way:
|
||||
*
|
||||
* \code
|
||||
* dw::core::Imgbuf *curBuf, *oldBuf;
|
||||
* int width, height,
|
||||
* // ...
|
||||
* oldBuf = curBuf;
|
||||
* curBuf = oldBuf->getScaledBuf(oldBuf, width, height);
|
||||
* oldBuf->unref();
|
||||
* \endcode
|
||||
*
|
||||
* \em oldBuf may both be a root buffer, or a scaled buffer.
|
||||
*
|
||||
* The root buffer keeps a list of all children, and all methods
|
||||
* operating on the image data (dw::core::Imgbuf::copyRow and
|
||||
* dw::core::Imgbuf::setCMap) are delegated to the scaled buffers, when
|
||||
* processed, and inherited, when a new scaled buffer is created. This
|
||||
* means, that they must only be performed for the root buffer.
|
||||
*
|
||||
* A possible implementation could be (dw::fltk::FltkImgbuf does it this way):
|
||||
*
|
||||
* <ul>
|
||||
* <li> If the method is called with an already scaled image buffer, this is
|
||||
* delegated to the root buffer.
|
||||
*
|
||||
* <li> If the given size is the original size, the root buffer is
|
||||
* returned, with an increased reference counter.
|
||||
*
|
||||
* <li> Otherwise, if this buffer has already been scaled to the given
|
||||
* size, return this scaled buffer, with an increased reference
|
||||
* counter.
|
||||
*
|
||||
* <li> Otherwise, return a new scaled buffer with reference counter 1.
|
||||
* </ul>
|
||||
*
|
||||
* Special care is to be taken, when the root buffer is not used anymore,
|
||||
* i.e. after dw::core::Imgbuf::unref the reference counter is 0, but there
|
||||
* are still scaled buffers. Since all methods operating on the image data
|
||||
* (dw::core::Imgbuf::copyRow and dw::core::Imgbuf::setCMap) are called for
|
||||
* the root buffer, the root buffer is still needed, and so must not be
|
||||
* deleted at this point. This is, how dw::fltk::FltkImgbuf solves this
|
||||
* problem:
|
||||
*
|
||||
* <ul>
|
||||
* <li> dw::fltk::FltkImgbuf::unref does, for root buffers, check, not only
|
||||
* whether dw::fltk::FltkImgbuf::refCount is 0, but also, whether
|
||||
* there are children left. When the latter is the case, the buffer
|
||||
* is not deleted.
|
||||
*
|
||||
* <li> There is an additional check in dw::fltk::FltkImgbuf::detachScaledBuf,
|
||||
* which deals with the case, that dw::fltk::FltkImgbuf::refCount is 0,
|
||||
* and the last scaled buffer is removed.
|
||||
* </ul>
|
||||
*
|
||||
* In the following example:
|
||||
*
|
||||
* \code
|
||||
* dw::fltk::FltkPlatform *platform = new dw::fltk::FltkPlatform ();
|
||||
* dw::core::Layout *layout = new dw::core::Layout (platform);
|
||||
*
|
||||
* dw::core::Imgbuf *rootbuf =
|
||||
* layout->createImgbuf (dw::core::Imgbuf::RGB, 100, 100);
|
||||
* dw::core::Imgbuf *scaledbuf = rootbuf->getScaledBuf (50, 50);
|
||||
* rootbuf->unref ();
|
||||
* scaledbuf->unref ();
|
||||
* \endcode
|
||||
*
|
||||
* the root buffer is not deleted, when dw::core::Imgbuf::unref is called,
|
||||
* since a scaled buffer is left. After calling dw::core::Imgbuf::unref for
|
||||
* the scaled buffer, it is deleted, and after it, the root buffer.
|
||||
*
|
||||
* <h3>Drawing</h3>
|
||||
*
|
||||
* dw::core::Imgbuf provides no methods for drawing, instead, this is
|
||||
* done by the views (implementation of dw::core::View).
|
||||
*
|
||||
* There are two situations, when drawing is necessary:
|
||||
*
|
||||
* <ol>
|
||||
* <li> To react on expose events, the function dw::core::View::drawImage
|
||||
* should be used, with the following parameters:
|
||||
* <ul>
|
||||
* <li> of course, the image buffer,
|
||||
* <li> where the root of the image would be displayed (as \em xRoot
|
||||
* and \em yRoot), and
|
||||
* <li> the region within the image, which should be displayed (\em x,
|
||||
* \em y, \em width, \em height).
|
||||
* </ul>
|
||||
*
|
||||
* <li> When a row has been copied, it has to be drawn. To determine the
|
||||
* area, which has to be drawn, the dw::core::Imgbuf::getRowArea
|
||||
* should be used. The result can then passed
|
||||
* to dw::core::View::drawImage.
|
||||
* </ol>
|
||||
*
|
||||
* \sa \ref dw-images-and-backgrounds
|
||||
*/
|
||||
class Imgbuf: public lout::object::Object, public lout::signal::ObservedObject
|
||||
{
|
||||
public:
|
||||
enum Type { RGB, RGBA, GRAY, INDEXED, INDEXED_ALPHA };
|
||||
|
||||
inline Imgbuf () {
|
||||
DBG_OBJ_CREATE ("dw::core::Imgbuf");
|
||||
DBG_OBJ_BASECLASS (lout::object::Object);
|
||||
DBG_OBJ_BASECLASS (lout::signal::ObservedObject);
|
||||
}
|
||||
|
||||
inline ~Imgbuf () {
|
||||
DBG_OBJ_DELETE ();
|
||||
}
|
||||
|
||||
/*
|
||||
* Methods called from the image decoding
|
||||
*/
|
||||
|
||||
virtual void setCMap (int *colors, int num_colors) = 0;
|
||||
virtual void copyRow (int row, const byte *data) = 0;
|
||||
virtual void newScan () = 0;
|
||||
|
||||
/*
|
||||
* Methods called from dw::Image
|
||||
*/
|
||||
|
||||
virtual Imgbuf* getScaledBuf (int width, int height) = 0;
|
||||
virtual void getRowArea (int row, dw::core::Rectangle *area) = 0;
|
||||
virtual int getRootWidth () = 0;
|
||||
virtual int getRootHeight () = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Creates an image buffer with same parameters (type, gamma etc.)
|
||||
* except size.
|
||||
*/
|
||||
virtual Imgbuf *createSimilarBuf (int width, int height) = 0;
|
||||
|
||||
/**
|
||||
* Copies another image buffer into this image buffer.
|
||||
*/
|
||||
virtual void copyTo (Imgbuf *dest, int xDestRoot, int yDestRoot,
|
||||
int xSrc, int ySrc, int widthSrc, int heightSrc) = 0;
|
||||
|
||||
/*
|
||||
* Reference counting.
|
||||
*/
|
||||
|
||||
virtual void ref () = 0;
|
||||
virtual void unref () = 0;
|
||||
|
||||
/**
|
||||
* \todo Comment
|
||||
*/
|
||||
virtual bool lastReference () = 0;
|
||||
|
||||
|
||||
/**
|
||||
* \todo Comment
|
||||
*/
|
||||
virtual void setDeleteOnUnref (bool deleteOnUnref) = 0;
|
||||
|
||||
/**
|
||||
* \todo Comment
|
||||
*/
|
||||
virtual bool isReferred () = 0;
|
||||
};
|
||||
|
||||
} // namespace core
|
||||
} // namespace dw
|
||||
|
||||
#endif // __DW_IMGBUF_HH__
|
Reference in New Issue
Block a user