#include #include #include #include #include #include #include #include typedef void (*clipper)(BView*, BRect, bool); typedef void (*test)(BView*, clipper); static const BRect bigRect(-1000,-1000, 1000,1000); static const BRect baseRect(-25,-10, 25,10); static const BRect corner(-25,-10, -15,0); static const BRect crossRect(-5,-35, 5,40); static void rectClipper(BView* view, BRect rect, bool inverse) { if (inverse) view->ClipToInverseRect(rect); else view->ClipToRect(rect); } static void pictureClipper(BView* view, BRect rect, bool inverse) { BPicture p; view->BeginPicture(&p); view->FillEllipse(rect); view->SetHighColor(0, 0, 0, 0); view->FillEllipse(rect.InsetByCopy(rect.Width()/4, rect.Height()/4)); view->EndPicture(); if (inverse) view->ClipToInversePicture(&p); else view->ClipToPicture(&p); } static void shapeClipper(BView* view, BRect rect, bool inverse) { BShape s; s.MoveTo(rect.LeftTop()); s.LineTo(rect.RightBottom()); s.ArcTo(rect.Width()/4, rect.Height()/4, 0, false, true, rect.RightTop()); s.LineTo(rect.LeftBottom()); s.Close(); if (inverse) view->ClipToInverseShape(&s); else view->ClipToShape(&s); } static void testBase(BView* view, clipper clip, bool inverse) { clip(view, baseRect, inverse); view->SetHighColor(255,0,0); view->FillRect(bigRect); } static void testBaseDirect(BView* view, clipper clip) { testBase(view, clip, false); } static void testBaseInverse(BView* view, clipper clip) { testBase(view, clip, true); } static void testCross(BView* view, clipper clip, bool inverse) { clip(view, crossRect, inverse); view->SetHighColor(0,0,255); view->FillRect(bigRect); } static void testCorner(BView* view, clipper clip, bool inverse) { clip(view, corner, inverse); view->SetHighColor(0,255,0); view->FillRect(bigRect); } static void testCross00(BView* view, clipper clip) { testBase(view, clip, false); testCross(view, clip, false); } static void testCross01(BView* view, clipper clip) { testBase(view, clip, false); testCross(view, clip, true); } static void testCross10(BView* view, clipper clip) { testBase(view, clip, true); testCross(view, clip, false); } static void testCross11(BView* view, clipper clip) { testBase(view, clip, true); testCross(view, clip, true); } static void test3000(BView* view, clipper clip) { testBase(view, clip, false); testCorner(view, clip, false); testCross(view, clip, false); } static void test3001(BView* view, clipper clip) { testBase(view, clip, false); testCorner(view, clip, false); testCross(view, clip, true); } static void test3010(BView* view, clipper clip) { testBase(view, clip, false); testCorner(view, clip, true); testCross(view, clip, false); } static void test3011(BView* view, clipper clip) { testBase(view, clip, false); testCorner(view, clip, true); testCross(view, clip, true); } static void test3100(BView* view, clipper clip) { testBase(view, clip, true); testCorner(view, clip, false); testCross(view, clip, false); } static void test3101(BView* view, clipper clip) { testBase(view, clip, true); testCorner(view, clip, false); testCross(view, clip, true); } static void test3110(BView* view, clipper clip) { testBase(view, clip, true); testCorner(view, clip, true); testCross(view, clip, false); } static void test3111(BView* view, clipper clip) { testBase(view, clip, true); testCorner(view, clip, true); testCross(view, clip, true); } static const test tests[] = { testBaseDirect, testBaseInverse, testCross00, testCross01, testCross10, testCross11, test3000, test3001, test3010, test3011, test3100, test3101, test3110, test3111 }; class View : public BView { public: View(const char* name, test, clipper); void Draw(BRect); void AttachedToWindow(); private: test fTest; clipper fClipper; }; View::View(const char* name, test fTest, clipper fClipper) : BView(BRect(0,0, 100,100), name, 0, B_WILL_DRAW), fTest(fTest), fClipper(fClipper) { } void View::AttachedToWindow() { BView::AttachedToWindow(); TranslateBy(50, 50); } void View::Draw(BRect) { fTest(this, fClipper); } class App : public BApplication { public: App(); }; App::App() : BApplication("application/x-vnd.Haiku-Test_inverse_clip") { BWindow* window = new BWindow(BRect(100,100, 800,400), "clip test", B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE); BGridView* grid = new BGridView(); grid->SetResizingMode(B_FOLLOW_ALL_SIDES); BLayoutBuilder::Grid<> layout(grid); layout.SetInsets(B_USE_DEFAULT_SPACING); int testsCount = B_COUNT_OF(tests); for (int i = 0; i < testsCount; i++) { layout.Add(new View("region", tests[i], rectClipper), 0, i); layout.Add(new View("rotate", tests[i], rectClipper), 1, i); // This one changes from Region to Shape clipping layout.Add(new View("picture", tests[i], pictureClipper), 2, i); layout.Add(new View("rotate", tests[i], pictureClipper), 3, i); layout.Add(new View("shape", tests[i], shapeClipper), 4, i); layout.Add(new View("rotate", tests[i], shapeClipper), 5, i); } BScrollView* scroll = new BScrollView("scroll", grid, B_FOLLOW_ALL_SIDES, 0, true, true, B_NO_BORDER); window->AddChild(scroll); BRect bounds(window->Bounds()); scroll->ResizeTo(bounds.Width(), bounds.Height()); BView* rotate; while ((rotate = window->FindView("rotate")) != NULL) { rotate->RotateBy(0.78); rotate->SetName("rotated"); } window->Show(); } int main() { App app; app.Run(); return 0; }