]> git.saurik.com Git - wxWidgets.git/commitdiff
new template-based more flexible and hopefully more efficient raw bitmap implementation
authorVadim Zeitlin <vadim@wxwidgets.org>
Mon, 28 Apr 2003 01:46:05 +0000 (01:46 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Mon, 28 Apr 2003 01:46:05 +0000 (01:46 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@20363 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/msw/bitmap.h
include/wx/rawbmp.h
src/msw/bitmap.cpp
src/msw/dc.cpp

index 75efef8d651780e0395a8e9a1ac879973f3cdbdc..c545d275ec321b5bf78d9bf0e08a75d39b3ce2d0 100644 (file)
@@ -31,7 +31,7 @@ class WXDLLEXPORT wxIcon;
 class WXDLLEXPORT wxImage;
 class WXDLLEXPORT wxMask;
 class WXDLLEXPORT wxPalette;
-class WXDLLEXPORT wxRawBitmapData;
+class WXDLLEXPORT wxPixelDataBase;
 
 // ----------------------------------------------------------------------------
 // wxBitmap: a mono or colour bitmap
@@ -132,8 +132,8 @@ public:
         { return (wxBitmapRefData *)m_refData; }
 
     // raw bitmap access support functions
-    bool GetRawData(wxRawBitmapData *data);
-    void UngetRawData(wxRawBitmapData *);
+    void *GetRawData(wxPixelDataBase& data, int bpp);
+    void UngetRawData(wxPixelDataBase& data);
 
 #if wxUSE_PALETTE
     wxPalette* GetPalette() const;
index 4edd08843c2654dcfbad108f9cd08a097788ad6b..7967318a03c29ebce2a66b4ce0f3a643c1c642d8 100644 (file)
 /*
    Usage example:
 
+    typedef wxPixelData<wxBitmap, wxNativePixelFormat> PixelData;
+
     wxBitmap bmp;
-    wxRawBitmapData data(bitmap);
+    PixelData data(bmp);
     if ( !data )
     {
         ... raw access to bitmap data unavailable, do something else ...
         return;
     }
 
-    if ( data.m_width < 20 || data.m_height < 20 )
+    if ( data.GetWidth() < 20 || data.GetHeight() < 20 )
     {
         ... complain: the bitmap it too small ...
         return;
     }
 
-    wxRawBitmapIterator p(data);
+    PixelData::Iterator p(data);
 
     // we draw a (10, 10)-(20, 20) rect manually using the given r, g, b
-    p.Offset(10, 10);
+    p.Offset(data, 10, 10);
 
     for ( int y = 0; y < 10; ++y )
     {
-        wxRawBitmapIterator rowStart = p;
+        PixelData::Iterator rowStart = p;
 
         for ( int x = 0; x < 10; ++x, ++p )
         {
         }
 
         p = rowStart;
-        p.OffsetY(1);
+        p.OffsetY(data, 1);
     }
  */
 
-// this struct represents a pointer to raw bitmap data
-class wxRawBitmapData
+#ifdef __VISUALC__
+    // VC++ gives an absolutely harmless warning for wxPixelData<wxBitmap> ctor
+    #pragma warning(disable: 4355) // 'this' used in initializer list
+#endif
+
+// ----------------------------------------------------------------------------
+// wxPixelFormat
+// ----------------------------------------------------------------------------
+
+/*
+    wxPixelFormat is a template class describing the bitmap data format. It
+    contains the constants describing the format of pixel data, but does not
+    describe how the entire bitmap is stored (i.e. top-to-bottom,
+    bottom-to-top, ...). It is also a "traits"-like class, i.e. it only
+    contains some constants and maybe static methods but nothing more, so it
+    can be safely used without incurring any overhead as all accesses to it are
+    done at compile-time.
+
+    Current limitations: we don't support RAGABA and ARAGAB formats supported
+    by Mac OS X. If there is sufficient interest, these classes could be
+    extended to deal with them. Neither do we support alpha channel having
+    different representation from the RGB ones (happens under QNX/Photon I
+    think), but again this could be achieved with some small extra effort.
+
+    Template parameters are:
+        - type of a single pixel component
+        - size of the single pixel in bits
+        - indices of red, green and blue pixel components inside the pixel
+        - index of the alpha component or -1 if none
+        - type which can contain the full pixel value (all channels)
+ */
+template <typename Channel,
+          size_t Bpp, int R, int G, int B, int A = -1,
+          typename Pixel = wxUint32>
+struct WXDLLEXPORT wxPixelFormat
 {
-public:
-    // ctor associates this pointer with a bitmap and locks the bitmap for raw
-    // access, it will be unlocked only by our dtor and so these objects should
-    // normally be only created on the stack, i.e. have limited life-time
-    wxRawBitmapData(wxBitmap bmp) : m_bmp(bmp)
-    {
-        if ( !bmp.GetRawData(this) )
-            m_pixels = NULL;
-    }
+    // iterator over pixels is usually of type "ChannelType *"
+    typedef Channel ChannelType;
+
+    // the type which may hold the entire pixel value
+    typedef Pixel PixelType;
 
-    // we evaluate to true only if we could get access to bitmap data
-    // successfully
-    operator bool() const { return m_pixels != NULL; }
+    // NB: using static ints initialized inside the class declaration is not
+    //     portable as it doesn't work with VC++ 6, so we must use enums
 
-    // dtor unlocks the bitmap
-    ~wxRawBitmapData()
+    // size of one pixel in bits
+    enum { BitsPerPixel = Bpp };
+
+    // size of one pixel in ChannelType units (usually bytes)
+    enum { SizePixel = BitsPerPixel / (8 * sizeof(ChannelType)) };
+
+    // the channels indices inside the pixel
+    enum
     {
-        m_bmp.UngetRawData(this);
-    }
+        RED = R,
+        GREEN = G,
+        BLUE = B,
+        ALPHA = A
+    };
 
-    // call this to indicate that we should use the alpha channel
-    void UseAlpha() { m_bmp.UseAlpha(); }
+    // true if we have an alpha channel (together with the other channels, this
+    // doesn't cover the case of wxImage which stores alpha separately)
+    enum { HasAlpha = A != -1 };
+};
+
+// some "predefined" pixel formats
+// -------------------------------
+
+// wxImage format is common to all platforms
+typedef wxPixelFormat<unsigned char, 24, 0, 1, 2> wxImagePixelFormat;
+
+// the (most common) native bitmap format without alpha support
+typedef wxPixelFormat<unsigned char, 24,
+                      #ifdef __WXMSW__
+                                2, 1, 0
+                      #else // !__WXMSW__
+                                0, 1, 2
+                      #endif // __WXMSW__/!__WXMSW__
+                     > wxNativePixelFormat;
+
+// the (most common) native format for bitmaps with alpha channel
+typedef wxPixelFormat<unsigned char, 32,
+                      wxNativePixelFormat::RED,
+                      wxNativePixelFormat::GREEN,
+                      wxNativePixelFormat::BLUE,
+                      3> wxAlphaPixelFormat;
+
+// we also define the (default/best) pixel format for the given class: this is
+// used as default value for the pixel format in wxPixelIterator template
+template <class T> struct wxPixelFormatFor;
+
+// wxPixelFormatFor is only defined for wxImage, attempt to use it with other
+// classes (wxBitmap...) will result in compile errors which is exactly what we
+// want
+template <>
+struct WXDLLEXPORT wxPixelFormatFor<wxImage>
+{
+    typedef wxImagePixelFormat Format;
+};
+
+// ----------------------------------------------------------------------------
+// wxPixelData
+// ----------------------------------------------------------------------------
 
-    // accessors
-    unsigned char *GetPixels() const { return m_pixels; }
+/*
+    wxPixelDataBase is just a helper for wxPixelData: it contains things common
+    to both wxImage and wxBitmap specializations.
+ */
+class WXDLLEXPORT wxPixelDataBase
+{
+public:
     int GetWidth() const { return m_width; }
     int GetHeight() const { return m_height; }
-    int GetByPP() const { return m_bypp; }
-    int GetBPP() const { return 8*GetByPP(); }
     int GetRowStride() const { return m_stride; }
 
-// private: -- public because accessed by the macros below but still mustn't be
-//             used directly
-
-    // the bitmap we're associated with
-    wxBitmap m_bmp;
-
-    // pointer to the start of the data
-    unsigned char *m_pixels;
+// private: -- see comment in the beginning of the file
 
     // the size of the image we address, in pixels
     int m_width,
         m_height;
 
-    // number of bytes (NOT bits) per pixel, including alpha channel if any
-    int m_bypp;
-
     // this parameter is the offset of the start of the (N+1)st row from the
     // Nth one and can be different from m_bypp*width in some cases:
     //  a) the most usual one is to force 32/64 bit alignment of rows
@@ -124,139 +197,406 @@ public:
     //  c) finally, it could conceivably be 0 for the images with all
     //     lines being identical
     int m_stride;
-};
-
-// this is the type for the iterator over raw bitmap data
-class wxRawBitmapIterator
-{
-public:
-    // ctors and such
-    // --------------
 
-    // we must be associated/initialized with some bitmap data object
-    wxRawBitmapIterator(const wxRawBitmapData& data) : m_data(&data)
+protected:
+    // ctor is protected because this class is only meant to be used as the
+    // base class by wxPixelData
+    wxPixelDataBase()
     {
-        m_ptr = m_data->GetPixels();
-    }
-
-    // default copy ctor, assignment operator and dtor are ok
-
-
-    // navigation
-    // ----------
-
-    // move x pixels to the right and y down
-    //
-    // note that the rows don't wrap!
-    void Offset(int x, int y)
-    {
-        m_ptr += m_data->GetRowStride()*y + m_data->GetByPP()*x;
+        m_width =
+        m_height =
+        m_stride = 0;
     }
+};
 
-    // move x pixels to the right (again, no row wrapping)
-    void OffsetX(int x)
-    {
-        m_ptr += m_data->GetByPP()*x;
-    }
+/*
+    wxPixelData represents the entire bitmap data, i.e. unlike
+    wxPixelFormat (which it uses) it also stores the global bitmap
+    characteristics such as its size, inter-row separation and so on.
+
+    Because of this it can be used to move the pixel iterators (which don't
+    have enough information about the bitmap themselves). This may seem a bit
+    unnatural but must be done in this way to keep the iterator objects as
+    small as possible for maximum efficiency as otherwise they wouldn't be put
+    into the CPU registers by the compiler any more.
+
+    Implementation note: we use the standard workaround for lack of partial
+    template specialization support in VC (both 6 and 7): instead of partly
+    specializing the class Foo<T, U> for some T we introduce FooOut<T> and
+    FooIn<U> nested in it, make Foo<T, U> equivalent to FooOut<T>::FooIn<U> and
+    fully specialize FooOut.
+
+    Also note that this class doesn't have any default definition because we
+    can't really do anything without knowing the exact image class. We do
+    provide wxPixelDataBase to make it simpler to write new wxPixelData
+    specializations.
+ */
 
-    // move y rows to the bottom
-    void OffsetY(int y)
+// we need to define this skeleton template to mollify VC++
+template <class Image>
+struct WXDLLEXPORT wxPixelDataOut
+{
+    template <class PixelFormat>
+    class WXDLLEXPORT wxPixelDataIn
     {
-        m_ptr += m_data->GetRowStride()*y;
-    }
+    public:
+        class Iterator { };
+    };
+};
 
-    // go back to (0, 0)
-    void Reset()
+// wxPixelData specialization for wxImage: this is the simplest case as we
+// don't have to care about different pixel formats here
+template <>
+struct WXDLLEXPORT wxPixelDataOut<wxImage>
+{
+    // NB: this is a template class even though it doesn't use its template
+    //     parameter because otherwise wxPixelData couldn't compile
+    template <class PixelFormat>
+    class WXDLLEXPORT wxPixelDataIn : public wxPixelDataBase
     {
-        m_ptr = m_data->GetPixels();
-    }
+        // the type of the class we're working with
+        typedef wxImage ImageType;
 
-    // go to the given position
-    void MoveTo(int x, int y)
-    {
-        Reset();
-        Offset(x, y);
-    }
+        // the iterator which should be used for working with data in this
+        // format
+        class Iterator
+        {
+        public:
+            // the pixel format we use
+            typedef wxImagePixelFormat PixelFormat;
+
+            // the type of the pixel components
+            typedef typename PixelFormat::ChannelType ChannelType;
+
+            // the pixel data we're working with
+            typedef
+                wxPixelDataOut<wxImage>::wxPixelDataIn<PixelFormat> PixelData;
+
+            // go back to (0, 0)
+            void Reset(const PixelData& data)
+            {
+                *this = data.GetPixels();
+            }
+
+            // creates the iterator pointing to the beginning of data
+            Iterator(PixelData& data)
+            {
+                Reset(data);
+            }
+
+            // creates the iterator initially pointing to the image origin
+            Iterator(const wxImage& image)
+            {
+                m_pRGB = image.GetData();
+
+                if ( image.HasAlpha() )
+                {
+                    m_pAlpha = image.GetAlpha();
+                }
+                else // alpha is not used at all
+                {
+                    m_pAlpha = NULL;
+                }
+            }
+
+            // true if the iterator is valid
+            bool IsOk() const { return m_pRGB != NULL; }
+
+
+            // navigation
+            // ----------
+
+            // advance the iterator to the next pixel, prefix version
+            Iterator& operator++()
+            {
+                m_pRGB += PixelFormat::SizePixel;
+                if ( m_pAlpha )
+                    m_pAlpha += PixelFormat::SizePixel;
+
+                return *this;
+            }
+
+            // postfix (hence less efficient -- don't use unless you must) version
+            Iterator operator++(int)
+            {
+                Iterator p(*this);
+                ++*this;
+                return p;
+            }
+
+            // move x pixels to the right and y down
+            //
+            // note that the rows don't wrap!
+            void Offset(const PixelData& data, int x, int y)
+            {
+                m_pRGB += data.GetRowStride()*y + PixelFormat::SizePixel*x;
+                if ( m_pAlpha )
+                    m_pAlpha += data.GetWidth() + x;
+            }
+
+            // move x pixels to the right (again, no row wrapping)
+            void OffsetX(const PixelData& WXUNUSED(data), int x)
+            {
+                m_pRGB += PixelFormat::SizePixel*x;
+                if ( m_pAlpha )
+                    m_pAlpha += x;
+            }
+
+            // move y rows to the bottom
+            void OffsetY(const PixelData& data, int y)
+            {
+                m_pRGB += data.GetRowStride()*y;
+                if ( m_pAlpha )
+                    m_pAlpha += data.GetWidth();
+            }
+
+            // go to the given position
+            void MoveTo(const PixelData& data, int x, int y)
+            {
+                Reset(data);
+                Offset(data, x, y);
+            }
+
+
+            // data access
+            // -----------
+
+            // access to invidividual colour components
+            ChannelType& Red() { return m_ptr[PixelFormat::RED]; }
+            ChannelType& Green() { return m_ptr[PixelFormat::GREEN]; }
+            ChannelType& Blue() { return m_ptr[PixelFormat::BLUE]; }
+            ChannelType& Alpha() { return *m_pAlpha; }
+
+        // private: -- see comment in the beginning of the file
+
+            // pointer into RGB buffer
+            unsigned char *m_pRGB;
+
+            // pointer into alpha buffer or NULL if alpha isn't used
+            unsigned char *m_pAlpha;
+        };
+
+        // initializes us with the data of the given image
+        wxPixelDataIn(ImageType& image) : m_image(image), m_pixels(image)
+        {
+            m_width = image.GetWidth();
+            m_height = image.GetHeight();
+            m_stride = Iterator::SizePixel * m_width;
+        }
 
-    // same as OffsetX(1) for convenience
-    wxRawBitmapIterator& operator++()
-    {
-        OffsetX(1);
-        return *this;
-    }
+        // we evaluate to true only if we could get access to bitmap data
+        // successfully
+        operator bool() const { return m_pixels.IsOk(); }
 
-    // postfix (hence less efficient) version
-    wxRawBitmapIterator operator++(int)
-    {
-        wxRawBitmapIterator p(*this);
-        OffsetX(1);
-        return p;
-    }
+        // get the iterator pointing to the origin
+        Iterator GetPixels() const { return m_pixels; }
 
-    // data access
-    // -----------
+    private:
+        // the image we're working with
+        ImageType& m_image;
 
-    // DIBs store data in BGR format, i.e. "little endian" RGB
-    enum
-    {
-#ifdef __WXMSW__
-        BLUE, GREEN, RED,
-#else // !__WXMSW__
-        RED, GREEN, BLUE,
-#endif // __WXMSW__/!__WXMSW__
-        ALPHA
+        // the iterator pointing to the image origin
+        Iterator m_pixels;
     };
+};
 
-    // access to invidividual colour components
-    unsigned char& Red() { return m_ptr[RED]; }
-    unsigned char& Green() { return m_ptr[GREEN]; }
-    unsigned char& Blue() { return m_ptr[BLUE]; }
-    unsigned char& Alpha() { return m_ptr[ALPHA]; }
-
-    // address the pixel contents directly
-    //
-    // warning: the format is platform dependent
-    wxUint32& Data() { return *(wxUint32 *)m_ptr; }
+// wxPixelData specialization for wxBitmap: here things are more interesting as
+// we also have to support different pixel formats
+template <>
+struct WXDLLEXPORT wxPixelDataOut<wxBitmap>
+{
+    template <class Format>
+    class WXDLLEXPORT wxPixelDataIn : public wxPixelDataBase
+    {
+    public:
+        // the type of the class we're working with
+        typedef wxBitmap ImageType;
 
-// private: -- don't access these fields directly, same as as above
-    unsigned char *m_ptr;
+        class Iterator
+        {
+        public:
+            // the pixel format we use
+            typedef Format PixelFormat;
+
+            // the type of the pixel components
+            typedef typename PixelFormat::ChannelType ChannelType;
+
+            // the pixel data we're working with
+            typedef wxPixelDataOut<wxBitmap>::wxPixelDataIn<Format> PixelData;
+
+
+            // go back to (0, 0)
+            void Reset(const PixelData& data)
+            {
+                *this = data.GetPixels();
+            }
+
+            // initializes the iterator to point to the origin of the given pixel
+            // data
+            Iterator(PixelData& data)
+            {
+                Reset(data);
+            }
+
+            // initializes the iterator to point to the origin of the given bitmap
+            Iterator(wxBitmap& bmp, PixelData& data)
+            {
+                // using cast here is ugly but it should be safe as GetRawData()
+                // real return type should be consistent with BitsPerPixel (which
+                // is in turn defined by ChannelType) and this is the only thing we
+                // can do without making GetRawData() a template function which is
+                // undesirable
+                m_ptr = (ChannelType *)
+                            bmp.GetRawData(data, PixelFormat::BitsPerPixel);
+            }
+
+            // return true if this iterator is valid
+            bool IsOk() const { return m_ptr != NULL; }
+
+
+            // navigation
+            // ----------
+
+            // advance the iterator to the next pixel, prefix version
+            Iterator& operator++()
+            {
+                m_ptr += PixelFormat::SizePixel;
+
+                return *this;
+            }
+
+            // postfix (hence less efficient -- don't use unless you must) version
+            Iterator operator++(int)
+            {
+                Iterator p(*this);
+                ++*this;
+                return p;
+            }
+
+            // move x pixels to the right and y down
+            //
+            // note that the rows don't wrap!
+            void Offset(const PixelData& data, int x, int y)
+            {
+                m_ptr += data.GetRowStride()*y + PixelFormat::SizePixel*x;
+            }
+
+            // move x pixels to the right (again, no row wrapping)
+            void OffsetX(const PixelData& WXUNUSED(data), int x)
+            {
+                m_ptr += PixelFormat::SizePixel*x;
+            }
+
+            // move y rows to the bottom
+            void OffsetY(const PixelData& data, int y)
+            {
+                m_ptr += data.GetRowStride()*y;
+            }
+
+            // go to the given position
+            void MoveTo(const PixelData& data, int x, int y)
+            {
+                Reset(data);
+                Offset(data, x, y);
+            }
+
+
+            // data access
+            // -----------
+
+            // access to invidividual colour components
+            ChannelType& Red() { return m_ptr[PixelFormat::RED]; }
+            ChannelType& Green() { return m_ptr[PixelFormat::GREEN]; }
+            ChannelType& Blue() { return m_ptr[PixelFormat::BLUE]; }
+            ChannelType& Alpha() { return m_ptr[PixelFormat::ALPHA]; }
+
+            // address the pixel contents directly
+            //
+            // warning: the format is platform dependent
+            typename PixelFormat::PixelType& Data()
+                { return *(typename PixelFormat::PixelType *)m_ptr; }
+
+        // private: -- see comment in the beginning of the file
+
+            // NB: for efficiency reasons this class must *not* have any other
+            //     fields, otherwise it won't be put into a CPU register (as it
+            //     should inside the inner loops) by some compilers, notably gcc
+            ChannelType *m_ptr;
+        };
+
+        // ctor associates this pointer with a bitmap and locks the bitmap for raw
+        // access, it will be unlocked only by our dtor and so these objects should
+        // normally be only created on the stack, i.e. have limited life-time
+        wxPixelDataIn(wxBitmap bmp) : m_bmp(bmp), m_pixels(bmp, *this)
+        {
+        }
 
-    const wxRawBitmapData *m_data;
-};
+        // we evaluate to true only if we could get access to bitmap data
+        // successfully
+        operator bool() const { return m_pixels.IsOk(); }
 
+        // get the iterator pointing to the origin
+        Iterator GetPixels() const { return m_pixels; }
 
-// these macros are used to change the current location in the bitmap
-// ------------------------------------------------------------------
+        // dtor unlocks the bitmap
+        ~wxPixelDataIn()
+        {
+            m_bmp.UngetRawData(*this);
+        }
 
-// move x pixels to the right and y down
-//
-// note that the rows don't wrap!
-#define wxBMP_OFFSET(p, x, y) \
-    p.m_ptr += p.m_data->m_stride * (y) + p.m_data->m_bypp * (x)
+        // call this to indicate that we should use the alpha channel
+        void UseAlpha() { m_bmp.UseAlpha(); }
 
-// move x pixels to the right (again, no row wrapping)
-#define wxBMP_OFFSET_X(p, x) p.m_ptr += p.m_data->m_bypp * (x)
+    // private: -- see comment in the beginning of the file
 
-// move y rows to the bottom
-#define wxBMP_OFFSET_Y(p, y) p.m_ptr += p.m_data->m_stride * (y)
+        // the bitmap we're associated with
+        wxBitmap m_bmp;
 
+        // the iterator pointing to the image origin
+        Iterator m_pixels;
+    };
+};
 
+template <class Image, class PixelFormat = wxPixelFormatFor<Image> >
+class wxPixelData :
+    public wxPixelDataOut<Image>::template wxPixelDataIn<PixelFormat>
+{
+public:
+    wxPixelData(const Image& image)
+        : wxPixelDataOut<Image>::template wxPixelDataIn<PixelFormat>(image)
+        {
+        }
+};
 
-// these macros are used to work with the pixel values
-//
-// all of them can be used as either lvalues or rvalues.
-// ----------------------------------------------------
+// some "predefined" pixel data classes
+typedef wxPixelData<wxImage> wxImagePixelData;
+typedef wxPixelData<wxBitmap, wxNativePixelFormat> wxNativePixelData;
+typedef wxPixelData<wxBitmap, wxAlphaPixelFormat> wxAlphaPixelData;
 
-#define wxBMP_RED(p)         (p.m_ptr[wxRawBitmapIterator::RED])
-#define wxBMP_GREEN(p)       (p.m_ptr[wxRawBitmapIterator::GREEN])
-#define wxBMP_BLUE(p)        (p.m_ptr[wxRawBitmapIterator::BLUE])
+// ----------------------------------------------------------------------------
+// wxPixelIterator
+// ----------------------------------------------------------------------------
 
-#define wxBMP_ALPHA(p)       (p.m_ptr[wxRawBitmapIterator::ALPHA])
+/*
+    wxPixel::Iterator represents something which points to the pixel data and
+    allows us to iterate over it. In the simplest case of wxBitmap it is,
+    indeed, just a pointer, but it can be something more complicated and,
+    moreover, you are free to specialize it for other image classes and bitmap
+    formats.
+
+    Note that although it would have been much more intuitive to have a real
+    class here instead of what we have now, this class would need two template
+    parameters, and this can't be done because we'd need compiler support for
+    partial template specialization then and neither VC6 nor VC7 provide it.
+ */
+template < class Image, class PixelFormat = wxPixelFormatFor<Image> >
+struct WXDLLEXPORT wxPixelIterator : wxPixelData<Image, PixelFormat>::Iterator
+{
+};
 
-// these macros are most efficient but return the buffer contents in
-// platform-specific format, e.g. RGB on all sane platforms and BGR under Win32
-#define wxBMP_RGB(p)     *(wxUint32 *)(p.m_ptr)
-#define wxBMP_RGBA(p)    *(wxUint32 *)(p.m_ptr)
+#ifdef __VISUALC__
+    #pragma warning(default: 4355)
+#endif
 
 #endif // _WX_RAWBMP_H_BASE_
 
index b34424a5fe1410cace71e3aa86fa0c28755b0f26..1cccec198089ee1684bf88972a2df262a3bbfa3f 100644 (file)
@@ -1185,14 +1185,12 @@ void wxBitmap::SetQuality(int WXUNUSED(quality))
 // raw bitmap access support
 // ----------------------------------------------------------------------------
 
-bool wxBitmap::GetRawData(wxRawBitmapData *data)
+void *wxBitmap::GetRawData(wxPixelDataBase& data, int bpp)
 {
-    wxCHECK_MSG( data, FALSE, _T("NULL pointer in wxBitmap::GetRawData") );
-
     if ( !Ok() )
     {
         // no bitmap, no data (raw or otherwise)
-        return FALSE;
+        return NULL;
     }
 
     // if we're already a DIB we can access our data directly, but if not we
@@ -1209,7 +1207,7 @@ bool wxBitmap::GetRawData(wxRawBitmapData *data)
         {
             delete dib;
 
-            return FALSE;
+            return NULL;
         }
 
         // we'll free it in UngetRawData()
@@ -1227,79 +1225,94 @@ bool wxBitmap::GetRawData(wxRawBitmapData *data)
     {
         wxFAIL_MSG( _T("failed to get DIBSECTION from a DIB?") );
 
-        return FALSE;
+        return NULL;
+    }
+
+    // check that the bitmap is in correct format
+    if ( ds.dsBm.bmBitsPixel != bpp )
+    {
+        wxFAIL_MSG( _T("incorrect bitmap type in wxBitmap::GetRawData()") );
+
+        return NULL;
     }
 
-    // ok, store the relevant info in wxRawBitmapData
+    // ok, store the relevant info in wxPixelDataBase
     const LONG h = ds.dsBm.bmHeight;
 
-    data->m_width = ds.dsBm.bmWidth;
-    data->m_height = h;
-    data->m_bypp = ds.dsBm.bmBitsPixel / 8;
+    data.m_width = ds.dsBm.bmWidth;
+    data.m_height = h;
 
     // remember that DIBs are stored in top to bottom order!
     const LONG bytesPerRow = ds.dsBm.bmWidthBytes;
-    data->m_stride = -bytesPerRow;
-    data->m_pixels = (unsigned char *)ds.dsBm.bmBits;
+    data.m_stride = -bytesPerRow;
+
+    char *bits = (char *)ds.dsBm.bmBits;
     if ( h > 1 )
     {
-        data->m_pixels += (h - 1)*bytesPerRow;
+        bits += (h - 1)*bytesPerRow;
     }
 
-    return TRUE;
+    return bits;
 }
 
-void wxBitmap::UngetRawData(wxRawBitmapData *data)
+void wxBitmap::UngetRawData(wxPixelDataBase& dataBase)
 {
-    wxCHECK_RET( data, _T("NULL pointer in wxBitmap::UngetRawData()") );
-
     if ( !Ok() )
         return;
 
-    if ( !*data )
+    // the cast is ugly but we can't do without it and without making this
+    // function template (and hence inline) unfortunately
+    typedef wxPixelData<wxBitmap, wxAlphaPixelFormat> PixelData;
+    PixelData& data = (PixelData &)dataBase;
+
+    if ( !data )
     {
         // invalid data, don't crash -- but don't assert neither as we're
-        // called automatically from wxRawBitmapData dtor and so there is no
+        // called automatically from wxPixelDataBase dtor and so there is no
         // way to prevent this from happening
         return;
     }
 
-    // AlphaBlend() wants to have premultiplied source alpha but wxRawBitmap
-    // API uses normal, not premultiplied, colours, so adjust them here now
-    wxRawBitmapIterator p(*data);
-
-    const int w = data->GetWidth();
-    const int h = data->GetHeight();
-
-    for ( int y = 0; y < h; y++ )
+    if ( GetBitmapData()->m_hasAlpha )
     {
-        wxRawBitmapIterator rowStart = p;
+        // AlphaBlend() wants to have premultiplied source alpha but
+        // wxRawBitmap API uses normal, not premultiplied, colours, so adjust
+        // them here now
+        PixelData::Iterator p(data);
 
-        for ( int x = 0; x < w; x++ )
+        const int w = data.GetWidth();
+        const int h = data.GetHeight();
+
+        for ( int y = 0; y < h; y++ )
         {
-            const unsigned alpha = p.Alpha();
+            PixelData::Iterator rowStart = p;
 
-            p.Red() = (p.Red() * alpha + 127) / 255;
-            p.Blue() = (p.Blue() * alpha + 127) / 255;
-            p.Green() = (p.Green() * alpha + 127) / 255;
+            for ( int x = 0; x < w; x++ )
+            {
+                const unsigned alpha = p.Alpha();
 
-            ++p;
-        }
+                p.Red() = (p.Red() * alpha + 127) / 255;
+                p.Blue() = (p.Blue() * alpha + 127) / 255;
+                p.Green() = (p.Green() * alpha + 127) / 255;
 
-        p = rowStart;
-        p.OffsetY(1);
-    }
+                ++p;
+            }
 
-    // if we're a DDB we need to convert DIB back to DDB now to make the
-    // changes made via wxRawBitmapData effective
-    if ( !GetBitmapData()->m_isDIB )
-    {
-        wxDIB *dib = GetBitmapData()->m_dib;
-        GetBitmapData()->m_dib = NULL;
+            p = rowStart;
+            p.OffsetY(data, 1);
+        }
+
+        // if we're a DDB we need to convert DIB back to DDB now to make the
+        // changes made via raw bitmap access effective
+        if ( !GetBitmapData()->m_isDIB )
+        {
+            wxDIB *dib = GetBitmapData()->m_dib;
+            GetBitmapData()->m_dib = NULL;
 
-        // TODO: convert
+            // TODO: convert
 
-        delete dib;
+            delete dib;
+        }
     }
 }
 
index e44692390d80cecf56123bda38d33e10ace0bd60..ab9254627145ac8bdcfc4dec86b02d23501b879f 100644 (file)
@@ -2313,19 +2313,19 @@ wxAlphaBlend(wxDC& dc, int xDst, int yDst, int w, int h, const wxBitmap& bmpSrc)
     }
 
     // combine them with the source bitmap using alpha
-    wxRawBitmapData dataDst(bmpDst),
-                    dataSrc(bmpSrc);
+    wxAlphaPixelData dataDst(bmpDst),
+                     dataSrc(bmpSrc);
 
     wxCHECK_RET( dataDst && dataSrc,
                     _T("failed to get raw data in wxAlphaBlend") );
 
-    wxRawBitmapIterator pDst(dataDst),
-                        pSrc(dataSrc);
+    wxAlphaPixelData::Iterator pDst(dataDst),
+                               pSrc(dataSrc);
 
     for ( int y = 0; y < h; y++ )
     {
-        wxRawBitmapIterator pDstRowStart = pDst,
-                            pSrcRowStart = pSrc;
+        wxAlphaPixelData::Iterator pDstRowStart = pDst,
+                                   pSrcRowStart = pSrc;
 
         for ( int x = 0; x < w; x++ )
         {
@@ -2343,8 +2343,8 @@ wxAlphaBlend(wxDC& dc, int xDst, int yDst, int w, int h, const wxBitmap& bmpSrc)
 
         pDst = pDstRowStart;
         pSrc = pSrcRowStart;
-        pDst.OffsetY(1);
-        pSrc.OffsetY(1);
+        pDst.OffsetY(dataDst, 1);
+        pSrc.OffsetY(dataSrc, 1);
     }
 
     // and finally blit them back to the destination DC