xref: /haiku/src/tests/servers/app/transformation/main.cpp (revision a4a2abe0d987fab7d466f3e869bcf256839b131f)
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>
16b6c34f4cSAdrien Destugues #include <Message.h>
17b6c34f4cSAdrien Destugues #include <Picture.h>
1808e109e5SStephan Aßmus #include <PopUpMenu.h>
19b6c34f4cSAdrien 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 
29b6c34f4cSAdrien 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 
59ae4fa7ceSStephan Aßmus class BitmapTest : public Test {
60ae4fa7ceSStephan Aßmus public:
61ae4fa7ceSStephan Aßmus 	BitmapTest(const char* name)
62ae4fa7ceSStephan Aßmus 		:
63ae4fa7ceSStephan Aßmus 		Test(name),
64ae4fa7ceSStephan Aßmus 		fBitmap(_LoadBitmap(555))
65ae4fa7ceSStephan Aßmus 	{
66ae4fa7ceSStephan Aßmus 	}
67ae4fa7ceSStephan Aßmus 
68ae4fa7ceSStephan Aßmus private:
69ae4fa7ceSStephan Aßmus 	status_t
70ae4fa7ceSStephan Aßmus 	_GetAppResources(BResources& resources) const
71ae4fa7ceSStephan Aßmus 	{
72ae4fa7ceSStephan Aßmus 		app_info info;
73ae4fa7ceSStephan Aßmus 		status_t status = be_app->GetAppInfo(&info);
74ae4fa7ceSStephan Aßmus 		if (status != B_OK)
75ae4fa7ceSStephan Aßmus 			return status;
76ae4fa7ceSStephan Aßmus 
77ae4fa7ceSStephan Aßmus 		return resources.SetTo(&info.ref);
78ae4fa7ceSStephan Aßmus 	}
79ae4fa7ceSStephan Aßmus 
80ae4fa7ceSStephan Aßmus 
81ae4fa7ceSStephan Aßmus 	BBitmap* _LoadBitmap(int resourceID) const
82ae4fa7ceSStephan Aßmus 	{
83ae4fa7ceSStephan Aßmus 		BResources resources;
84ae4fa7ceSStephan Aßmus 		status_t status = _GetAppResources(resources);
85ae4fa7ceSStephan Aßmus 		if (status != B_OK)
86ae4fa7ceSStephan Aßmus 			return NULL;
87ae4fa7ceSStephan Aßmus 
88ae4fa7ceSStephan Aßmus 		size_t dataSize;
89ae4fa7ceSStephan Aßmus 		const void* data = resources.LoadResource(B_MESSAGE_TYPE, resourceID,
90ae4fa7ceSStephan Aßmus 			&dataSize);
91ae4fa7ceSStephan Aßmus 		if (data == NULL)
92ae4fa7ceSStephan Aßmus 			return NULL;
93ae4fa7ceSStephan Aßmus 
94ae4fa7ceSStephan Aßmus 		BMemoryIO stream(data, dataSize);
95ae4fa7ceSStephan Aßmus 
96ae4fa7ceSStephan Aßmus 		// Try to read as an archived bitmap.
97ae4fa7ceSStephan Aßmus 		BMessage archive;
98ae4fa7ceSStephan Aßmus 		status = archive.Unflatten(&stream);
99ae4fa7ceSStephan Aßmus 		if (status != B_OK)
100ae4fa7ceSStephan Aßmus 			return NULL;
101ae4fa7ceSStephan Aßmus 
102ae4fa7ceSStephan Aßmus 		BBitmap* bitmap = new BBitmap(&archive);
103ae4fa7ceSStephan Aßmus 
104ae4fa7ceSStephan Aßmus 		status = bitmap->InitCheck();
105ae4fa7ceSStephan Aßmus 		if (status != B_OK) {
106ae4fa7ceSStephan Aßmus 			delete bitmap;
107ae4fa7ceSStephan Aßmus 			bitmap = NULL;
108ae4fa7ceSStephan Aßmus 		}
109ae4fa7ceSStephan Aßmus 
110ae4fa7ceSStephan Aßmus 		return bitmap;
111ae4fa7ceSStephan Aßmus 	}
112ae4fa7ceSStephan Aßmus 
113ae4fa7ceSStephan Aßmus protected:
114ae4fa7ceSStephan Aßmus 	BBitmap*	fBitmap;
115ae4fa7ceSStephan Aßmus };
116ae4fa7ceSStephan Aßmus 
117ae4fa7ceSStephan Aßmus 
118ae4fa7ceSStephan Aßmus 
11908e109e5SStephan Aßmus // #pragma mark - TestView
12008e109e5SStephan Aßmus 
12108e109e5SStephan Aßmus 
12208e109e5SStephan Aßmus class TestView : public BView {
12308e109e5SStephan Aßmus public:
12408e109e5SStephan Aßmus 								TestView();
12508e109e5SStephan Aßmus 	virtual						~TestView();
12608e109e5SStephan Aßmus 
12708e109e5SStephan Aßmus 	virtual	void				Draw(BRect updateRect);
12808e109e5SStephan Aßmus 
12908e109e5SStephan Aßmus 			void				SetTest(Test* test);
13008e109e5SStephan Aßmus 
13108e109e5SStephan Aßmus private:
13208e109e5SStephan Aßmus 			Test*				fTest;
13308e109e5SStephan Aßmus };
13408e109e5SStephan Aßmus 
13508e109e5SStephan Aßmus 
13608e109e5SStephan Aßmus TestView::TestView()
13708e109e5SStephan Aßmus 	:
13808e109e5SStephan Aßmus 	BView(NULL, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
13908e109e5SStephan Aßmus 	fTest(NULL)
14008e109e5SStephan Aßmus {
14108e109e5SStephan Aßmus }
14208e109e5SStephan Aßmus 
14308e109e5SStephan Aßmus 
14408e109e5SStephan Aßmus TestView::~TestView()
14508e109e5SStephan Aßmus {
14608e109e5SStephan Aßmus }
14708e109e5SStephan Aßmus 
14808e109e5SStephan Aßmus 
14908e109e5SStephan Aßmus void
15008e109e5SStephan Aßmus TestView::Draw(BRect updateRect)
15108e109e5SStephan Aßmus {
15208e109e5SStephan Aßmus 	if (fTest != NULL)
15308e109e5SStephan Aßmus 		fTest->Draw(this, updateRect);
15408e109e5SStephan Aßmus }
15508e109e5SStephan Aßmus 
15608e109e5SStephan Aßmus 
15708e109e5SStephan Aßmus void
15808e109e5SStephan Aßmus TestView::SetTest(Test* test)
15908e109e5SStephan Aßmus {
16008e109e5SStephan Aßmus 	fTest = test;
16108e109e5SStephan Aßmus 	Invalidate();
16208e109e5SStephan Aßmus }
16308e109e5SStephan Aßmus 
16408e109e5SStephan Aßmus 
16508e109e5SStephan Aßmus // #pragma mark - TestWindow
16608e109e5SStephan Aßmus 
16708e109e5SStephan Aßmus 
16808e109e5SStephan Aßmus enum {
16908e109e5SStephan Aßmus 	MSG_SELECT_TEST	= 'stst'
17008e109e5SStephan Aßmus };
17108e109e5SStephan Aßmus 
17208e109e5SStephan Aßmus 
17308e109e5SStephan Aßmus class TestWindow : public BWindow {
17408e109e5SStephan Aßmus public:
17508e109e5SStephan Aßmus 								TestWindow();
17608e109e5SStephan Aßmus 	virtual						~TestWindow();
17708e109e5SStephan Aßmus 
17808e109e5SStephan Aßmus 	virtual	void				MessageReceived(BMessage* message);
17908e109e5SStephan Aßmus 
18008e109e5SStephan Aßmus 			void				AddTest(Test* test);
18108e109e5SStephan Aßmus 			void				SetToTest(int32 index);
18208e109e5SStephan Aßmus 
18308e109e5SStephan Aßmus private:
18408e109e5SStephan Aßmus 			TestView*			fTestView;
18508e109e5SStephan Aßmus 
18608e109e5SStephan Aßmus 			BMenuField*			fTestSelectionField;
18708e109e5SStephan Aßmus 
18808e109e5SStephan Aßmus 			BList				fTests;
18908e109e5SStephan Aßmus };
19008e109e5SStephan Aßmus 
19108e109e5SStephan Aßmus 
19208e109e5SStephan Aßmus TestWindow::TestWindow()
19308e109e5SStephan Aßmus 	:
19408e109e5SStephan Aßmus 	BWindow(BRect(50.0, 50.0, 450.0, 250.0), "Transformations Test",
19508e109e5SStephan Aßmus 		B_DOCUMENT_WINDOW, B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE
19608e109e5SStephan Aßmus 			| B_AUTO_UPDATE_SIZE_LIMITS)
19708e109e5SStephan Aßmus {
19808e109e5SStephan Aßmus 	fTestView = new TestView();
19908e109e5SStephan Aßmus 
20008e109e5SStephan Aßmus 	BScrollView* scrollView = new BScrollView("scroll", fTestView, 0, true,
20108e109e5SStephan Aßmus 		true);
20208e109e5SStephan Aßmus 
20308e109e5SStephan Aßmus 	fTestSelectionField = new BMenuField("test selection",
20408e109e5SStephan Aßmus 		"Select test:", new BPopUpMenu("select"));
20508e109e5SStephan Aßmus 
20608e109e5SStephan Aßmus 	BLayoutBuilder::Group<>(this, B_VERTICAL, 0.0f)
20708e109e5SStephan Aßmus 		.AddGroup(B_HORIZONTAL)
20808e109e5SStephan Aßmus 			.Add(fTestSelectionField)
20908e109e5SStephan Aßmus 			.AddGlue()
21008e109e5SStephan Aßmus 			.SetInsets(B_USE_DEFAULT_SPACING)
21108e109e5SStephan Aßmus 		.End()
21208e109e5SStephan Aßmus 		.Add(scrollView)
21308e109e5SStephan Aßmus 	;
21408e109e5SStephan Aßmus }
21508e109e5SStephan Aßmus 
21608e109e5SStephan Aßmus 
21708e109e5SStephan Aßmus TestWindow::~TestWindow()
21808e109e5SStephan Aßmus {
21908e109e5SStephan Aßmus 	for (int32 i = fTests.CountItems() - 1; i >= 0; i++)
22008e109e5SStephan Aßmus 		delete (Test*)fTests.ItemAt(i);
22108e109e5SStephan Aßmus }
22208e109e5SStephan Aßmus 
22308e109e5SStephan Aßmus 
22408e109e5SStephan Aßmus void
22508e109e5SStephan Aßmus TestWindow::MessageReceived(BMessage* message)
22608e109e5SStephan Aßmus {
22708e109e5SStephan Aßmus 	switch (message->what) {
22808e109e5SStephan Aßmus 		case MSG_SELECT_TEST:
22908e109e5SStephan Aßmus 		{
23008e109e5SStephan Aßmus 			int32 index;
23108e109e5SStephan Aßmus 			if (message->FindInt32("index", &index) == B_OK)
23208e109e5SStephan Aßmus 				SetToTest(index);
23308e109e5SStephan Aßmus 			break;
23408e109e5SStephan Aßmus 		}
23508e109e5SStephan Aßmus 
23608e109e5SStephan Aßmus 		default:
23708e109e5SStephan Aßmus 			BWindow::MessageReceived(message);
23808e109e5SStephan Aßmus 	}
23908e109e5SStephan Aßmus }
24008e109e5SStephan Aßmus 
24108e109e5SStephan Aßmus 
24208e109e5SStephan Aßmus void
24308e109e5SStephan Aßmus TestWindow::AddTest(Test* test)
24408e109e5SStephan Aßmus {
24508e109e5SStephan Aßmus 	if (test == NULL || fTests.HasItem(test))
24608e109e5SStephan Aßmus 		return;
24708e109e5SStephan Aßmus 
24808e109e5SStephan Aßmus 	if (!fTests.AddItem(test)) {
24908e109e5SStephan Aßmus 		delete test;
25008e109e5SStephan Aßmus 		return;
25108e109e5SStephan Aßmus 	}
25208e109e5SStephan Aßmus 
25308e109e5SStephan Aßmus 	BMessage* message = new BMessage(MSG_SELECT_TEST);
25408e109e5SStephan Aßmus 	message->AddInt32("index", fTests.CountItems() - 1);
25508e109e5SStephan Aßmus 
25608e109e5SStephan Aßmus 	BMenuItem* item = new BMenuItem(test->Name(), message);
25708e109e5SStephan Aßmus 	if (!fTestSelectionField->Menu()->AddItem(item)) {
25808e109e5SStephan Aßmus 		fTests.RemoveItem(fTests.CountItems() - 1);
25908e109e5SStephan Aßmus 		delete test;
26008e109e5SStephan Aßmus 		delete item;
26108e109e5SStephan Aßmus 		return;
26208e109e5SStephan Aßmus 	}
26308e109e5SStephan Aßmus 
26408e109e5SStephan Aßmus 	if (fTests.CountItems() == 1)
26508e109e5SStephan Aßmus 		SetToTest(0);
26608e109e5SStephan Aßmus }
26708e109e5SStephan Aßmus 
26808e109e5SStephan Aßmus 
26908e109e5SStephan Aßmus void
27008e109e5SStephan Aßmus TestWindow::SetToTest(int32 index)
27108e109e5SStephan Aßmus {
27208e109e5SStephan Aßmus 	Test* test = (Test*)fTests.ItemAt(index);
27308e109e5SStephan Aßmus 	if (test == NULL)
27408e109e5SStephan Aßmus 		return;
27508e109e5SStephan Aßmus 
27608e109e5SStephan Aßmus 	fTestSelectionField->Menu()->ItemAt(index)->SetMarked(true);
27708e109e5SStephan Aßmus 
27808e109e5SStephan Aßmus 	fTestView->SetTest(test);
27908e109e5SStephan Aßmus }
28008e109e5SStephan Aßmus 
28108e109e5SStephan Aßmus 
28208e109e5SStephan Aßmus // #pragma mark - Test1
28308e109e5SStephan Aßmus 
28408e109e5SStephan Aßmus 
28508e109e5SStephan Aßmus class RectsTest : public Test {
28608e109e5SStephan Aßmus public:
28708e109e5SStephan Aßmus 	RectsTest()
28808e109e5SStephan Aßmus 		:
28908e109e5SStephan Aßmus 		Test("Rects")
29008e109e5SStephan Aßmus 	{
29108e109e5SStephan Aßmus 	}
29208e109e5SStephan Aßmus 
29308e109e5SStephan Aßmus 	virtual void Draw(BView* view, BRect updateRect)
29408e109e5SStephan Aßmus 	{
29508e109e5SStephan Aßmus 		view->DrawString("Rects", BPoint(20, 30));
29608e109e5SStephan Aßmus 
29708e109e5SStephan Aßmus 		view->SetDrawingMode(B_OP_ALPHA);
29808e109e5SStephan Aßmus 		view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
29908e109e5SStephan Aßmus 
30008e109e5SStephan Aßmus 		BRect rect(view->Bounds());
3012f9ac958SAdrien Destugues 		rect.OffsetTo(B_ORIGIN);
3022f9ac958SAdrien Destugues 
30308e109e5SStephan Aßmus 		rect.InsetBy(rect.Width() / 3, rect.Height() / 3);
30408e109e5SStephan Aßmus 		BPoint center(
30508e109e5SStephan Aßmus 			rect.left + rect.Width() / 2,
30608e109e5SStephan Aßmus 			rect.top + rect.Height() / 2);
30708e109e5SStephan Aßmus 
308d93591ffSStephan Aßmus 		for (int32 i = 0; i < 360; i += 40) {
30908e109e5SStephan Aßmus 			BAffineTransform transform;
31008e109e5SStephan Aßmus 			transform.RotateBy(center, i * M_PI / 180.0);
31108e109e5SStephan Aßmus 			view->SetTransform(transform);
312d93591ffSStephan Aßmus 
313d93591ffSStephan Aßmus 			view->SetHighColor(51, 151, 255, 20);
31408e109e5SStephan Aßmus 			view->FillRect(rect);
315d93591ffSStephan Aßmus 
316d93591ffSStephan Aßmus 			view->SetHighColor(51, 255, 151, 180);
317d93591ffSStephan Aßmus 			view->DrawString("Rect", center);
31808e109e5SStephan Aßmus 		}
31908e109e5SStephan Aßmus 	}
32008e109e5SStephan Aßmus };
32108e109e5SStephan Aßmus 
32208e109e5SStephan Aßmus 
323ae4fa7ceSStephan Aßmus // #pragma mark - AlphaMaskBitmapTest
32405a19d41SStephan Aßmus 
32505a19d41SStephan Aßmus 
326ae4fa7ceSStephan Aßmus class AlphaMaskBitmapTest : public BitmapTest {
32705a19d41SStephan Aßmus public:
328ae4fa7ceSStephan Aßmus 	AlphaMaskBitmapTest()
32905a19d41SStephan Aßmus 		:
330ae4fa7ceSStephan Aßmus 		BitmapTest("Alpha Masked Bitmap")
33105a19d41SStephan Aßmus 	{
33205a19d41SStephan Aßmus 	}
33305a19d41SStephan Aßmus 
33405a19d41SStephan Aßmus 	virtual void Draw(BView* view, BRect updateRect)
33505a19d41SStephan Aßmus 	{
33605a19d41SStephan Aßmus 		BRect rect(view->Bounds());
33705a19d41SStephan Aßmus 
33805a19d41SStephan Aßmus 		if (fBitmap == NULL) {
33905a19d41SStephan Aßmus 			view->SetHighColor(255, 0, 0);
34005a19d41SStephan Aßmus 			view->FillRect(rect);
34105a19d41SStephan Aßmus 			view->SetHighColor(0, 0, 0);
34205a19d41SStephan Aßmus 			view->DrawString("Failed to load the bitmap.", BPoint(20, 20));
34305a19d41SStephan Aßmus 			return;
34405a19d41SStephan Aßmus 		}
34505a19d41SStephan Aßmus 
34605a19d41SStephan Aßmus 		rect.left = (rect.Width() - fBitmap->Bounds().Width()) / 2;
34705a19d41SStephan Aßmus 		rect.top = (rect.Height() - fBitmap->Bounds().Height()) / 2;
34805a19d41SStephan Aßmus 		rect.right = rect.left + fBitmap->Bounds().Width();
34905a19d41SStephan Aßmus 		rect.bottom = rect.top + fBitmap->Bounds().Height();
35005a19d41SStephan Aßmus 
35105a19d41SStephan Aßmus 		BPoint center(
35205a19d41SStephan Aßmus 			rect.left + rect.Width() / 2,
35305a19d41SStephan Aßmus 			rect.top + rect.Height() / 2);
35405a19d41SStephan Aßmus 
35505a19d41SStephan Aßmus 		BPicture picture;
35605a19d41SStephan Aßmus 		view->BeginPicture(&picture);
35705a19d41SStephan Aßmus 		view->SetDrawingMode(B_OP_ALPHA);
35805a19d41SStephan Aßmus 		view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE);
35905a19d41SStephan Aßmus 		BFont font;
36005a19d41SStephan Aßmus 		view->GetFont(&font);
36105a19d41SStephan Aßmus 		font.SetSize(70);
36205a19d41SStephan Aßmus 		view->SetFont(&font);
36305a19d41SStephan Aßmus 		view->SetHighColor(0, 0, 0, 80);
36405a19d41SStephan Aßmus 		view->FillRect(view->Bounds());
36505a19d41SStephan Aßmus 		view->SetHighColor(0, 0, 0, 255);
36605a19d41SStephan Aßmus 		view->DrawString("CLIPPING", BPoint(0, center.y + 35));
36705a19d41SStephan Aßmus 		view->EndPicture();
36805a19d41SStephan Aßmus 
36905a19d41SStephan Aßmus 		view->ClipToPicture(&picture);
37005a19d41SStephan Aßmus 
37105a19d41SStephan Aßmus 		BAffineTransform transform;
37205a19d41SStephan Aßmus 			transform.RotateBy(center, 30 * M_PI / 180.0);
37305a19d41SStephan Aßmus 			view->SetTransform(transform);
37405a19d41SStephan Aßmus 
37505a19d41SStephan Aßmus 		view->DrawBitmap(fBitmap, fBitmap->Bounds(), rect);
37605a19d41SStephan Aßmus 	}
37705a19d41SStephan Aßmus };
37805a19d41SStephan Aßmus 
37905a19d41SStephan Aßmus 
380e966330cSStephan Aßmus // #pragma mark - Gradient
381e966330cSStephan Aßmus 
382e966330cSStephan Aßmus 
383e966330cSStephan Aßmus class GradientTest : public Test {
384e966330cSStephan Aßmus public:
385e966330cSStephan Aßmus 	GradientTest()
386e966330cSStephan Aßmus 		:
387e966330cSStephan Aßmus 		Test("Gradient")
388e966330cSStephan Aßmus 	{
389e966330cSStephan Aßmus 	}
390e966330cSStephan Aßmus 
391e966330cSStephan Aßmus 	virtual void Draw(BView* view, BRect updateRect)
392e966330cSStephan Aßmus 	{
393e966330cSStephan Aßmus 		BRect rect(view->Bounds());
394e966330cSStephan Aßmus 		rect.InsetBy(rect.Width() / 3, rect.Height() / 3);
395e966330cSStephan Aßmus 		BPoint center(
396e966330cSStephan Aßmus 			rect.left + rect.Width() / 2,
397e966330cSStephan Aßmus 			rect.top + rect.Height() / 2);
398e966330cSStephan Aßmus 
399e966330cSStephan Aßmus 		BAffineTransform transform;
400e966330cSStephan Aßmus 		transform.RotateBy(center, 30.0 * M_PI / 180.0);
401e966330cSStephan Aßmus 		view->SetTransform(transform);
402e966330cSStephan Aßmus 
403e966330cSStephan Aßmus 		rgb_color top = (rgb_color){ 255, 255, 0, 255 };
404e966330cSStephan Aßmus 		rgb_color bottom = (rgb_color){ 0, 255, 255, 255 };
405e966330cSStephan Aßmus 
406e966330cSStephan Aßmus 		BGradientLinear gradient;
407e966330cSStephan Aßmus 		gradient.AddColor(top, 0.0f);
408e966330cSStephan Aßmus 		gradient.AddColor(bottom, 255.0f);
409e966330cSStephan Aßmus 		gradient.SetStart(rect.LeftTop());
410e966330cSStephan Aßmus 		gradient.SetEnd(rect.LeftBottom());
411e966330cSStephan Aßmus 
412e966330cSStephan Aßmus 		float radius = std::min(rect.Width() / 5, rect.Height() / 5);
413e966330cSStephan Aßmus 
414e966330cSStephan Aßmus 		view->FillRoundRect(rect, radius, radius, gradient);
415e966330cSStephan Aßmus 	}
416e966330cSStephan Aßmus };
41705a19d41SStephan Aßmus 
41805a19d41SStephan Aßmus 
4199f44851eSStephan Aßmus // #pragma mark - NestedStates
4209f44851eSStephan Aßmus 
4219f44851eSStephan Aßmus 
4229f44851eSStephan Aßmus class NestedStatesTest : public Test {
4239f44851eSStephan Aßmus public:
4249f44851eSStephan Aßmus 	NestedStatesTest()
4259f44851eSStephan Aßmus 		:
4269f44851eSStephan Aßmus 		Test("Nested view states")
4279f44851eSStephan Aßmus 	{
4289f44851eSStephan Aßmus 	}
4299f44851eSStephan Aßmus 
4309f44851eSStephan Aßmus 	virtual void Draw(BView* view, BRect updateRect)
4319f44851eSStephan Aßmus 	{
4329f44851eSStephan Aßmus 		BAffineTransform transform;
4339f44851eSStephan Aßmus 		transform.RotateBy(BPoint(100, 100), 30.0 * M_PI / 180.0);
4349f44851eSStephan Aßmus 		view->SetTransform(transform);
4359f44851eSStephan Aßmus 
4369f44851eSStephan Aßmus 		rgb_color top = (rgb_color){ 255, 0, 0, 255 };
4379f44851eSStephan Aßmus 		rgb_color bottom = (rgb_color){ 255, 255, 0, 255 };
4389f44851eSStephan Aßmus 
4399f44851eSStephan Aßmus 		BRect rect(20, 20, 120, 120);
4409f44851eSStephan Aßmus 
4419f44851eSStephan Aßmus 		BGradientLinear gradient;
4429f44851eSStephan Aßmus 		gradient.AddColor(top, 0.0f);
4439f44851eSStephan Aßmus 		gradient.AddColor(bottom, 255.0f);
4449f44851eSStephan Aßmus 		gradient.SetStart(rect.LeftTop());
4459f44851eSStephan Aßmus 		gradient.SetEnd(rect.LeftBottom());
4469f44851eSStephan Aßmus 
4479f44851eSStephan Aßmus 		view->FillRoundRect(rect, 20, 20, gradient);
4489f44851eSStephan Aßmus 
4499f44851eSStephan Aßmus 		view->PushState();
4509f44851eSStephan Aßmus 		// Should be in the same place!
4519f44851eSStephan Aßmus 		view->StrokeRoundRect(rect, 20, 20);
4529f44851eSStephan Aßmus 
4539f44851eSStephan Aßmus 		// Now rotated by another 30 degree
4549f44851eSStephan Aßmus 		view->SetTransform(transform);
4559f44851eSStephan Aßmus 
4569f44851eSStephan Aßmus 		view->SetDrawingMode(B_OP_ALPHA);
4579f44851eSStephan Aßmus 		view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE);
4589f44851eSStephan Aßmus 		view->SetHighColor(0, 0, 255, 120);
4599f44851eSStephan Aßmus 		view->FillRoundRect(rect, 20, 20);
4609f44851eSStephan Aßmus 
4619f44851eSStephan Aßmus 		view->PopState();
4629f44851eSStephan Aßmus 	}
4639f44851eSStephan Aßmus };
4649f44851eSStephan Aßmus 
4659f44851eSStephan Aßmus 
4662f9ac958SAdrien Destugues // #pragma mark - Clipping
4672f9ac958SAdrien Destugues 
4682f9ac958SAdrien Destugues 
4692f9ac958SAdrien Destugues class ClippingTest : public Test {
4702f9ac958SAdrien Destugues public:
4712f9ac958SAdrien Destugues 	ClippingTest()
4722f9ac958SAdrien Destugues 		:
4732f9ac958SAdrien Destugues 		Test("View bounds clipping")
4742f9ac958SAdrien Destugues 	{
4752f9ac958SAdrien Destugues 	}
4762f9ac958SAdrien Destugues 
4772f9ac958SAdrien Destugues 	virtual void Draw(BView* view, BRect updateRect)
4782f9ac958SAdrien Destugues 	{
4792f9ac958SAdrien Destugues 		BRect r (20, 20, 50, 50);
4802f9ac958SAdrien Destugues 		view->SetHighColor(ui_color(B_FAILURE_COLOR));
4812f9ac958SAdrien Destugues 		view->FillRect(r);
4822f9ac958SAdrien Destugues 
4832f9ac958SAdrien Destugues 		BAffineTransform transform;
4842f9ac958SAdrien Destugues 		transform.TranslateBy(400, 400);
4852f9ac958SAdrien Destugues 		view->SetTransform(transform);
4862f9ac958SAdrien Destugues 
4872f9ac958SAdrien Destugues 		// Make sure this rectangle is drawn, even when the original one is out
4882f9ac958SAdrien Destugues 		// of the view bounds (for example because of scrolling).
4892f9ac958SAdrien Destugues 		view->SetHighColor(ui_color(B_SUCCESS_COLOR));
4902f9ac958SAdrien Destugues 		view->FillRect(r);
4912f9ac958SAdrien Destugues 	}
4922f9ac958SAdrien Destugues };
4932f9ac958SAdrien Destugues 
4942f9ac958SAdrien Destugues 
495b6c34f4cSAdrien Destugues // #pragma mark - Clipping
496b6c34f4cSAdrien Destugues 
497b6c34f4cSAdrien Destugues 
498b6c34f4cSAdrien Destugues class TextClippingTest : public Test {
499b6c34f4cSAdrien Destugues public:
500b6c34f4cSAdrien Destugues 	TextClippingTest()
501b6c34f4cSAdrien Destugues 		:
502b6c34f4cSAdrien Destugues 		Test("Text clipping")
503b6c34f4cSAdrien Destugues 	{
504b6c34f4cSAdrien Destugues 	}
505b6c34f4cSAdrien Destugues 
506b6c34f4cSAdrien Destugues 	virtual void Draw(BView* view, BRect updateRect)
507b6c34f4cSAdrien Destugues 	{
508b6c34f4cSAdrien Destugues 		BFont font;
509b6c34f4cSAdrien Destugues 		view->GetFont(&font);
510b6c34f4cSAdrien Destugues 		font.SetSize(70);
511b6c34f4cSAdrien Destugues 		view->SetFont(&font);
512b6c34f4cSAdrien Destugues 
513b6c34f4cSAdrien Destugues 		float width = view->Bounds().Width();
514b6c34f4cSAdrien Destugues 
515b6c34f4cSAdrien Destugues 		// The translation make the text, which has negative coordinates, be
516b6c34f4cSAdrien Destugues 		// visible inside the viewport.
517b6c34f4cSAdrien Destugues 		BAffineTransform transform;
518b6c34f4cSAdrien Destugues 		transform.TranslateBy(width, 0);
519b6c34f4cSAdrien Destugues 		view->SetTransform(transform);
520b6c34f4cSAdrien Destugues 
521b6c34f4cSAdrien Destugues 		const char* str = "CLIPPING";
522b6c34f4cSAdrien Destugues 
523b6c34f4cSAdrien Destugues 		// Test the standard DrawString method
524b6c34f4cSAdrien Destugues 
525b6c34f4cSAdrien Destugues 		// Draw the text bounds
526b6c34f4cSAdrien Destugues 		float size = view->StringWidth(str);
527b6c34f4cSAdrien Destugues 		BRect r(-width, 0, size - width, 70);
528b6c34f4cSAdrien Destugues 		view->SetHighColor(ui_color(B_SUCCESS_COLOR));
529b6c34f4cSAdrien Destugues 		view->FillRect(r);
530b6c34f4cSAdrien Destugues 
531b6c34f4cSAdrien Destugues 		// Draw the text (which should fit inside the bounds rectangle)
532b6c34f4cSAdrien Destugues 		view->SetHighColor(0, 0, 0, 255);
533b6c34f4cSAdrien Destugues 		view->DrawString(str, BPoint(-width, 70));
534b6c34f4cSAdrien Destugues 
535b6c34f4cSAdrien Destugues 		// Test with offset-based DrawString
536b6c34f4cSAdrien Destugues 		BPoint offsets[strlen(str)];
537b6c34f4cSAdrien Destugues 		for(unsigned int i = 0; i < strlen(str); i++)
538b6c34f4cSAdrien Destugues 		{
539b6c34f4cSAdrien Destugues 			offsets[i].x = i * 35 - width;
540b6c34f4cSAdrien Destugues 			offsets[i].y = 145;
541b6c34f4cSAdrien Destugues 		}
542b6c34f4cSAdrien Destugues 
543b6c34f4cSAdrien Destugues 		// Draw the text bounds
544b6c34f4cSAdrien Destugues 		view->SetHighColor(ui_color(B_SUCCESS_COLOR));
545b6c34f4cSAdrien Destugues 		r = BRect(offsets[0], offsets[strlen(str) - 1]);
546b6c34f4cSAdrien Destugues 		r.top = 75;
547b6c34f4cSAdrien Destugues 		view->FillRect(r);
548b6c34f4cSAdrien Destugues 
549b6c34f4cSAdrien Destugues 		// Draw the text (which should fit inside the bounds rectangle)
550b6c34f4cSAdrien Destugues 		view->SetHighColor(0, 0, 0, 255);
551b6c34f4cSAdrien Destugues 		view->DrawString(str, offsets, strlen(str));
552b6c34f4cSAdrien Destugues 
553b6c34f4cSAdrien Destugues 	}
554b6c34f4cSAdrien Destugues };
555b6c34f4cSAdrien Destugues 
556b6c34f4cSAdrien Destugues 
557ae4fa7ceSStephan Aßmus // #pragma mark - BitmapClipTest
558569bd922SAdrien Destugues 
559569bd922SAdrien Destugues 
560ae4fa7ceSStephan Aßmus class BitmapClipTest : public BitmapTest {
561569bd922SAdrien Destugues public:
562569bd922SAdrien Destugues 	BitmapClipTest()
563569bd922SAdrien Destugues 		:
564ae4fa7ceSStephan Aßmus 		BitmapTest("Bitmap clipping")
565569bd922SAdrien Destugues 	{
566569bd922SAdrien Destugues 	}
567569bd922SAdrien Destugues 
568569bd922SAdrien Destugues 	virtual void Draw(BView* view, BRect updateRect)
569569bd922SAdrien Destugues 	{
570569bd922SAdrien Destugues 		BRect rect(view->Bounds());
571569bd922SAdrien Destugues 
572569bd922SAdrien Destugues 		if (fBitmap == NULL) {
573569bd922SAdrien Destugues 			view->SetHighColor(255, 0, 0);
574569bd922SAdrien Destugues 			view->FillRect(rect);
575569bd922SAdrien Destugues 			view->SetHighColor(0, 0, 0);
576569bd922SAdrien Destugues 			view->DrawString("Failed to load the bitmap.", BPoint(20, 20));
577569bd922SAdrien Destugues 			return;
578569bd922SAdrien Destugues 		}
579569bd922SAdrien Destugues 
580569bd922SAdrien Destugues 		rect = fBitmap->Bounds();
581569bd922SAdrien Destugues 
582569bd922SAdrien Destugues 		view->SetHighColor(ui_color(B_FAILURE_COLOR));
583569bd922SAdrien Destugues 		view->FillRect(rect);
584569bd922SAdrien Destugues 
585569bd922SAdrien Destugues 		// The rect offset should compensate the transform translation, so the
586b6c34f4cSAdrien Destugues 		// bitmap should be drawn at the view origin. It will then exactly
587b6c34f4cSAdrien Destugues 		// cover the red rectangle, which should not be visible anymore.
588569bd922SAdrien Destugues 		rect.OffsetBy(0, 40);
589569bd922SAdrien Destugues 
590569bd922SAdrien Destugues 		BAffineTransform transform;
591569bd922SAdrien Destugues 			transform.TranslateBy(0, -40);
592569bd922SAdrien Destugues 		view->SetTransform(transform);
593569bd922SAdrien Destugues 
594569bd922SAdrien Destugues 		view->DrawBitmap(fBitmap, fBitmap->Bounds(), rect);
595569bd922SAdrien Destugues 	}
596569bd922SAdrien Destugues };
597569bd922SAdrien Destugues 
598569bd922SAdrien Destugues 
599*a4a2abe0SAdrien Destugues // #pragma mark - PixelAlignTest
600*a4a2abe0SAdrien Destugues 
601*a4a2abe0SAdrien Destugues 
602*a4a2abe0SAdrien Destugues class PixelAlignTest : public Test {
603*a4a2abe0SAdrien Destugues public:
604*a4a2abe0SAdrien Destugues 	PixelAlignTest()
605*a4a2abe0SAdrien Destugues 		:
606*a4a2abe0SAdrien Destugues 		Test("Pixel alignment")
607*a4a2abe0SAdrien Destugues 	{
608*a4a2abe0SAdrien Destugues 	}
609*a4a2abe0SAdrien Destugues 
610*a4a2abe0SAdrien Destugues 	virtual void Draw(BView* view, BRect updateRect)
611*a4a2abe0SAdrien Destugues 	{
612*a4a2abe0SAdrien Destugues 		BRect rect(20, 20, 120, 120);
613*a4a2abe0SAdrien Destugues 		view->SetHighColor(ui_color(B_SUCCESS_COLOR));
614*a4a2abe0SAdrien Destugues 		view->StrokeRect(rect);
615*a4a2abe0SAdrien Destugues 
616*a4a2abe0SAdrien Destugues 		BAffineTransform transform;
617*a4a2abe0SAdrien Destugues 			transform.TranslateBy(140, 0);
618*a4a2abe0SAdrien Destugues 		view->SetTransform(transform);
619*a4a2abe0SAdrien Destugues 
620*a4a2abe0SAdrien Destugues 		// Translating a pixel-aligned rectangle by an integer number of
621*a4a2abe0SAdrien Destugues 		// pixels should result in a pixel-aligned rectangle.
622*a4a2abe0SAdrien Destugues 		view->SetHighColor(ui_color(B_FAILURE_COLOR));
623*a4a2abe0SAdrien Destugues 		view->StrokeRect(rect);
624*a4a2abe0SAdrien Destugues 	}
625*a4a2abe0SAdrien Destugues };
626*a4a2abe0SAdrien Destugues 
627*a4a2abe0SAdrien Destugues 
62808e109e5SStephan Aßmus // #pragma mark -
62908e109e5SStephan Aßmus 
63008e109e5SStephan Aßmus 
63108e109e5SStephan Aßmus int
63208e109e5SStephan Aßmus main(int argc, char** argv)
63308e109e5SStephan Aßmus {
63408e109e5SStephan Aßmus 	BApplication app(kAppSignature);
63508e109e5SStephan Aßmus 
63608e109e5SStephan Aßmus 	TestWindow* window = new TestWindow();
63708e109e5SStephan Aßmus 
63808e109e5SStephan Aßmus 	window->AddTest(new RectsTest());
639569bd922SAdrien Destugues 	window->AddTest(new BitmapClipTest());
640b6c34f4cSAdrien Destugues 	window->AddTest(new TextClippingTest());
641ae4fa7ceSStephan Aßmus 	window->AddTest(new AlphaMaskBitmapTest());
642e966330cSStephan Aßmus 	window->AddTest(new GradientTest());
6439f44851eSStephan Aßmus 	window->AddTest(new NestedStatesTest());
6442f9ac958SAdrien Destugues 	window->AddTest(new ClippingTest());
645*a4a2abe0SAdrien Destugues 	window->AddTest(new PixelAlignTest());
64608e109e5SStephan Aßmus 
647b6c34f4cSAdrien Destugues 	window->SetToTest(2);
64808e109e5SStephan Aßmus 	window->Show();
64908e109e5SStephan Aßmus 
65008e109e5SStephan Aßmus 	app.Run();
65108e109e5SStephan Aßmus 	return 0;
65208e109e5SStephan Aßmus }
653