#ifndef DRAW_BITMAP_NO_SCALE_H
#define DRAW_BITMAP_NO_SCALE_H
#include "IntPoint.h"
#include "IntRect.h"
#include "Painter.h"
#include "SystemPalette.h"
template<class BlendType>
struct DrawBitmapNoScale {
public:
void
Draw(PainterAggInterface& aggInterface, agg::rendering_buffer& bitmap,
uint32 bytesPerSourcePixel, IntPoint offset, BRect destinationRect)
{
uint8* dst = aggInterface.fBuffer.row_ptr(0);
const uint32 dstBPR = aggInterface.fBuffer.stride();
const uint8* src = bitmap.row_ptr(0);
const uint32 srcBPR = bitmap.stride();
const int32 left = (int32)destinationRect.left;
const int32 top = (int32)destinationRect.top;
const int32 right = (int32)destinationRect.right;
const int32 bottom = (int32)destinationRect.bottom;
#if DEBUG_DRAW_BITMAP
if (left - offset.x < 0
|| left - offset.x >= (int32)bitmap.width()
|| right - offset.x >= (int32)srcBuffer.width()
|| top - offset.y < 0
|| top - offset.y >= (int32)bitmap.height()
|| bottom - offset.y >= (int32)bitmap.height()) {
char message[256];
sprintf(message, "reading outside of bitmap (%ld, %ld, %ld, %ld) "
"(%d, %d) (%ld, %ld)",
left - offset.x, top - offset.y,
right - offset.x, bottom - offset.y,
bitmap.width(), bitmap.height(), offset.x, offset.y);
debugger(message);
}
#endif
fColorMap = SystemPalette();
fAlphaMask = aggInterface.fClippedAlphaMask;
renderer_base& baseRenderer = aggInterface.fBaseRenderer;
baseRenderer.first_clip_box();
do {
fRect.left = max_c(baseRenderer.xmin(), left);
fRect.right = min_c(baseRenderer.xmax(), right);
if (fRect.left <= fRect.right) {
fRect.top = max_c(baseRenderer.ymin(), top);
fRect.bottom = min_c(baseRenderer.ymax(), bottom);
if (fRect.top <= fRect.bottom) {
uint8* dstHandle = dst + fRect.top * dstBPR
+ fRect.left * 4;
const uint8* srcHandle = src
+ (fRect.top - offset.y) * srcBPR
+ (fRect.left - offset.x) * bytesPerSourcePixel;
for (; fRect.top <= fRect.bottom; fRect.top++) {
static_cast<BlendType*>(this)->BlendRow(dstHandle,
srcHandle, fRect.right - fRect.left + 1);
dstHandle += dstBPR;
srcHandle += srcBPR;
}
}
}
} while (baseRenderer.next_clip_box());
}
protected:
IntRect fRect;
const rgb_color* fColorMap;
const agg::clipped_alpha_mask* fAlphaMask;
};
struct CMap8Copy : public DrawBitmapNoScale<CMap8Copy>
{
void BlendRow(uint8* dst, const uint8* src, int32 numPixels)
{
uint32* d = (uint32*)dst;
const uint8* s = src;
while (numPixels--) {
const rgb_color c = fColorMap[*s++];
*d++ = (c.alpha << 24) | (c.red << 16) | (c.green << 8) | (c.blue);
}
}
};
struct CMap8Over : public DrawBitmapNoScale<CMap8Over>
{
void BlendRow(uint8* dst, const uint8* src, int32 numPixels)
{
uint32* d = (uint32*)dst;
const uint8* s = src;
while (numPixels--) {
const rgb_color c = fColorMap[*s++];
if (c.alpha)
*d = (c.alpha << 24) | (c.red << 16)
| (c.green << 8) | (c.blue);
d++;
}
}
};
struct Bgr32Copy : public DrawBitmapNoScale<Bgr32Copy>
{
void BlendRow(uint8* dst, const uint8* src, int32 numPixels)
{
memcpy(dst, src, numPixels * 4);
}
};
struct Bgr32Over : public DrawBitmapNoScale<Bgr32Over>
{
void BlendRow(uint8* dst, const uint8* src, int32 numPixels)
{
uint32* d = (uint32*)dst;
uint32* s = (uint32*)src;
while (numPixels--) {
if (*s != B_TRANSPARENT_MAGIC_RGBA32)
*(uint32*)d = *(uint32*)s;
d++;
s++;
}
}
};
struct Bgr32Alpha : public DrawBitmapNoScale<Bgr32Alpha>
{
void BlendRow(uint8* dst, const uint8* src, int32 numPixels)
{
uint32* d = (uint32*)dst;
int32 bytes = numPixels * 4;
uint8 buffer[bytes];
uint8* b = buffer;
while (numPixels--) {
if (src[3] == 255) {
*(uint32*)b = *(uint32*)src;
} else {
*(uint32*)b = *d;
b[0] = ((src[0] - b[0]) * src[3] + (b[0] << 8)) >> 8;
b[1] = ((src[1] - b[1]) * src[3] + (b[1] << 8)) >> 8;
b[2] = ((src[2] - b[2]) * src[3] + (b[2] << 8)) >> 8;
}
d++;
b += 4;
src += 4;
}
memcpy(dst, buffer, bytes);
}
};
struct Bgr32CopyMasked : public DrawBitmapNoScale<Bgr32CopyMasked>
{
void BlendRow(uint8* dst, const uint8* src, int32 numPixels)
{
uint8 covers[numPixels];
fAlphaMask->get_hspan(fRect.left, fRect.top, covers, numPixels);
uint32* destination = (uint32*)dst;
uint32* source = (uint32*)src;
uint8* mask = (uint8*)&covers[0];
while (numPixels--) {
if (*mask != 0)
*destination = *source;
destination++;
source++;
mask++;
}
}
};
#endif