* Copyright 2009, Christian Packmann.
* Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>.
* Copyright 2005-2014, Stephan Aßmus <superstippi@gmx.de>.
* Copyright 2015, Julian Harnath <julian.harnath@rwth-aachen.de>
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef DRAW_BITMAP_NEAREST_NEIGHBOR_H
#define DRAW_BITMAP_NEAREST_NEIGHBOR_H
#include "Painter.h"
struct DrawBitmapNearestNeighborCopy {
static void
Draw(const Painter* painter, PainterAggInterface& aggInterface,
agg::rendering_buffer& bitmap, BPoint offset,
double scaleX, double scaleY, BRect destinationRect)
{
uint32 dstWidth = destinationRect.IntegerWidth() + 1;
uint32 dstHeight = destinationRect.IntegerHeight() + 1;
uint32 srcWidth = bitmap.width();
uint32 srcHeight = bitmap.height();
const BRegion& clippingRegion = *painter->ClippingRegion();
if (clippingRegion.Frame().IntegerWidth() + 1 < (int32)dstWidth)
dstWidth = clippingRegion.Frame().IntegerWidth() + 1;
if (clippingRegion.Frame().IntegerHeight() + 1 < (int32)dstHeight)
dstHeight = clippingRegion.Frame().IntegerHeight() + 1;
uint32 filterWeightXIndexOffset = 0;
uint32 filterWeightYIndexOffset = 0;
if (clippingRegion.Frame().left > destinationRect.left) {
filterWeightXIndexOffset = (int32)(clippingRegion.Frame().left
- destinationRect.left);
}
if (clippingRegion.Frame().top > destinationRect.top) {
filterWeightYIndexOffset = (int32)(clippingRegion.Frame().top
- destinationRect.top);
}
uint16 xIndices[dstWidth];
uint16 yIndices[dstHeight];
const int32 xBitmapShift = (int32)(destinationRect.left - offset.x);
const int32 yBitmapShift = (int32)(destinationRect.top - offset.y);
for (uint32 i = 0; i < dstWidth; i++) {
uint16 index = (uint16)((i + filterWeightXIndexOffset) * srcWidth
/ (srcWidth * scaleX));
xIndices[i] = index;
xIndices[i] += xBitmapShift;
xIndices[i] *= 4;
}
for (uint32 i = 0; i < dstHeight; i++) {
uint16 index = (uint16)((i + filterWeightYIndexOffset) * srcHeight
/ (srcHeight * scaleY));
yIndices[i] = index;
yIndices[i] += yBitmapShift;
}
const int32 left = (int32)destinationRect.left;
const int32 top = (int32)destinationRect.top;
const int32 right = (int32)destinationRect.right;
const int32 bottom = (int32)destinationRect.bottom;
const uint32 dstBPR = aggInterface.fBuffer.stride();
renderer_base& baseRenderer = aggInterface.fBaseRenderer;
baseRenderer.first_clip_box();
do {
const int32 x1 = max_c(baseRenderer.xmin(), left);
const int32 x2 = min_c(baseRenderer.xmax(), right);
if (x1 > x2)
continue;
int32 y1 = max_c(baseRenderer.ymin(), top);
int32 y2 = min_c(baseRenderer.ymax(), bottom);
if (y1 > y2)
continue;
uint8* dst = aggInterface.fBuffer.row_ptr(y1) + x1 * 4;
const int32 xIndexL = x1 - left - filterWeightXIndexOffset;
const int32 xIndexR = x2 - left - filterWeightXIndexOffset;
y1 -= top + filterWeightYIndexOffset;
y2 -= top + filterWeightYIndexOffset;
for (; y1 <= y2; y1++) {
const uint8* src = bitmap.row_ptr(yIndices[y1]);
uint32* d = (uint32*)dst;
for (int32 x = xIndexL; x <= xIndexR; x++) {
*d = *(uint32*)(src + xIndices[x]);
d++;
}
dst += dstBPR;
}
} while (baseRenderer.next_clip_box());
}
};
#endif