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