From 79eb23a82dfd137b0a8f2a70058463f6d7a3b476 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Mon, 19 May 2014 13:18:45 +0200 Subject: [PATCH] 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. --- src/servers/app/drawing/DrawingEngine.cpp | 86 ++++++++++++++--------- 1 file changed, 52 insertions(+), 34 deletions(-) diff --git a/src/servers/app/drawing/DrawingEngine.cpp b/src/servers/app/drawing/DrawingEngine.cpp index e37ad034bf..a07a255957 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); }