aboutsummaryrefslogtreecommitdiff
path: root/dw/imgbuf.hh
diff options
context:
space:
mode:
Diffstat (limited to 'dw/imgbuf.hh')
-rw-r--r--dw/imgbuf.hh210
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__