root/src/tests/servers/app/drawing_modes/DrawingModes.cpp
#include <Application.h>
#include <Bitmap.h>
#include <View.h>
#include <Window.h>
#include <stdio.h>
#include <string.h>

//#define DUMP_BLENDING_RESULTS
#ifdef DUMP_BLENDING_RESULTS
#include <BitmapStream.h>
#include <File.h>
#include <TranslatorRoster.h>
#include <String.h>
#endif

uint32 kBitmapBits[] = {
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00111111,
        0x00777777, 0x00000000, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00111111,
        0x00777777, 0x00444444, 0x00000000, 0x00000000, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00000000, 0x00000000, 0x00bb0000, 0x00ffffff, 0x00000000,
        0x00444444, 0x00777777, 0x00111111, 0x00000000, 0x00000000, 0x00000000,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00000000, 0x00bb0000, 0x00ee0000, 0x00ee0000,
        0x00ff0000, 0x00ffffff, 0x00ee0000, 0x00111111, 0x00000000, 0x00000000,
        0x00000000, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00000000, 0x00bb0000, 0x00ee0000,
        0x00ee0000, 0x00ff0000, 0x00ffffff, 0x00ee0000, 0x00ee0000, 0x00ee0000,
        0x00000000, 0x00000000, 0x00000000, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00000000, 0x00bb0000,
        0x00ee0000, 0x00ee0000, 0x00ff0000, 0x00ffffff, 0x00ee0000, 0x00ee0000,
        0x00ee0000, 0x00cc0000, 0x00000000, 0x00000000, 0x00000000, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00000000,
        0x00bb0000, 0x00ee0000, 0x00ee0000, 0x00ff0000, 0x00ffffff, 0x00ee0000,
        0x00ee0000, 0x00ee0000, 0x00cc0000, 0x00990000, 0x00990000, 0x00000000,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00000000, 0x00ee0000, 0x00ee0000, 0x00ee0000, 0x00ffffff,
        0x00ee0000, 0x00ff0000, 0x00cc0000, 0x00cc0000, 0x00990000, 0x00bb0000,
        0x00880000, 0x00000000, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00000000, 0x00ee0000, 0x00ee0000, 0x00ee0000,
        0x00ffffff, 0x00ee0000, 0x00ff0000, 0x00cc0000, 0x00cc0000, 0x00990000,
        0x00bb0000, 0x00880000, 0x00000000, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00000000, 0x00ee0000, 0x00ee0000,
        0x00ee0000, 0x00ffffff, 0x00ee0000, 0x00ff0000, 0x00cc0000, 0x00cc0000,
        0x00990000, 0x00bb0000, 0x00880000, 0x00990000, 0x00000000, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00000000, 0x00ee0000,
        0x00ee0000, 0x00ee0000, 0x00ffffff, 0x00ee0000, 0x00ff0000, 0x00cc0000,
        0x00cc0000, 0x00990000, 0x00bb0000, 0x00880000, 0x00990000, 0x00000000,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00000000, 0x00ee0000, 0x00ff0000, 0x00ffffff, 0x00ee0000, 0x00ee0000,
        0x00ee0000, 0x00cc0000, 0x00990000, 0x00bb0000, 0x00880000, 0x00880000,
        0x00000000, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00000000, 0x00ee0000, 0x00ee0000, 0x00ffffff, 0x00ee0000,
        0x00ff0000, 0x00cc0000, 0x00cc0000, 0x00990000, 0x00bb0000, 0x00880000,
        0x00990000, 0x00000000, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00ee0000, 0x00ffffff,
        0x00ee0000, 0x00ff0000, 0x00cc0000, 0x00cc0000, 0x00990000, 0x00bb0000,
        0x00880000, 0x00000000, 0x00000000, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00000000, 0x00ff6666,
        0x00ff6666, 0x00ff6666, 0x00ff6666, 0x00880000, 0x00000000, 0x00ee0000,
        0x00ff6666, 0x00000000, 0x00ee0000, 0x00ee0000, 0x00bb0000, 0x00bb0000,
        0x00bb0000, 0x00880000, 0x00000000, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00000000,
        0x00ee0000, 0x00ff0000, 0x00ee0000, 0x00880000, 0x00990000, 0x00000000,
        0x00ee0000, 0x00ff6666, 0x00880000, 0x00000000, 0x00cc0000, 0x00990000,
        0x00bb0000, 0x00880000, 0x00990000, 0x00000000, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00000000, 0x00ee0000, 0x00ff0000, 0x00ee0000, 0x00880000, 0x00990000,
        0x00000000, 0x00ee0000, 0x00ff6666, 0x00880000, 0x00000000, 0x00990000,
        0x00880000, 0x00880000, 0x00990000, 0x00000000, 0x00000000, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00ff6666, 0x00880000, 0x00000000,
        0x00990000, 0x00880000, 0x00880000, 0x00000000, 0x00000000, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00000000, 0x00444444, 0x00ff6666, 0x00880000,
        0x00000000, 0x00990000, 0x00880000, 0x00880000, 0x00000000, 0x00ee0000,
        0x00000000, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777777, 0x00777777,
        0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00000000, 0x00ff6666,
        0x00880000, 0x00000000, 0x00000000, 0x00000000, 0x00990000, 0x00000000,
        0x00880000, 0x00ee0000, 0x00000000, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
        0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00000000, 0x00000000,
        0x00ff9900, 0x00000000, 0x00000000, 0x00000000, 0x00444444, 0x00000000,
        0x00000000, 0x00880000, 0x00990000, 0x00ee0000, 0x00000000, 0x00777477,
        0x00777477, 0x00777477, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
        0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
        0x00777777, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00000000,
        0x00ff9900, 0x00ff9900, 0x00ffff00, 0x00ffff00, 0x00ffff00, 0x00000000,
        0x00444444, 0x00000000, 0x00000000, 0x00880000, 0x00ff0000, 0x00ee0000,
        0x00000000, 0x00777477, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
        0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
        0x00777777, 0x00777777, 0x00777777, 0x00777477, 0x00777477, 0x00777477,
        0x00000000, 0x00ff9900, 0x00ff9900, 0x00ffff00, 0x00ffff00, 0x00ffff00,
        0x00ff9900, 0x00000000, 0x00000000, 0x00777477, 0x00000000, 0x00ee0000,
        0x00ff0000, 0x00880000, 0x00000000, 0x00777477, 0x00777777, 0x00777777,
        0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
        0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00000000, 0x00ff9900, 0x00ff9900, 0x00ffff00,
        0x00ffff00, 0x00ff9900, 0x00000000, 0x00777777, 0x00777777, 0x00777777,
        0x00000000, 0x00ee0000, 0x00990000, 0x00000000, 0x00777777, 0x00777777,
        0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
        0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00000000, 0x00ff9900, 0x00ff9900,
        0x00ffff00, 0x00ff9900, 0x00ff9900, 0x00ff9900, 0x00000000, 0x00777777,
        0x00777777, 0x00777777, 0x00000000, 0x00880000, 0x00000000, 0x00777777,
        0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
        0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00000000,
        0x00ff9900, 0x00ffff00, 0x00ff9900, 0x00ff9900, 0x00ff9900, 0x00000000,
        0x00777477, 0x00777477, 0x00777477, 0x00777777, 0x00000000, 0x00000000,
        0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
        0x00777777, 0x00777777, 0x00777777, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00000000, 0x00ff9900, 0x00ffff00, 0x00ff9900, 0x00ff9900, 0x00000000,
        0x00000000, 0x00777477, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
        0x00000000, 0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
        0x00777777, 0x00777777, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00000000, 0x00ffff00, 0x00ff9900, 0x00000000,
        0x00000000, 0x00777477, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
        0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
        0x00777777, 0x00777777, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00000000, 0x00000000,
        0x00000000, 0x00777477, 0x00777477, 0x00777777, 0x00777777, 0x00777777,
        0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
        0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777777, 0x00777777, 0x00777777,
        0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777477,
        0x00777477, 0x00777477, 0x00777777, 0x00777777, 0x00777777, 0x00777777,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777777, 0x00777777, 0x00777777,
        0x00777777, 0x00777777, 0x00777777, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777777, 0x00777777,
        0x00777777, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
        0x00777477, 0x00777477, 0x00777477, 0x00777477
};

class DrawingModeView : public BView {
public:
                                                        DrawingModeView(BRect frame);
virtual                                         ~DrawingModeView();

virtual void                            Draw(BRect updateRect);

private:
                BBitmap *                       fBitmap;
                BBitmap *                       fTriangleLeft;
                BBitmap *                       fTriangleRight;
};


class DrawingModeWindow : public BWindow {
public:
                                                        DrawingModeWindow(BRect frame);

private:
                DrawingModeView *       fView;
};


class DrawingModeApp : public BApplication {
public:
                                                        DrawingModeApp();

private:
                DrawingModeWindow *     fWindow;
};


DrawingModeApp::DrawingModeApp()
        :       BApplication("application/x.vnd-Haiku.DrawingModeTest")
{
        fWindow = new DrawingModeWindow(BRect(200, 200, 760, 800));
        fWindow->Show();
}


DrawingModeWindow::DrawingModeWindow(BRect frame)
        :       BWindow(frame, "Drawing Modes Test", B_TITLED_WINDOW,
                        B_QUIT_ON_WINDOW_CLOSE)
{
        fView = new DrawingModeView(frame.OffsetToSelf(0, 0));
        AddChild(fView);
        fView->SetViewColor(255, 203, 0);
        fView->SetDrawingMode(B_OP_OVER);
}


DrawingModeView::DrawingModeView(BRect frame)
        :       BView(frame, "DrawingModeView", B_FOLLOW_ALL, B_WILL_DRAW),
                fBitmap(NULL)
{
        fBitmap = new BBitmap(BRect(0, 0, 31, 31), B_RGB32);
        memcpy(fBitmap->Bits(), kBitmapBits, fBitmap->BitsLength());

        uint32 triangleLeftBits[32 * 32] = { 0 };
        uint32 triangleRightBits[32 * 32] = { 0 };
        for(int y = 0; y < 32; ++y) {
                for(int x = 0; x < 32; ++x) {
                        if(x < 32 - y) {
                                triangleLeftBits[y * 32 + x] = 0xffff0000;
                        }
                        if(x >= y) {
                                triangleRightBits[y * 32 + x] = 0xff0000ff;
                        }
                }
        }

        fTriangleLeft = new BBitmap(BRect(0, 0, 31, 31), B_RGBA32);
        memcpy(fTriangleLeft->Bits(), triangleLeftBits,
                fTriangleLeft->BitsLength());
        fTriangleRight = new BBitmap(BRect(0, 0, 31, 31), B_RGBA32);
        memcpy(fTriangleRight->Bits(), triangleRightBits,
                fTriangleRight->BitsLength());
}


DrawingModeView::~DrawingModeView()
{
        delete fBitmap;
        delete fTriangleLeft;
        delete fTriangleRight;
}


void
DrawingModeView::Draw(BRect updateRect)
{
        SetDrawingMode(B_OP_COPY);
        SetLowColor(ViewColor());
        FillRect(Bounds(), B_SOLID_LOW);

        SetLowColor(255, 0, 0);
        SetHighColor(0, 0, 255);

        BRect bitmapBounds = fBitmap->Bounds();
        int32 imageHeight = bitmapBounds.IntegerHeight() + 10;
        int32 imageWidth = bitmapBounds.IntegerWidth() + 10;
        BRect triangleBounds = fTriangleLeft->Bounds();
        int32 triangleHeight = triangleBounds.IntegerHeight() + 10;
        int32 triangleWidth = triangleBounds.IntegerWidth() + 10;

#define MODE(m) { m, #m }

        struct {
                drawing_mode mode;
                const char *name;
        } drawingModes[] = {
                MODE(B_OP_COPY),
                MODE(B_OP_OVER),
                MODE(B_OP_ERASE),
                MODE(B_OP_INVERT),
                MODE(B_OP_SELECT),
                MODE(B_OP_ADD),
                MODE(B_OP_SUBTRACT),
                MODE(B_OP_BLEND),
                MODE(B_OP_MIN),
                MODE(B_OP_MAX)
        };

        struct {
                alpha_function mode;
                const char *name;
        } blendingModes[] = {
                MODE(B_ALPHA_COMPOSITE_SOURCE_OVER),
                MODE(B_ALPHA_COMPOSITE_SOURCE_IN),
                MODE(B_ALPHA_COMPOSITE_SOURCE_OUT),
                MODE(B_ALPHA_COMPOSITE_SOURCE_ATOP),
                MODE(B_ALPHA_COMPOSITE_DESTINATION_OVER),
                MODE(B_ALPHA_COMPOSITE_DESTINATION_IN),
                MODE(B_ALPHA_COMPOSITE_DESTINATION_OUT),
                MODE(B_ALPHA_COMPOSITE_DESTINATION_ATOP),
                MODE(B_ALPHA_COMPOSITE_XOR),
                MODE(B_ALPHA_COMPOSITE_CLEAR),
                MODE(B_ALPHA_COMPOSITE_DIFFERENCE),
                MODE(B_ALPHA_COMPOSITE_LIGHTEN),
                MODE(B_ALPHA_COMPOSITE_DARKEN)
        };

        int32 modeCount = sizeof(drawingModes) / sizeof(drawingModes[0]);
        for (int32 i = 0; i < modeCount; i++) {
                if (drawingModes[i].mode == B_OP_SELECT) {
                        // make the background contain the low and high color to see
                        // actual effect of B_OP_SELECT
                        SetDrawingMode(B_OP_COPY);
                        FillRect(BRect(0, imageHeight * i, imageWidth * 2 - 10,
                                imageHeight * i + bitmapBounds.Height() / 2), B_SOLID_LOW);
                        FillRect(BRect(0, imageHeight * i  + bitmapBounds.Height() / 2,
                                imageWidth * 2 - 10, imageHeight * i + bitmapBounds.Height()),
                                B_SOLID_HIGH);
                } else if (drawingModes[i].mode == B_OP_MAX
                        || drawingModes[i].mode == B_OP_MIN) {
                        // need a darker/lighter color as a background otherwise nothing
                        // will be selected from the source
                        SetDrawingMode(B_OP_COPY);
                        SetHighColor(255, 255, 255);
                        FillRect(BRect(0, imageHeight * i, imageWidth * 2 - 10,
                                imageHeight * i + bitmapBounds.Height() / 3), B_SOLID_HIGH);
                        SetHighColor(128, 128, 128);
                        FillRect(BRect(0, imageHeight * i  + bitmapBounds.Height() / 3,
                                imageWidth * 2 - 10, imageHeight * i + bitmapBounds.Height()),
                                B_SOLID_HIGH);
                        SetHighColor(0, 0, 0);
                        FillRect(BRect(0, imageHeight * i  + bitmapBounds.Height() / 3 * 2,
                                imageWidth * 2 - 10, imageHeight * i + bitmapBounds.Height()),
                                B_SOLID_HIGH);
                        SetHighColor(0, 0, 255);
                }

                SetDrawingMode(drawingModes[i].mode);
                DrawBitmap(fBitmap, BPoint(0, imageHeight * i));
                FillRect(bitmapBounds.OffsetToCopy(imageWidth,
                        imageHeight * i), B_MIXED_COLORS);

                SetDrawingMode(B_OP_OVER);
                DrawString(drawingModes[i].name, BPoint(imageWidth * 2,
                        imageHeight * i + 20));
        }

#ifdef DUMP_BLENDING_RESULTS
        BTranslatorRoster* roster = BTranslatorRoster::Default();
        if (roster == NULL)
                abort();

        translator_id* outId;
        int32 outCount;
        translation_format pngFormat;
        roster->GetAllTranslators(&outId, &outCount);
        for(int32 i = 0; i < outCount; ++i) {
                const translation_format* formats;
                int32 formatCount;
                roster->GetOutputFormats(outId[i], &formats, &formatCount);
                for(int32 j = 0; j < formatCount; ++j) {
                        if(strcmp(formats[j].MIME, "image/png") == 0) {
                                pngFormat = formats[j];
                        }
                }
        }

        status_t r = B_OK;
        {
                BFile file("DESTINATION.png",
                        B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
                BBitmapStream stream(fTriangleLeft);
                r = roster->Translate(&stream, NULL, NULL, &file, pngFormat.type);
                if(r != B_OK)
                        fprintf(stderr, "Failed to save PNG file for destination\n");
                stream.DetachBitmap(&fTriangleLeft);
        }
        {
                BFile file("SOURCE.png", B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
                BBitmapStream stream(fTriangleRight);
                r = roster->Translate(&stream, NULL, NULL, &file, pngFormat.type);
                if(r != B_OK)
                        fprintf(stderr, "Failed to save PNG file for source\n");
                stream.DetachBitmap(&fTriangleRight);
        }
#endif

        modeCount = sizeof(blendingModes) / sizeof(blendingModes[0]);
        const int columnOffset = 180;
        BView *blitter = new BView(BRect(0, 0, 31, 31),
                "blitter", B_FOLLOW_ALL, B_WILL_DRAW);
        BBitmap *resultBitmap = new BBitmap(BRect(0, 0, 31, 31),
                B_RGBA32, true, false);
        resultBitmap->AddChild(blitter);
        for (int32 i = 0; i < modeCount; i++) {
                resultBitmap->Lock();
                blitter->SetDrawingMode(B_OP_COPY);
                blitter->SetHighColor(0, 0, 0, 0);
                blitter->FillRect(resultBitmap->Bounds());
                blitter->DrawBitmap(fTriangleLeft, B_ORIGIN);
                blitter->SetDrawingMode(B_OP_ALPHA);
                blitter->SetBlendingMode(B_PIXEL_ALPHA, blendingModes[i].mode);
                blitter->DrawBitmap(fTriangleRight, B_ORIGIN);
                resultBitmap->Unlock();

#ifdef DUMP_BLENDING_RESULTS
                BBitmapStream stream(resultBitmap);
                BString fileName(blendingModes[i].name);
                BFile file(fileName.Append(".png"),
                        B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);

                r = roster->Translate(&stream, NULL, NULL, &file, pngFormat.type);
                if(r != B_OK) {
                        fprintf(stderr, "Failed to save PNG file for %s\n",
                                blendingModes[i].name);
                }

                stream.DetachBitmap(&resultBitmap);
#endif

                SetDrawingMode(B_OP_ALPHA);
                SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
                DrawBitmap(resultBitmap, BPoint(columnOffset, triangleHeight * i));

                SetDrawingMode(B_OP_OVER);
                DrawString(blendingModes[i].name, BPoint(columnOffset + triangleWidth,
                        triangleHeight * i + 20));
        }
        resultBitmap->Lock();
        resultBitmap->RemoveChild(blitter);
        delete resultBitmap;
        delete blitter;
}


int
main(int argc, const char *argv[])
{
        DrawingModeApp *app = new DrawingModeApp();
        app->Run();
        delete app;
        return 0;
}