hrev47230 adds 3 changesets to branch 'master' old head: a8f9011015d0a7b00d0fd0772ede3e9fec6347e0 new head: 2f9ac9582db33ca8eb53261f19486abfa98b41c1 overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=2f9ac95+%5Ea8f9011 ---------------------------------------------------------------------------- 66bce82: CID 1210936: use after free. 79eb23a: Fix handling of filled rectangles with transforms. The DrawingEngine didn't properly make a distinction between the rectangle being filled and the damaged region on screen. This led to unexpected results when using BAffineTransform. 2f9ac95: Transformation: add one more test * Add test for a translation that makes things that are out of view bounds to become visible * Fix the "rectangles" test to handle scrolling of the view. It seems that in some cases some of the rectangles are not drawn. The gradient and bitmap tests currently have problem with view scrolling, but I'm not sure why. [ Adrien Destugues <pulkomandy@xxxxxxxxxxxxx> ] ---------------------------------------------------------------------------- 3 files changed, 86 insertions(+), 36 deletions(-) src/apps/terminal/TermView.cpp | 4 +- src/servers/app/drawing/DrawingEngine.cpp | 86 ++++++++++++++--------- src/tests/servers/app/transformation/main.cpp | 32 +++++++++ ############################################################################ Commit: 66bce8233aa664cfb6ac31fb234a0cf4950e585e URL: http://cgit.haiku-os.org/haiku/commit/?id=66bce82 Author: Adrien Destugues <pulkomandy@xxxxxxxxxxxxx> Date: Fri May 16 07:17:15 2014 UTC CID 1210936: use after free. ---------------------------------------------------------------------------- diff --git a/src/apps/terminal/TermView.cpp b/src/apps/terminal/TermView.cpp index 8bd3616..f06ab5f 100644 --- a/src/apps/terminal/TermView.cpp +++ b/src/apps/terminal/TermView.cpp @@ -2601,10 +2601,10 @@ TermView::_AddHighlight(Highlight* highlight) void TermView::_RemoveHighlight(Highlight* highlight) { - fHighlights.RemoveItem(highlight); - if (!highlight->IsEmpty()) _InvalidateTextRange(highlight->Start(), highlight->End()); + + fHighlights.RemoveItem(highlight); } ############################################################################ Commit: 79eb23a82dfd137b0a8f2a70058463f6d7a3b476 URL: http://cgit.haiku-os.org/haiku/commit/?id=79eb23a Author: Adrien Destugues <pulkomandy@xxxxxxxxxxxxx> Date: Mon May 19 11:18:45 2014 UTC Fix handling of filled rectangles with transforms. The DrawingEngine didn't properly make a distinction between the rectangle being filled and the damaged region on screen. This led to unexpected results when using BAffineTransform. ---------------------------------------------------------------------------- diff --git a/src/servers/app/drawing/DrawingEngine.cpp b/src/servers/app/drawing/DrawingEngine.cpp index e37ad03..a07a255 100644 --- a/src/servers/app/drawing/DrawingEngine.cpp +++ b/src/servers/app/drawing/DrawingEngine.cpp @@ -963,49 +963,62 @@ DrawingEngine::FillRect(BRect r) ASSERT_PARALLEL_LOCKED(); make_rect_valid(r); - r = fPainter->TransformAlignAndClipRect(r); - if (!r.IsValid()) + r.left = floorf(r.left); + r.top = floorf(r.top); + r.right = ceilf(r.right); + r.bottom = ceilf(r.bottom); + + BRect dirty = fPainter->TransformAndClipRect(r); + if (!dirty.IsValid()) return; AutoFloatingOverlaysHider overlaysHider(fGraphicsCard, r); bool doInSoftware = true; - if ((r.Width() + 1) * (r.Height() + 1) > 100.0) { - // try hardware optimized version first - // if the rect is large enough - if ((fAvailableHWAccleration & HW_ACC_FILL_REGION) != 0) { - if (fPainter->Pattern() == B_SOLID_HIGH - && (fPainter->DrawingMode() == B_OP_COPY - || fPainter->DrawingMode() == B_OP_OVER)) { - BRegion region(r); - region.IntersectWith(fPainter->ClippingRegion()); - fGraphicsCard->FillRegion(region, fPainter->HighColor(), - fSuspendSyncLevel == 0 || overlaysHider.WasHidden()); - doInSoftware = false; - } else if (fPainter->Pattern() == B_SOLID_LOW - && fPainter->DrawingMode() == B_OP_COPY) { - BRegion region(r); - region.IntersectWith(fPainter->ClippingRegion()); - fGraphicsCard->FillRegion(region, fPainter->LowColor(), - fSuspendSyncLevel == 0 || overlaysHider.WasHidden()); - doInSoftware = false; + + if (fPainter->IsIdentityTransform()) + { + // TODO the accelerated code path may also be used for transforms that + // only scale and translate (but don't shear or rotate). + + if ((r.Width() + 1) * (r.Height() + 1) > 100.0) { + // try hardware optimized version first + // if the rect is large enough + if ((fAvailableHWAccleration & HW_ACC_FILL_REGION) != 0) { + if (fPainter->Pattern() == B_SOLID_HIGH + && (fPainter->DrawingMode() == B_OP_COPY + || fPainter->DrawingMode() == B_OP_OVER)) { + BRegion region(r); + region.IntersectWith(fPainter->ClippingRegion()); + fGraphicsCard->FillRegion(region, fPainter->HighColor(), + fSuspendSyncLevel == 0 || overlaysHider.WasHidden()); + doInSoftware = false; + } else if (fPainter->Pattern() == B_SOLID_LOW + && fPainter->DrawingMode() == B_OP_COPY) { + BRegion region(r); + region.IntersectWith(fPainter->ClippingRegion()); + fGraphicsCard->FillRegion(region, fPainter->LowColor(), + fSuspendSyncLevel == 0 || overlaysHider.WasHidden()); + doInSoftware = false; + } } } - } - if (doInSoftware && (fAvailableHWAccleration & HW_ACC_INVERT_REGION) != 0 - && fPainter->Pattern() == B_SOLID_HIGH - && fPainter->DrawingMode() == B_OP_INVERT) { - BRegion region(r); - region.IntersectWith(fPainter->ClippingRegion()); - fGraphicsCard->InvertRegion(region); - doInSoftware = false; + if (doInSoftware + && (fAvailableHWAccleration & HW_ACC_INVERT_REGION) != 0 + && fPainter->Pattern() == B_SOLID_HIGH + && fPainter->DrawingMode() == B_OP_INVERT) { + BRegion region(r); + region.IntersectWith(fPainter->ClippingRegion()); + fGraphicsCard->InvertRegion(region); + doInSoftware = false; + } } if (doInSoftware) fPainter->FillRect(r); - _CopyToFront(r); + _CopyToFront(dirty); } @@ -1015,15 +1028,20 @@ DrawingEngine::FillRect(BRect r, const BGradient& gradient) ASSERT_PARALLEL_LOCKED(); make_rect_valid(r); - r = fPainter->TransformAlignAndClipRect(r); - if (!r.IsValid()) + r.left = floorf(r.left); + r.top = floorf(r.top); + r.right = ceilf(r.right); + r.bottom = ceilf(r.bottom); + + BRect dirty = fPainter->TransformAndClipRect(r); + if (!dirty.IsValid()) return; - AutoFloatingOverlaysHider overlaysHider(fGraphicsCard, r); + AutoFloatingOverlaysHider overlaysHider(fGraphicsCard, dirty); fPainter->FillRect(r, gradient); - _CopyToFront(r); + _CopyToFront(dirty); } ############################################################################ Revision: hrev47230 Commit: 2f9ac9582db33ca8eb53261f19486abfa98b41c1 URL: http://cgit.haiku-os.org/haiku/commit/?id=2f9ac95 Author: Adrien Destugues <pulkomandy@xxxxxxxxxxxxx> Date: Mon May 19 12:10:27 2014 UTC Transformation: add one more test * Add test for a translation that makes things that are out of view bounds to become visible * Fix the "rectangles" test to handle scrolling of the view. It seems that in some cases some of the rectangles are not drawn. The gradient and bitmap tests currently have problem with view scrolling, but I'm not sure why. ---------------------------------------------------------------------------- diff --git a/src/tests/servers/app/transformation/main.cpp b/src/tests/servers/app/transformation/main.cpp index fc22f96..b33ab7e 100644 --- a/src/tests/servers/app/transformation/main.cpp +++ b/src/tests/servers/app/transformation/main.cpp @@ -237,6 +237,8 @@ public: view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY); BRect rect(view->Bounds()); + rect.OffsetTo(B_ORIGIN); + rect.InsetBy(rect.Width() / 3, rect.Height() / 3); BPoint center( rect.left + rect.Width() / 2, @@ -449,6 +451,35 @@ public: }; +// #pragma mark - Clipping + + +class ClippingTest : public Test { +public: + ClippingTest() + : + Test("View bounds clipping") + { + } + + virtual void Draw(BView* view, BRect updateRect) + { + BRect r (20, 20, 50, 50); + view->SetHighColor(ui_color(B_FAILURE_COLOR)); + view->FillRect(r); + + BAffineTransform transform; + transform.TranslateBy(400, 400); + view->SetTransform(transform); + + // Make sure this rectangle is drawn, even when the original one is out + // of the view bounds (for example because of scrolling). + view->SetHighColor(ui_color(B_SUCCESS_COLOR)); + view->FillRect(r); + } +}; + + // #pragma mark - @@ -463,6 +494,7 @@ main(int argc, char** argv) window->AddTest(new BitmapTest()); window->AddTest(new GradientTest()); window->AddTest(new NestedStatesTest()); + window->AddTest(new ClippingTest()); window->SetToTest(3); window->Show();