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.
This commit is contained in:
@@ -963,49 +963,62 @@ DrawingEngine::FillRect(BRect r)
|
|||||||
ASSERT_PARALLEL_LOCKED();
|
ASSERT_PARALLEL_LOCKED();
|
||||||
|
|
||||||
make_rect_valid(r);
|
make_rect_valid(r);
|
||||||
r = fPainter->TransformAlignAndClipRect(r);
|
r.left = floorf(r.left);
|
||||||
if (!r.IsValid())
|
r.top = floorf(r.top);
|
||||||
|
r.right = ceilf(r.right);
|
||||||
|
r.bottom = ceilf(r.bottom);
|
||||||
|
|
||||||
|
BRect dirty = fPainter->TransformAndClipRect(r);
|
||||||
|
if (!dirty.IsValid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
AutoFloatingOverlaysHider overlaysHider(fGraphicsCard, r);
|
AutoFloatingOverlaysHider overlaysHider(fGraphicsCard, r);
|
||||||
|
|
||||||
bool doInSoftware = true;
|
bool doInSoftware = true;
|
||||||
if ((r.Width() + 1) * (r.Height() + 1) > 100.0) {
|
|
||||||
// try hardware optimized version first
|
if (fPainter->IsIdentityTransform())
|
||||||
// if the rect is large enough
|
{
|
||||||
if ((fAvailableHWAccleration & HW_ACC_FILL_REGION) != 0) {
|
// TODO the accelerated code path may also be used for transforms that
|
||||||
if (fPainter->Pattern() == B_SOLID_HIGH
|
// only scale and translate (but don't shear or rotate).
|
||||||
&& (fPainter->DrawingMode() == B_OP_COPY
|
|
||||||
|| fPainter->DrawingMode() == B_OP_OVER)) {
|
if ((r.Width() + 1) * (r.Height() + 1) > 100.0) {
|
||||||
BRegion region(r);
|
// try hardware optimized version first
|
||||||
region.IntersectWith(fPainter->ClippingRegion());
|
// if the rect is large enough
|
||||||
fGraphicsCard->FillRegion(region, fPainter->HighColor(),
|
if ((fAvailableHWAccleration & HW_ACC_FILL_REGION) != 0) {
|
||||||
fSuspendSyncLevel == 0 || overlaysHider.WasHidden());
|
if (fPainter->Pattern() == B_SOLID_HIGH
|
||||||
doInSoftware = false;
|
&& (fPainter->DrawingMode() == B_OP_COPY
|
||||||
} else if (fPainter->Pattern() == B_SOLID_LOW
|
|| fPainter->DrawingMode() == B_OP_OVER)) {
|
||||||
&& fPainter->DrawingMode() == B_OP_COPY) {
|
BRegion region(r);
|
||||||
BRegion region(r);
|
region.IntersectWith(fPainter->ClippingRegion());
|
||||||
region.IntersectWith(fPainter->ClippingRegion());
|
fGraphicsCard->FillRegion(region, fPainter->HighColor(),
|
||||||
fGraphicsCard->FillRegion(region, fPainter->LowColor(),
|
fSuspendSyncLevel == 0 || overlaysHider.WasHidden());
|
||||||
fSuspendSyncLevel == 0 || overlaysHider.WasHidden());
|
doInSoftware = false;
|
||||||
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
|
if (doInSoftware
|
||||||
&& fPainter->Pattern() == B_SOLID_HIGH
|
&& (fAvailableHWAccleration & HW_ACC_INVERT_REGION) != 0
|
||||||
&& fPainter->DrawingMode() == B_OP_INVERT) {
|
&& fPainter->Pattern() == B_SOLID_HIGH
|
||||||
BRegion region(r);
|
&& fPainter->DrawingMode() == B_OP_INVERT) {
|
||||||
region.IntersectWith(fPainter->ClippingRegion());
|
BRegion region(r);
|
||||||
fGraphicsCard->InvertRegion(region);
|
region.IntersectWith(fPainter->ClippingRegion());
|
||||||
doInSoftware = false;
|
fGraphicsCard->InvertRegion(region);
|
||||||
|
doInSoftware = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doInSoftware)
|
if (doInSoftware)
|
||||||
fPainter->FillRect(r);
|
fPainter->FillRect(r);
|
||||||
|
|
||||||
_CopyToFront(r);
|
_CopyToFront(dirty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1015,15 +1028,20 @@ DrawingEngine::FillRect(BRect r, const BGradient& gradient)
|
|||||||
ASSERT_PARALLEL_LOCKED();
|
ASSERT_PARALLEL_LOCKED();
|
||||||
|
|
||||||
make_rect_valid(r);
|
make_rect_valid(r);
|
||||||
r = fPainter->TransformAlignAndClipRect(r);
|
r.left = floorf(r.left);
|
||||||
if (!r.IsValid())
|
r.top = floorf(r.top);
|
||||||
|
r.right = ceilf(r.right);
|
||||||
|
r.bottom = ceilf(r.bottom);
|
||||||
|
|
||||||
|
BRect dirty = fPainter->TransformAndClipRect(r);
|
||||||
|
if (!dirty.IsValid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
AutoFloatingOverlaysHider overlaysHider(fGraphicsCard, r);
|
AutoFloatingOverlaysHider overlaysHider(fGraphicsCard, dirty);
|
||||||
|
|
||||||
fPainter->FillRect(r, gradient);
|
fPainter->FillRect(r, gradient);
|
||||||
|
|
||||||
_CopyToFront(r);
|
_CopyToFront(dirty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user