xref: /haiku/src/tests/servers/app/transformation/main.cpp (revision b6c34f4c44851acfa4f671933f304adab82bedbb)
108e109e5SStephan Aßmus /*
208e109e5SStephan Aßmus  * Copyright 2014 Stephan Aßmus <superstippi@gmx.de>
308e109e5SStephan Aßmus  * All rights reserved. Distributed under the terms of the MIT license.
408e109e5SStephan Aßmus  */
508e109e5SStephan Aßmus 
608e109e5SStephan Aßmus 
7e966330cSStephan Aßmus #include <algorithm>
808e109e5SStephan Aßmus #include <stdio.h>
908e109e5SStephan Aßmus #include <string.h>
1008e109e5SStephan Aßmus 
1108e109e5SStephan Aßmus #include <Application.h>
1205a19d41SStephan Aßmus #include <Bitmap.h>
13e966330cSStephan Aßmus #include <GradientLinear.h>
1408e109e5SStephan Aßmus #include <LayoutBuilder.h>
1508e109e5SStephan Aßmus #include <List.h>
16*b6c34f4cSAdrien Destugues #include <Message.h>
17*b6c34f4cSAdrien Destugues #include <Picture.h>
1808e109e5SStephan Aßmus #include <PopUpMenu.h>
19*b6c34f4cSAdrien Destugues #include <Region.h>
2005a19d41SStephan Aßmus #include <Resources.h>
2105a19d41SStephan Aßmus #include <Roster.h>
2208e109e5SStephan Aßmus #include <ScrollView.h>
2308e109e5SStephan Aßmus #include <String.h>
2408e109e5SStephan Aßmus #include <StringView.h>
2508e109e5SStephan Aßmus #include <View.h>
2608e109e5SStephan Aßmus #include <Window.h>
2708e109e5SStephan Aßmus 
2808e109e5SStephan Aßmus 
29*b6c34f4cSAdrien Destugues static const char* kAppSignature = "application/x-vnd.Haiku-Transformation";
3008e109e5SStephan Aßmus 
3108e109e5SStephan Aßmus 
3208e109e5SStephan Aßmus class Test {
3308e109e5SStephan Aßmus public:
3408e109e5SStephan Aßmus 								Test(const char* name);
3508e109e5SStephan Aßmus 	virtual						~Test();
3608e109e5SStephan Aßmus 
3708e109e5SStephan Aßmus 			const char*			Name() const
3808e109e5SStephan Aßmus 									{ return fName.String(); }
3908e109e5SStephan Aßmus 
4008e109e5SStephan Aßmus 	virtual	void				Draw(BView* view, BRect updateRect) = 0;
4108e109e5SStephan Aßmus 
4208e109e5SStephan Aßmus private:
4308e109e5SStephan Aßmus 			BString				fName;
4408e109e5SStephan Aßmus };
4508e109e5SStephan Aßmus 
4608e109e5SStephan Aßmus 
4708e109e5SStephan Aßmus Test::Test(const char* name)
4808e109e5SStephan Aßmus 	:
4908e109e5SStephan Aßmus 	fName(name)
5008e109e5SStephan Aßmus {
5108e109e5SStephan Aßmus }
5208e109e5SStephan Aßmus 
5308e109e5SStephan Aßmus 
5408e109e5SStephan Aßmus Test::~Test()
5508e109e5SStephan Aßmus {
5608e109e5SStephan Aßmus }
5708e109e5SStephan Aßmus 
5808e109e5SStephan Aßmus 
5908e109e5SStephan Aßmus // #pragma mark - TestView
6008e109e5SStephan Aßmus 
6108e109e5SStephan Aßmus 
6208e109e5SStephan Aßmus class TestView : public BView {
6308e109e5SStephan Aßmus public:
6408e109e5SStephan Aßmus 								TestView();
6508e109e5SStephan Aßmus 	virtual						~TestView();
6608e109e5SStephan Aßmus 
6708e109e5SStephan Aßmus 	virtual	void				Draw(BRect updateRect);
6808e109e5SStephan Aßmus 
6908e109e5SStephan Aßmus 			void				SetTest(Test* test);
7008e109e5SStephan Aßmus 
7108e109e5SStephan Aßmus private:
7208e109e5SStephan Aßmus 			Test*				fTest;
7308e109e5SStephan Aßmus };
7408e109e5SStephan Aßmus 
7508e109e5SStephan Aßmus 
7608e109e5SStephan Aßmus TestView::TestView()
7708e109e5SStephan Aßmus 	:
7808e109e5SStephan Aßmus 	BView(NULL, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
7908e109e5SStephan Aßmus 	fTest(NULL)
8008e109e5SStephan Aßmus {
8108e109e5SStephan Aßmus }
8208e109e5SStephan Aßmus 
8308e109e5SStephan Aßmus 
8408e109e5SStephan Aßmus TestView::~TestView()
8508e109e5SStephan Aßmus {
8608e109e5SStephan Aßmus }
8708e109e5SStephan Aßmus 
8808e109e5SStephan Aßmus 
8908e109e5SStephan Aßmus void
9008e109e5SStephan Aßmus TestView::Draw(BRect updateRect)
9108e109e5SStephan Aßmus {
9208e109e5SStephan Aßmus 	if (fTest != NULL)
9308e109e5SStephan Aßmus 		fTest->Draw(this, updateRect);
9408e109e5SStephan Aßmus }
9508e109e5SStephan Aßmus 
9608e109e5SStephan Aßmus 
9708e109e5SStephan Aßmus void
9808e109e5SStephan Aßmus TestView::SetTest(Test* test)
9908e109e5SStephan Aßmus {
10008e109e5SStephan Aßmus 	fTest = test;
10108e109e5SStephan Aßmus 	Invalidate();
10208e109e5SStephan Aßmus }
10308e109e5SStephan Aßmus 
10408e109e5SStephan Aßmus 
10508e109e5SStephan Aßmus // #pragma mark - TestWindow
10608e109e5SStephan Aßmus 
10708e109e5SStephan Aßmus 
10808e109e5SStephan Aßmus enum {
10908e109e5SStephan Aßmus 	MSG_SELECT_TEST	= 'stst'
11008e109e5SStephan Aßmus };
11108e109e5SStephan Aßmus 
11208e109e5SStephan Aßmus 
11308e109e5SStephan Aßmus class TestWindow : public BWindow {
11408e109e5SStephan Aßmus public:
11508e109e5SStephan Aßmus 								TestWindow();
11608e109e5SStephan Aßmus 	virtual						~TestWindow();
11708e109e5SStephan Aßmus 
11808e109e5SStephan Aßmus 	virtual	void				MessageReceived(BMessage* message);
11908e109e5SStephan Aßmus 
12008e109e5SStephan Aßmus 			void				AddTest(Test* test);
12108e109e5SStephan Aßmus 			void				SetToTest(int32 index);
12208e109e5SStephan Aßmus 
12308e109e5SStephan Aßmus private:
12408e109e5SStephan Aßmus 			TestView*			fTestView;
12508e109e5SStephan Aßmus 
12608e109e5SStephan Aßmus 			BMenuField*			fTestSelectionField;
12708e109e5SStephan Aßmus 
12808e109e5SStephan Aßmus 			BList				fTests;
12908e109e5SStephan Aßmus };
13008e109e5SStephan Aßmus 
13108e109e5SStephan Aßmus 
13208e109e5SStephan Aßmus TestWindow::TestWindow()
13308e109e5SStephan Aßmus 	:
13408e109e5SStephan Aßmus 	BWindow(BRect(50.0, 50.0, 450.0, 250.0), "Transformations Test",
13508e109e5SStephan Aßmus 		B_DOCUMENT_WINDOW, B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE
13608e109e5SStephan Aßmus 			| B_AUTO_UPDATE_SIZE_LIMITS)
13708e109e5SStephan Aßmus {
13808e109e5SStephan Aßmus 	fTestView = new TestView();
13908e109e5SStephan Aßmus 
14008e109e5SStephan Aßmus 	BScrollView* scrollView = new BScrollView("scroll", fTestView, 0, true,
14108e109e5SStephan Aßmus 		true);
14208e109e5SStephan Aßmus 
14308e109e5SStephan Aßmus 	fTestSelectionField = new BMenuField("test selection",
14408e109e5SStephan Aßmus 		"Select test:", new BPopUpMenu("select"));
14508e109e5SStephan Aßmus 
14608e109e5SStephan Aßmus 	BLayoutBuilder::Group<>(this, B_VERTICAL, 0.0f)
14708e109e5SStephan Aßmus 		.AddGroup(B_HORIZONTAL)
14808e109e5SStephan Aßmus 			.Add(fTestSelectionField)
14908e109e5SStephan Aßmus 			.AddGlue()
15008e109e5SStephan Aßmus 			.SetInsets(B_USE_DEFAULT_SPACING)
15108e109e5SStephan Aßmus 		.End()
15208e109e5SStephan Aßmus 		.Add(scrollView)
15308e109e5SStephan Aßmus 	;
15408e109e5SStephan Aßmus }
15508e109e5SStephan Aßmus 
15608e109e5SStephan Aßmus 
15708e109e5SStephan Aßmus TestWindow::~TestWindow()
15808e109e5SStephan Aßmus {
15908e109e5SStephan Aßmus 	for (int32 i = fTests.CountItems() - 1; i >= 0; i++)
16008e109e5SStephan Aßmus 		delete (Test*)fTests.ItemAt(i);
16108e109e5SStephan Aßmus }
16208e109e5SStephan Aßmus 
16308e109e5SStephan Aßmus 
16408e109e5SStephan Aßmus void
16508e109e5SStephan Aßmus TestWindow::MessageReceived(BMessage* message)
16608e109e5SStephan Aßmus {
16708e109e5SStephan Aßmus 	switch (message->what) {
16808e109e5SStephan Aßmus 		case MSG_SELECT_TEST:
16908e109e5SStephan Aßmus 		{
17008e109e5SStephan Aßmus 			int32 index;
17108e109e5SStephan Aßmus 			if (message->FindInt32("index", &index) == B_OK)
17208e109e5SStephan Aßmus 				SetToTest(index);
17308e109e5SStephan Aßmus 			break;
17408e109e5SStephan Aßmus 		}
17508e109e5SStephan Aßmus 
17608e109e5SStephan Aßmus 		default:
17708e109e5SStephan Aßmus 			BWindow::MessageReceived(message);
17808e109e5SStephan Aßmus 	}
17908e109e5SStephan Aßmus }
18008e109e5SStephan Aßmus 
18108e109e5SStephan Aßmus 
18208e109e5SStephan Aßmus void
18308e109e5SStephan Aßmus TestWindow::AddTest(Test* test)
18408e109e5SStephan Aßmus {
18508e109e5SStephan Aßmus 	if (test == NULL || fTests.HasItem(test))
18608e109e5SStephan Aßmus 		return;
18708e109e5SStephan Aßmus 
18808e109e5SStephan Aßmus 	if (!fTests.AddItem(test)) {
18908e109e5SStephan Aßmus 		delete test;
19008e109e5SStephan Aßmus 		return;
19108e109e5SStephan Aßmus 	}
19208e109e5SStephan Aßmus 
19308e109e5SStephan Aßmus 	BMessage* message = new BMessage(MSG_SELECT_TEST);
19408e109e5SStephan Aßmus 	message->AddInt32("index", fTests.CountItems() - 1);
19508e109e5SStephan Aßmus 
19608e109e5SStephan Aßmus 	BMenuItem* item = new BMenuItem(test->Name(), message);
19708e109e5SStephan Aßmus 	if (!fTestSelectionField->Menu()->AddItem(item)) {
19808e109e5SStephan Aßmus 		fTests.RemoveItem(fTests.CountItems() - 1);
19908e109e5SStephan Aßmus 		delete test;
20008e109e5SStephan Aßmus 		delete item;
20108e109e5SStephan Aßmus 		return;
20208e109e5SStephan Aßmus 	}
20308e109e5SStephan Aßmus 
20408e109e5SStephan Aßmus 	if (fTests.CountItems() == 1)
20508e109e5SStephan Aßmus 		SetToTest(0);
20608e109e5SStephan Aßmus }
20708e109e5SStephan Aßmus 
20808e109e5SStephan Aßmus 
20908e109e5SStephan Aßmus void
21008e109e5SStephan Aßmus TestWindow::SetToTest(int32 index)
21108e109e5SStephan Aßmus {
21208e109e5SStephan Aßmus 	Test* test = (Test*)fTests.ItemAt(index);
21308e109e5SStephan Aßmus 	if (test == NULL)
21408e109e5SStephan Aßmus 		return;
21508e109e5SStephan Aßmus 
21608e109e5SStephan Aßmus 	fTestSelectionField->Menu()->ItemAt(index)->SetMarked(true);
21708e109e5SStephan Aßmus 
21808e109e5SStephan Aßmus 	fTestView->SetTest(test);
21908e109e5SStephan Aßmus }
22008e109e5SStephan Aßmus 
22108e109e5SStephan Aßmus 
22208e109e5SStephan Aßmus // #pragma mark - Test1
22308e109e5SStephan Aßmus 
22408e109e5SStephan Aßmus 
22508e109e5SStephan Aßmus class RectsTest : public Test {
22608e109e5SStephan Aßmus public:
22708e109e5SStephan Aßmus 	RectsTest()
22808e109e5SStephan Aßmus 		:
22908e109e5SStephan Aßmus 		Test("Rects")
23008e109e5SStephan Aßmus 	{
23108e109e5SStephan Aßmus 	}
23208e109e5SStephan Aßmus 
23308e109e5SStephan Aßmus 	virtual void Draw(BView* view, BRect updateRect)
23408e109e5SStephan Aßmus 	{
23508e109e5SStephan Aßmus 		view->DrawString("Rects", BPoint(20, 30));
23608e109e5SStephan Aßmus 
23708e109e5SStephan Aßmus 		view->SetDrawingMode(B_OP_ALPHA);
23808e109e5SStephan Aßmus 		view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
23908e109e5SStephan Aßmus 
24008e109e5SStephan Aßmus 		BRect rect(view->Bounds());
2412f9ac958SAdrien Destugues 		rect.OffsetTo(B_ORIGIN);
2422f9ac958SAdrien Destugues 
24308e109e5SStephan Aßmus 		rect.InsetBy(rect.Width() / 3, rect.Height() / 3);
24408e109e5SStephan Aßmus 		BPoint center(
24508e109e5SStephan Aßmus 			rect.left + rect.Width() / 2,
24608e109e5SStephan Aßmus 			rect.top + rect.Height() / 2);
24708e109e5SStephan Aßmus 
248d93591ffSStephan Aßmus 		for (int32 i = 0; i < 360; i += 40) {
24908e109e5SStephan Aßmus 			BAffineTransform transform;
25008e109e5SStephan Aßmus 			transform.RotateBy(center, i * M_PI / 180.0);
25108e109e5SStephan Aßmus 			view->SetTransform(transform);
252d93591ffSStephan Aßmus 
253d93591ffSStephan Aßmus 			view->SetHighColor(51, 151, 255, 20);
25408e109e5SStephan Aßmus 			view->FillRect(rect);
255d93591ffSStephan Aßmus 
256d93591ffSStephan Aßmus 			view->SetHighColor(51, 255, 151, 180);
257d93591ffSStephan Aßmus 			view->DrawString("Rect", center);
25808e109e5SStephan Aßmus 		}
25908e109e5SStephan Aßmus 	}
26008e109e5SStephan Aßmus };
26108e109e5SStephan Aßmus 
26208e109e5SStephan Aßmus 
26305a19d41SStephan Aßmus // #pragma mark - BitmapTest
26405a19d41SStephan Aßmus 
26505a19d41SStephan Aßmus 
26605a19d41SStephan Aßmus class BitmapTest : public Test {
26705a19d41SStephan Aßmus public:
26805a19d41SStephan Aßmus 	BitmapTest()
26905a19d41SStephan Aßmus 		:
27005a19d41SStephan Aßmus 		Test("Bitmap"),
27105a19d41SStephan Aßmus 		fBitmap(_LoadBitmap(555))
27205a19d41SStephan Aßmus 	{
27305a19d41SStephan Aßmus 	}
27405a19d41SStephan Aßmus 
27505a19d41SStephan Aßmus 	virtual void Draw(BView* view, BRect updateRect)
27605a19d41SStephan Aßmus 	{
27705a19d41SStephan Aßmus 		BRect rect(view->Bounds());
27805a19d41SStephan Aßmus 
27905a19d41SStephan Aßmus 		if (fBitmap == NULL) {
28005a19d41SStephan Aßmus 			view->SetHighColor(255, 0, 0);
28105a19d41SStephan Aßmus 			view->FillRect(rect);
28205a19d41SStephan Aßmus 			view->SetHighColor(0, 0, 0);
28305a19d41SStephan Aßmus 			view->DrawString("Failed to load the bitmap.", BPoint(20, 20));
28405a19d41SStephan Aßmus 			return;
28505a19d41SStephan Aßmus 		}
28605a19d41SStephan Aßmus 
28705a19d41SStephan Aßmus 		rect.left = (rect.Width() - fBitmap->Bounds().Width()) / 2;
28805a19d41SStephan Aßmus 		rect.top = (rect.Height() - fBitmap->Bounds().Height()) / 2;
28905a19d41SStephan Aßmus 		rect.right = rect.left + fBitmap->Bounds().Width();
29005a19d41SStephan Aßmus 		rect.bottom = rect.top + fBitmap->Bounds().Height();
29105a19d41SStephan Aßmus 
29205a19d41SStephan Aßmus 		BPoint center(
29305a19d41SStephan Aßmus 			rect.left + rect.Width() / 2,
29405a19d41SStephan Aßmus 			rect.top + rect.Height() / 2);
29505a19d41SStephan Aßmus 
29605a19d41SStephan Aßmus 		BPicture picture;
29705a19d41SStephan Aßmus 		view->BeginPicture(&picture);
29805a19d41SStephan Aßmus 		view->SetDrawingMode(B_OP_ALPHA);
29905a19d41SStephan Aßmus 		view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE);
30005a19d41SStephan Aßmus 		BFont font;
30105a19d41SStephan Aßmus 		view->GetFont(&font);
30205a19d41SStephan Aßmus 		font.SetSize(70);
30305a19d41SStephan Aßmus 		view->SetFont(&font);
30405a19d41SStephan Aßmus 		view->SetHighColor(0, 0, 0, 80);
30505a19d41SStephan Aßmus 		view->FillRect(view->Bounds());
30605a19d41SStephan Aßmus 		view->SetHighColor(0, 0, 0, 255);
30705a19d41SStephan Aßmus 		view->DrawString("CLIPPING", BPoint(0, center.y + 35));
30805a19d41SStephan Aßmus 		view->EndPicture();
30905a19d41SStephan Aßmus 
31005a19d41SStephan Aßmus 		view->ClipToPicture(&picture);
31105a19d41SStephan Aßmus 
31205a19d41SStephan Aßmus 		BAffineTransform transform;
31305a19d41SStephan Aßmus 			transform.RotateBy(center, 30 * M_PI / 180.0);
31405a19d41SStephan Aßmus 			view->SetTransform(transform);
31505a19d41SStephan Aßmus 
31605a19d41SStephan Aßmus 		view->DrawBitmap(fBitmap, fBitmap->Bounds(), rect);
31705a19d41SStephan Aßmus 	}
31805a19d41SStephan Aßmus 
31905a19d41SStephan Aßmus private:
32005a19d41SStephan Aßmus 	status_t
32105a19d41SStephan Aßmus 	_GetAppResources(BResources& resources) const
32205a19d41SStephan Aßmus 	{
32305a19d41SStephan Aßmus 		app_info info;
32405a19d41SStephan Aßmus 		status_t status = be_app->GetAppInfo(&info);
32505a19d41SStephan Aßmus 		if (status != B_OK)
32605a19d41SStephan Aßmus 			return status;
32705a19d41SStephan Aßmus 
32805a19d41SStephan Aßmus 		return resources.SetTo(&info.ref);
32905a19d41SStephan Aßmus 	}
33005a19d41SStephan Aßmus 
33105a19d41SStephan Aßmus 
33205a19d41SStephan Aßmus 	BBitmap* _LoadBitmap(int resourceID) const
33305a19d41SStephan Aßmus 	{
33405a19d41SStephan Aßmus 		BResources resources;
33505a19d41SStephan Aßmus 		status_t status = _GetAppResources(resources);
33605a19d41SStephan Aßmus 		if (status != B_OK)
33705a19d41SStephan Aßmus 			return NULL;
33805a19d41SStephan Aßmus 
33905a19d41SStephan Aßmus 		size_t dataSize;
34005a19d41SStephan Aßmus 		const void* data = resources.LoadResource(B_MESSAGE_TYPE, resourceID,
34105a19d41SStephan Aßmus 			&dataSize);
34205a19d41SStephan Aßmus 		if (data == NULL)
34305a19d41SStephan Aßmus 			return NULL;
34405a19d41SStephan Aßmus 
34505a19d41SStephan Aßmus 		BMemoryIO stream(data, dataSize);
34605a19d41SStephan Aßmus 
34705a19d41SStephan Aßmus 		// Try to read as an archived bitmap.
34805a19d41SStephan Aßmus 		BMessage archive;
34905a19d41SStephan Aßmus 		status = archive.Unflatten(&stream);
35005a19d41SStephan Aßmus 		if (status != B_OK)
35105a19d41SStephan Aßmus 			return NULL;
35205a19d41SStephan Aßmus 
35305a19d41SStephan Aßmus 		BBitmap* bitmap = new BBitmap(&archive);
35405a19d41SStephan Aßmus 
35505a19d41SStephan Aßmus 		status = bitmap->InitCheck();
35605a19d41SStephan Aßmus 		if (status != B_OK) {
35705a19d41SStephan Aßmus 			delete bitmap;
35805a19d41SStephan Aßmus 			bitmap = NULL;
35905a19d41SStephan Aßmus 		}
36005a19d41SStephan Aßmus 
36105a19d41SStephan Aßmus 		return bitmap;
36205a19d41SStephan Aßmus 	}
36305a19d41SStephan Aßmus 
36405a19d41SStephan Aßmus private:
36505a19d41SStephan Aßmus 	BBitmap*	fBitmap;
36605a19d41SStephan Aßmus };
36705a19d41SStephan Aßmus 
36805a19d41SStephan Aßmus 
369e966330cSStephan Aßmus // #pragma mark - Gradient
370e966330cSStephan Aßmus 
371e966330cSStephan Aßmus 
372e966330cSStephan Aßmus class GradientTest : public Test {
373e966330cSStephan Aßmus public:
374e966330cSStephan Aßmus 	GradientTest()
375e966330cSStephan Aßmus 		:
376e966330cSStephan Aßmus 		Test("Gradient")
377e966330cSStephan Aßmus 	{
378e966330cSStephan Aßmus 	}
379e966330cSStephan Aßmus 
380e966330cSStephan Aßmus 	virtual void Draw(BView* view, BRect updateRect)
381e966330cSStephan Aßmus 	{
382e966330cSStephan Aßmus 		BRect rect(view->Bounds());
383e966330cSStephan Aßmus 		rect.InsetBy(rect.Width() / 3, rect.Height() / 3);
384e966330cSStephan Aßmus 		BPoint center(
385e966330cSStephan Aßmus 			rect.left + rect.Width() / 2,
386e966330cSStephan Aßmus 			rect.top + rect.Height() / 2);
387e966330cSStephan Aßmus 
388e966330cSStephan Aßmus 		BAffineTransform transform;
389e966330cSStephan Aßmus 		transform.RotateBy(center, 30.0 * M_PI / 180.0);
390e966330cSStephan Aßmus 		view->SetTransform(transform);
391e966330cSStephan Aßmus 
392e966330cSStephan Aßmus 		rgb_color top = (rgb_color){ 255, 255, 0, 255 };
393e966330cSStephan Aßmus 		rgb_color bottom = (rgb_color){ 0, 255, 255, 255 };
394e966330cSStephan Aßmus 
395e966330cSStephan Aßmus 		BGradientLinear gradient;
396e966330cSStephan Aßmus 		gradient.AddColor(top, 0.0f);
397e966330cSStephan Aßmus 		gradient.AddColor(bottom, 255.0f);
398e966330cSStephan Aßmus 		gradient.SetStart(rect.LeftTop());
399e966330cSStephan Aßmus 		gradient.SetEnd(rect.LeftBottom());
400e966330cSStephan Aßmus 
401e966330cSStephan Aßmus 		float radius = std::min(rect.Width() / 5, rect.Height() / 5);
402e966330cSStephan Aßmus 
403e966330cSStephan Aßmus 		view->FillRoundRect(rect, radius, radius, gradient);
404e966330cSStephan Aßmus 	}
405e966330cSStephan Aßmus };
40605a19d41SStephan Aßmus 
40705a19d41SStephan Aßmus 
4089f44851eSStephan Aßmus // #pragma mark - NestedStates
4099f44851eSStephan Aßmus 
4109f44851eSStephan Aßmus 
4119f44851eSStephan Aßmus class NestedStatesTest : public Test {
4129f44851eSStephan Aßmus public:
4139f44851eSStephan Aßmus 	NestedStatesTest()
4149f44851eSStephan Aßmus 		:
4159f44851eSStephan Aßmus 		Test("Nested view states")
4169f44851eSStephan Aßmus 	{
4179f44851eSStephan Aßmus 	}
4189f44851eSStephan Aßmus 
4199f44851eSStephan Aßmus 	virtual void Draw(BView* view, BRect updateRect)
4209f44851eSStephan Aßmus 	{
4219f44851eSStephan Aßmus 		BAffineTransform transform;
4229f44851eSStephan Aßmus 		transform.RotateBy(BPoint(100, 100), 30.0 * M_PI / 180.0);
4239f44851eSStephan Aßmus 		view->SetTransform(transform);
4249f44851eSStephan Aßmus 
4259f44851eSStephan Aßmus 		rgb_color top = (rgb_color){ 255, 0, 0, 255 };
4269f44851eSStephan Aßmus 		rgb_color bottom = (rgb_color){ 255, 255, 0, 255 };
4279f44851eSStephan Aßmus 
4289f44851eSStephan Aßmus 		BRect rect(20, 20, 120, 120);
4299f44851eSStephan Aßmus 
4309f44851eSStephan Aßmus 		BGradientLinear gradient;
4319f44851eSStephan Aßmus 		gradient.AddColor(top, 0.0f);
4329f44851eSStephan Aßmus 		gradient.AddColor(bottom, 255.0f);
4339f44851eSStephan Aßmus 		gradient.SetStart(rect.LeftTop());
4349f44851eSStephan Aßmus 		gradient.SetEnd(rect.LeftBottom());
4359f44851eSStephan Aßmus 
4369f44851eSStephan Aßmus 		view->FillRoundRect(rect, 20, 20, gradient);
4379f44851eSStephan Aßmus 
4389f44851eSStephan Aßmus 		view->PushState();
4399f44851eSStephan Aßmus 		// Should be in the same place!
4409f44851eSStephan Aßmus 		view->StrokeRoundRect(rect, 20, 20);
4419f44851eSStephan Aßmus 
4429f44851eSStephan Aßmus 		// Now rotated by another 30 degree
4439f44851eSStephan Aßmus 		view->SetTransform(transform);
4449f44851eSStephan Aßmus 
4459f44851eSStephan Aßmus 		view->SetDrawingMode(B_OP_ALPHA);
4469f44851eSStephan Aßmus 		view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE);
4479f44851eSStephan Aßmus 		view->SetHighColor(0, 0, 255, 120);
4489f44851eSStephan Aßmus 		view->FillRoundRect(rect, 20, 20);
4499f44851eSStephan Aßmus 
4509f44851eSStephan Aßmus 		view->PopState();
4519f44851eSStephan Aßmus 	}
4529f44851eSStephan Aßmus };
4539f44851eSStephan Aßmus 
4549f44851eSStephan Aßmus 
4552f9ac958SAdrien Destugues // #pragma mark - Clipping
4562f9ac958SAdrien Destugues 
4572f9ac958SAdrien Destugues 
4582f9ac958SAdrien Destugues class ClippingTest : public Test {
4592f9ac958SAdrien Destugues public:
4602f9ac958SAdrien Destugues 	ClippingTest()
4612f9ac958SAdrien Destugues 		:
4622f9ac958SAdrien Destugues 		Test("View bounds clipping")
4632f9ac958SAdrien Destugues 	{
4642f9ac958SAdrien Destugues 	}
4652f9ac958SAdrien Destugues 
4662f9ac958SAdrien Destugues 	virtual void Draw(BView* view, BRect updateRect)
4672f9ac958SAdrien Destugues 	{
4682f9ac958SAdrien Destugues 		BRect r (20, 20, 50, 50);
4692f9ac958SAdrien Destugues 		view->SetHighColor(ui_color(B_FAILURE_COLOR));
4702f9ac958SAdrien Destugues 		view->FillRect(r);
4712f9ac958SAdrien Destugues 
4722f9ac958SAdrien Destugues 		BAffineTransform transform;
4732f9ac958SAdrien Destugues 		transform.TranslateBy(400, 400);
4742f9ac958SAdrien Destugues 		view->SetTransform(transform);
4752f9ac958SAdrien Destugues 
4762f9ac958SAdrien Destugues 		// Make sure this rectangle is drawn, even when the original one is out
4772f9ac958SAdrien Destugues 		// of the view bounds (for example because of scrolling).
4782f9ac958SAdrien Destugues 		view->SetHighColor(ui_color(B_SUCCESS_COLOR));
4792f9ac958SAdrien Destugues 		view->FillRect(r);
4802f9ac958SAdrien Destugues 	}
4812f9ac958SAdrien Destugues };
4822f9ac958SAdrien Destugues 
4832f9ac958SAdrien Destugues 
484*b6c34f4cSAdrien Destugues // #pragma mark - Clipping
485*b6c34f4cSAdrien Destugues 
486*b6c34f4cSAdrien Destugues 
487*b6c34f4cSAdrien Destugues class TextClippingTest : public Test {
488*b6c34f4cSAdrien Destugues public:
489*b6c34f4cSAdrien Destugues 	TextClippingTest()
490*b6c34f4cSAdrien Destugues 		:
491*b6c34f4cSAdrien Destugues 		Test("Text clipping")
492*b6c34f4cSAdrien Destugues 	{
493*b6c34f4cSAdrien Destugues 	}
494*b6c34f4cSAdrien Destugues 
495*b6c34f4cSAdrien Destugues 	virtual void Draw(BView* view, BRect updateRect)
496*b6c34f4cSAdrien Destugues 	{
497*b6c34f4cSAdrien Destugues 		BFont font;
498*b6c34f4cSAdrien Destugues 		view->GetFont(&font);
499*b6c34f4cSAdrien Destugues 		font.SetSize(70);
500*b6c34f4cSAdrien Destugues 		view->SetFont(&font);
501*b6c34f4cSAdrien Destugues 
502*b6c34f4cSAdrien Destugues 		float width = view->Bounds().Width();
503*b6c34f4cSAdrien Destugues 
504*b6c34f4cSAdrien Destugues 		// The translation make the text, which has negative coordinates, be
505*b6c34f4cSAdrien Destugues 		// visible inside the viewport.
506*b6c34f4cSAdrien Destugues 		BAffineTransform transform;
507*b6c34f4cSAdrien Destugues 		transform.TranslateBy(width, 0);
508*b6c34f4cSAdrien Destugues 		view->SetTransform(transform);
509*b6c34f4cSAdrien Destugues 
510*b6c34f4cSAdrien Destugues 		const char* str = "CLIPPING";
511*b6c34f4cSAdrien Destugues 
512*b6c34f4cSAdrien Destugues 		// Test the standard DrawString method
513*b6c34f4cSAdrien Destugues 
514*b6c34f4cSAdrien Destugues 		// Draw the text bounds
515*b6c34f4cSAdrien Destugues 		float size = view->StringWidth(str);
516*b6c34f4cSAdrien Destugues 		BRect r(-width, 0, size - width, 70);
517*b6c34f4cSAdrien Destugues 		view->SetHighColor(ui_color(B_SUCCESS_COLOR));
518*b6c34f4cSAdrien Destugues 		view->FillRect(r);
519*b6c34f4cSAdrien Destugues 
520*b6c34f4cSAdrien Destugues 		// Draw the text (which should fit inside the bounds rectangle)
521*b6c34f4cSAdrien Destugues 		view->SetHighColor(0, 0, 0, 255);
522*b6c34f4cSAdrien Destugues 		view->DrawString(str, BPoint(-width, 70));
523*b6c34f4cSAdrien Destugues 
524*b6c34f4cSAdrien Destugues 		// Test with offset-based DrawString
525*b6c34f4cSAdrien Destugues 		BPoint offsets[strlen(str)];
526*b6c34f4cSAdrien Destugues 		for(unsigned int i = 0; i < strlen(str); i++)
527*b6c34f4cSAdrien Destugues 		{
528*b6c34f4cSAdrien Destugues 			offsets[i].x = i * 35 - width;
529*b6c34f4cSAdrien Destugues 			offsets[i].y = 145;
530*b6c34f4cSAdrien Destugues 		}
531*b6c34f4cSAdrien Destugues 
532*b6c34f4cSAdrien Destugues 		// Draw the text bounds
533*b6c34f4cSAdrien Destugues 		view->SetHighColor(ui_color(B_SUCCESS_COLOR));
534*b6c34f4cSAdrien Destugues 		r = BRect(offsets[0], offsets[strlen(str) - 1]);
535*b6c34f4cSAdrien Destugues 		r.top = 75;
536*b6c34f4cSAdrien Destugues 		view->FillRect(r);
537*b6c34f4cSAdrien Destugues 
538*b6c34f4cSAdrien Destugues 		// Draw the text (which should fit inside the bounds rectangle)
539*b6c34f4cSAdrien Destugues 		view->SetHighColor(0, 0, 0, 255);
540*b6c34f4cSAdrien Destugues 		view->DrawString(str, offsets, strlen(str));
541*b6c34f4cSAdrien Destugues 
542*b6c34f4cSAdrien Destugues 	}
543*b6c34f4cSAdrien Destugues };
544*b6c34f4cSAdrien Destugues 
545*b6c34f4cSAdrien Destugues 
546569bd922SAdrien Destugues // #pragma mark - BitmapTest
547569bd922SAdrien Destugues 
548569bd922SAdrien Destugues 
549569bd922SAdrien Destugues class BitmapClipTest : public Test {
550569bd922SAdrien Destugues public:
551569bd922SAdrien Destugues 	BitmapClipTest()
552569bd922SAdrien Destugues 		:
553569bd922SAdrien Destugues 		Test("Bitmap clipping"),
554569bd922SAdrien Destugues 		fBitmap(_LoadBitmap(555))
555569bd922SAdrien Destugues 	{
556569bd922SAdrien Destugues 	}
557569bd922SAdrien Destugues 
558569bd922SAdrien Destugues 	virtual void Draw(BView* view, BRect updateRect)
559569bd922SAdrien Destugues 	{
560569bd922SAdrien Destugues 		BRect rect(view->Bounds());
561569bd922SAdrien Destugues 
562569bd922SAdrien Destugues 		if (fBitmap == NULL) {
563569bd922SAdrien Destugues 			view->SetHighColor(255, 0, 0);
564569bd922SAdrien Destugues 			view->FillRect(rect);
565569bd922SAdrien Destugues 			view->SetHighColor(0, 0, 0);
566569bd922SAdrien Destugues 			view->DrawString("Failed to load the bitmap.", BPoint(20, 20));
567569bd922SAdrien Destugues 			return;
568569bd922SAdrien Destugues 		}
569569bd922SAdrien Destugues 
570569bd922SAdrien Destugues 		rect = fBitmap->Bounds();
571569bd922SAdrien Destugues 
572569bd922SAdrien Destugues 		view->SetHighColor(ui_color(B_FAILURE_COLOR));
573569bd922SAdrien Destugues 		view->FillRect(rect);
574569bd922SAdrien Destugues 
575569bd922SAdrien Destugues 		// The rect offset should compensate the transform translation, so the
576*b6c34f4cSAdrien Destugues 		// bitmap should be drawn at the view origin. It will then exactly
577*b6c34f4cSAdrien Destugues 		// cover the red rectangle, which should not be visible anymore.
578569bd922SAdrien Destugues 		rect.OffsetBy(0, 40);
579569bd922SAdrien Destugues 
580569bd922SAdrien Destugues 		BAffineTransform transform;
581569bd922SAdrien Destugues 			transform.TranslateBy(0, -40);
582569bd922SAdrien Destugues 		view->SetTransform(transform);
583569bd922SAdrien Destugues 
584569bd922SAdrien Destugues 		view->DrawBitmap(fBitmap, fBitmap->Bounds(), rect);
585569bd922SAdrien Destugues 	}
586569bd922SAdrien Destugues 
587569bd922SAdrien Destugues private:
588569bd922SAdrien Destugues 	status_t
589569bd922SAdrien Destugues 	_GetAppResources(BResources& resources) const
590569bd922SAdrien Destugues 	{
591569bd922SAdrien Destugues 		app_info info;
592569bd922SAdrien Destugues 		status_t status = be_app->GetAppInfo(&info);
593569bd922SAdrien Destugues 		if (status != B_OK)
594569bd922SAdrien Destugues 			return status;
595569bd922SAdrien Destugues 
596569bd922SAdrien Destugues 		return resources.SetTo(&info.ref);
597569bd922SAdrien Destugues 	}
598569bd922SAdrien Destugues 
599569bd922SAdrien Destugues 
600569bd922SAdrien Destugues 	BBitmap* _LoadBitmap(int resourceID) const
601569bd922SAdrien Destugues 	{
602569bd922SAdrien Destugues 		BResources resources;
603569bd922SAdrien Destugues 		status_t status = _GetAppResources(resources);
604569bd922SAdrien Destugues 		if (status != B_OK)
605569bd922SAdrien Destugues 			return NULL;
606569bd922SAdrien Destugues 
607569bd922SAdrien Destugues 		size_t dataSize;
608569bd922SAdrien Destugues 		const void* data = resources.LoadResource(B_MESSAGE_TYPE, resourceID,
609569bd922SAdrien Destugues 			&dataSize);
610569bd922SAdrien Destugues 		if (data == NULL)
611569bd922SAdrien Destugues 			return NULL;
612569bd922SAdrien Destugues 
613569bd922SAdrien Destugues 		BMemoryIO stream(data, dataSize);
614569bd922SAdrien Destugues 
615569bd922SAdrien Destugues 		// Try to read as an archived bitmap.
616569bd922SAdrien Destugues 		BMessage archive;
617569bd922SAdrien Destugues 		status = archive.Unflatten(&stream);
618569bd922SAdrien Destugues 		if (status != B_OK)
619569bd922SAdrien Destugues 			return NULL;
620569bd922SAdrien Destugues 
621569bd922SAdrien Destugues 		BBitmap* bitmap = new BBitmap(&archive);
622569bd922SAdrien Destugues 
623569bd922SAdrien Destugues 		status = bitmap->InitCheck();
624569bd922SAdrien Destugues 		if (status != B_OK) {
625569bd922SAdrien Destugues 			delete bitmap;
626569bd922SAdrien Destugues 			bitmap = NULL;
627569bd922SAdrien Destugues 		}
628569bd922SAdrien Destugues 
629569bd922SAdrien Destugues 		return bitmap;
630569bd922SAdrien Destugues 	}
631569bd922SAdrien Destugues 
632569bd922SAdrien Destugues private:
633569bd922SAdrien Destugues 	BBitmap*	fBitmap;
634569bd922SAdrien Destugues };
635569bd922SAdrien Destugues 
636569bd922SAdrien Destugues 
63708e109e5SStephan Aßmus // #pragma mark -
63808e109e5SStephan Aßmus 
63908e109e5SStephan Aßmus 
64008e109e5SStephan Aßmus int
64108e109e5SStephan Aßmus main(int argc, char** argv)
64208e109e5SStephan Aßmus {
64308e109e5SStephan Aßmus 	BApplication app(kAppSignature);
64408e109e5SStephan Aßmus 
64508e109e5SStephan Aßmus 	TestWindow* window = new TestWindow();
64608e109e5SStephan Aßmus 
64708e109e5SStephan Aßmus 	window->AddTest(new RectsTest());
648569bd922SAdrien Destugues 	window->AddTest(new BitmapClipTest());
649*b6c34f4cSAdrien Destugues 	window->AddTest(new TextClippingTest());
65005a19d41SStephan Aßmus 	window->AddTest(new BitmapTest());
651e966330cSStephan Aßmus 	window->AddTest(new GradientTest());
6529f44851eSStephan Aßmus 	window->AddTest(new NestedStatesTest());
6532f9ac958SAdrien Destugues 	window->AddTest(new ClippingTest());
65408e109e5SStephan Aßmus 
655*b6c34f4cSAdrien Destugues 	window->SetToTest(2);
65608e109e5SStephan Aßmus 	window->Show();
65708e109e5SStephan Aßmus 
65808e109e5SStephan Aßmus 	app.Run();
65908e109e5SStephan Aßmus 	return 0;
66008e109e5SStephan Aßmus }
661