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