For the filter indices and wheight calculation, never calculate more
pixels than can possibly be visible. Clients may pass very large view rects to layout a zoomed in bitmap. This doesn't only speed things up, but also avoids a stack overflow in the app_server, as reported in #3166. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29397 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1979,6 +1979,26 @@ Painter::_DrawBitmapNearestNeighborCopy32(agg::rendering_buffer& srcBuffer,
|
|||||||
uint32 srcWidth = srcBuffer.width();
|
uint32 srcWidth = srcBuffer.width();
|
||||||
uint32 srcHeight = srcBuffer.height();
|
uint32 srcHeight = srcBuffer.height();
|
||||||
|
|
||||||
|
// Do not calculate more filter weights than necessary and also
|
||||||
|
// keep the stack based allocations reasonably sized
|
||||||
|
if (fClippingRegion->Frame().IntegerWidth() + 1 < dstWidth)
|
||||||
|
dstWidth = fClippingRegion->Frame().IntegerWidth() + 1;
|
||||||
|
if (fClippingRegion->Frame().IntegerHeight() + 1 < dstHeight)
|
||||||
|
dstHeight = fClippingRegion->Frame().IntegerHeight() + 1;
|
||||||
|
|
||||||
|
// When calculating less filter weights than specified by viewRect,
|
||||||
|
// we need to compensate the offset.
|
||||||
|
uint32 filterWeightXIndexOffset = 0;
|
||||||
|
uint32 filterWeightYIndexOffset = 0;
|
||||||
|
if (fClippingRegion->Frame().left > viewRect.left) {
|
||||||
|
filterWeightXIndexOffset = fClippingRegion->Frame().left
|
||||||
|
- viewRect.left;
|
||||||
|
}
|
||||||
|
if (fClippingRegion->Frame().top > viewRect.top) {
|
||||||
|
filterWeightYIndexOffset = fClippingRegion->Frame().top
|
||||||
|
- viewRect.top;
|
||||||
|
}
|
||||||
|
|
||||||
// should not pose a problem with stack overflows
|
// should not pose a problem with stack overflows
|
||||||
// (needs around 6Kb for 1920x1200)
|
// (needs around 6Kb for 1920x1200)
|
||||||
uint16 xIndices[dstWidth];
|
uint16 xIndices[dstWidth];
|
||||||
@@ -1992,7 +2012,8 @@ Painter::_DrawBitmapNearestNeighborCopy32(agg::rendering_buffer& srcBuffer,
|
|||||||
|
|
||||||
for (uint32 i = 0; i < dstWidth; i++) {
|
for (uint32 i = 0; i < dstWidth; i++) {
|
||||||
// index into source
|
// index into source
|
||||||
uint16 index = (uint16)(i * srcWidth / (srcWidth * xScale));
|
uint16 index = (uint16)((i + filterWeightXIndexOffset) * srcWidth
|
||||||
|
/ (srcWidth * xScale));
|
||||||
// round down to get the left pixel
|
// round down to get the left pixel
|
||||||
xIndices[i] = index;
|
xIndices[i] = index;
|
||||||
// handle cropped source bitmap
|
// handle cropped source bitmap
|
||||||
@@ -2003,7 +2024,8 @@ Painter::_DrawBitmapNearestNeighborCopy32(agg::rendering_buffer& srcBuffer,
|
|||||||
|
|
||||||
for (uint32 i = 0; i < dstHeight; i++) {
|
for (uint32 i = 0; i < dstHeight; i++) {
|
||||||
// index into source
|
// index into source
|
||||||
uint16 index = (uint16)(i * srcHeight / (srcHeight * yScale));
|
uint16 index = (uint16)((i + filterWeightYIndexOffset) * srcHeight
|
||||||
|
/ (srcHeight * yScale));
|
||||||
// round down to get the top pixel
|
// round down to get the top pixel
|
||||||
yIndices[i] = index;
|
yIndices[i] = index;
|
||||||
// handle cropped source bitmap
|
// handle cropped source bitmap
|
||||||
@@ -2041,10 +2063,10 @@ Painter::_DrawBitmapNearestNeighborCopy32(agg::rendering_buffer& srcBuffer,
|
|||||||
|
|
||||||
// x and y are needed as indeces into the wheight arrays, so the
|
// x and y are needed as indeces into the wheight arrays, so the
|
||||||
// offset into the target buffer needs to be compensated
|
// offset into the target buffer needs to be compensated
|
||||||
const int32 xIndexL = x1 - left;
|
const int32 xIndexL = x1 - left - filterWeightXIndexOffset;
|
||||||
const int32 xIndexR = x2 - left;
|
const int32 xIndexR = x2 - left - filterWeightXIndexOffset;
|
||||||
y1 -= top;
|
y1 -= top + filterWeightYIndexOffset;
|
||||||
y2 -= top;
|
y2 -= top + filterWeightYIndexOffset;
|
||||||
|
|
||||||
//printf("x: %ld - %ld\n", xIndexL, xIndexR);
|
//printf("x: %ld - %ld\n", xIndexL, xIndexR);
|
||||||
//printf("y: %ld - %ld\n", y1, y2);
|
//printf("y: %ld - %ld\n", y1, y2);
|
||||||
@@ -2078,6 +2100,26 @@ Painter::_DrawBitmapBilinearCopy32(agg::rendering_buffer& srcBuffer,
|
|||||||
uint32 srcWidth = srcBuffer.width();
|
uint32 srcWidth = srcBuffer.width();
|
||||||
uint32 srcHeight = srcBuffer.height();
|
uint32 srcHeight = srcBuffer.height();
|
||||||
|
|
||||||
|
// Do not calculate more filter weights than necessary and also
|
||||||
|
// keep the stack based allocations reasonably sized
|
||||||
|
if (fClippingRegion->Frame().IntegerWidth() + 1 < dstWidth)
|
||||||
|
dstWidth = fClippingRegion->Frame().IntegerWidth() + 1;
|
||||||
|
if (fClippingRegion->Frame().IntegerHeight() + 1 < dstHeight)
|
||||||
|
dstHeight = fClippingRegion->Frame().IntegerHeight() + 1;
|
||||||
|
|
||||||
|
// When calculating less filter weights than specified by viewRect,
|
||||||
|
// we need to compensate the offset.
|
||||||
|
uint32 filterWeightXIndexOffset = 0;
|
||||||
|
uint32 filterWeightYIndexOffset = 0;
|
||||||
|
if (fClippingRegion->Frame().left > viewRect.left) {
|
||||||
|
filterWeightXIndexOffset = fClippingRegion->Frame().left
|
||||||
|
- viewRect.left;
|
||||||
|
}
|
||||||
|
if (fClippingRegion->Frame().top > viewRect.top) {
|
||||||
|
filterWeightYIndexOffset = fClippingRegion->Frame().top
|
||||||
|
- viewRect.top;
|
||||||
|
}
|
||||||
|
|
||||||
struct FilterInfo {
|
struct FilterInfo {
|
||||||
uint16 index; // index into source bitmap row/column
|
uint16 index; // index into source bitmap row/column
|
||||||
uint16 weight; // weight of the pixel at index [0..255]
|
uint16 weight; // weight of the pixel at index [0..255]
|
||||||
@@ -2114,7 +2156,8 @@ Painter::_DrawBitmapBilinearCopy32(agg::rendering_buffer& srcBuffer,
|
|||||||
// to access the rightmost pixel of the source with a weighting
|
// to access the rightmost pixel of the source with a weighting
|
||||||
// of 255. This in turn will trigger an optimization in the loop
|
// of 255. This in turn will trigger an optimization in the loop
|
||||||
// that also prevents out of bounds access.
|
// that also prevents out of bounds access.
|
||||||
float index = i * (srcWidth - 1) / (srcWidth * xScale - 1);
|
float index = (i + filterWeightXIndexOffset) * (srcWidth - 1)
|
||||||
|
/ (srcWidth * xScale - 1);
|
||||||
// round down to get the left pixel
|
// round down to get the left pixel
|
||||||
xWeights[i].index = (uint16)index;
|
xWeights[i].index = (uint16)index;
|
||||||
xWeights[i].weight = 255 - (uint16)((index - xWeights[i].index) * 255);
|
xWeights[i].weight = 255 - (uint16)((index - xWeights[i].index) * 255);
|
||||||
@@ -2132,7 +2175,8 @@ Painter::_DrawBitmapBilinearCopy32(agg::rendering_buffer& srcBuffer,
|
|||||||
// to access the bottommost pixel of the source with a weighting
|
// to access the bottommost pixel of the source with a weighting
|
||||||
// of 255. This in turn will trigger an optimization in the loop
|
// of 255. This in turn will trigger an optimization in the loop
|
||||||
// that also prevents out of bounds access.
|
// that also prevents out of bounds access.
|
||||||
float index = i * (srcHeight - 1) / (srcHeight * yScale - 1);
|
float index = (i + filterWeightYIndexOffset) * (srcHeight - 1)
|
||||||
|
/ (srcHeight * yScale - 1);
|
||||||
// round down to get the top pixel
|
// round down to get the top pixel
|
||||||
yWeights[i].index = (uint16)index;
|
yWeights[i].index = (uint16)index;
|
||||||
yWeights[i].weight = 255 - (uint16)((index - yWeights[i].index) * 255);
|
yWeights[i].weight = 255 - (uint16)((index - yWeights[i].index) * 255);
|
||||||
@@ -2179,10 +2223,10 @@ Painter::_DrawBitmapBilinearCopy32(agg::rendering_buffer& srcBuffer,
|
|||||||
|
|
||||||
// x and y are needed as indeces into the wheight arrays, so the
|
// x and y are needed as indeces into the wheight arrays, so the
|
||||||
// offset into the target buffer needs to be compensated
|
// offset into the target buffer needs to be compensated
|
||||||
const int32 xIndexL = x1 - left;
|
const int32 xIndexL = x1 - left - filterWeightXIndexOffset;
|
||||||
const int32 xIndexR = x2 - left;
|
const int32 xIndexR = x2 - left - filterWeightXIndexOffset;
|
||||||
y1 -= top;
|
y1 -= top + filterWeightYIndexOffset;
|
||||||
y2 -= top;
|
y2 -= top + filterWeightYIndexOffset;
|
||||||
|
|
||||||
//printf("x: %ld - %ld\n", xIndexL, xIndexR);
|
//printf("x: %ld - %ld\n", xIndexL, xIndexR);
|
||||||
//printf("y: %ld - %ld\n", y1, y2);
|
//printf("y: %ld - %ld\n", y1, y2);
|
||||||
|
|||||||
Reference in New Issue
Block a user