diff options
Diffstat (limited to 'dw/imgbuf.hh')
-rw-r--r-- | dw/imgbuf.hh | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/dw/imgbuf.hh b/dw/imgbuf.hh new file mode 100644 index 00000000..8948bbef --- /dev/null +++ b/dw/imgbuf.hh @@ -0,0 +1,210 @@ +#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 + +namespace dw { +namespace core { + +using namespace lout; + +/** + * \brief The platform independant interface for image buffers. + * + * %Image buffers depend on the platform (see \ref dw-images-and-backgrounds), + * but have this general, platform independant 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, heigt, + * // ... + * 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 object::Object, public lout::signal::ObservedObject +{ +public: + enum Type { RGB, RGBA, GRAY, INDEXED, INDEXED_ALPHA }; + + /* + * 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; + + /* + * 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 dw +} // namespace core + +#endif // __DW_IMGBUF_HH__ |