1e353fe39SJulian Harnath /* 2e353fe39SJulian Harnath * Copyright 2009, Christian Packmann. 3e353fe39SJulian Harnath * Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>. 4e353fe39SJulian Harnath * Copyright 2005-2014, Stephan Aßmus <superstippi@gmx.de>. 5e353fe39SJulian Harnath * Copyright 2015, Julian Harnath <julian.harnath@rwth-aachen.de> 6e353fe39SJulian Harnath * All rights reserved. Distributed under the terms of the MIT License. 7e353fe39SJulian Harnath */ 8e353fe39SJulian Harnath #ifndef DRAW_BITMAP_NO_SCALE_H 9e353fe39SJulian Harnath #define DRAW_BITMAP_NO_SCALE_H 10e353fe39SJulian Harnath 11e353fe39SJulian Harnath #include "IntPoint.h" 1279a483ebSJulian Harnath #include "IntRect.h" 13e353fe39SJulian Harnath #include "Painter.h" 14*0a6baa7eSJulian Harnath #include "SystemPalette.h" 15e353fe39SJulian Harnath 16e353fe39SJulian Harnath 17e353fe39SJulian Harnath template<class BlendType> 18e353fe39SJulian Harnath struct DrawBitmapNoScale { 1979a483ebSJulian Harnath public: 2079a483ebSJulian Harnath void DrawDrawBitmapNoScale21e353fe39SJulian Harnath Draw(PainterAggInterface& aggInterface, agg::rendering_buffer& bitmap, 22e353fe39SJulian Harnath uint32 bytesPerSourcePixel, IntPoint offset, BRect destinationRect) 23e353fe39SJulian Harnath { 24e353fe39SJulian Harnath // NOTE: this would crash if destinationRect was large enough to read 25e353fe39SJulian Harnath // outside the bitmap, so make sure this is not the case before calling 26e353fe39SJulian Harnath // this function! 27e353fe39SJulian Harnath uint8* dst = aggInterface.fBuffer.row_ptr(0); 28e353fe39SJulian Harnath const uint32 dstBPR = aggInterface.fBuffer.stride(); 29e353fe39SJulian Harnath 30e353fe39SJulian Harnath const uint8* src = bitmap.row_ptr(0); 31e353fe39SJulian Harnath const uint32 srcBPR = bitmap.stride(); 32e353fe39SJulian Harnath 33e353fe39SJulian Harnath const int32 left = (int32)destinationRect.left; 34e353fe39SJulian Harnath const int32 top = (int32)destinationRect.top; 35e353fe39SJulian Harnath const int32 right = (int32)destinationRect.right; 36e353fe39SJulian Harnath const int32 bottom = (int32)destinationRect.bottom; 37e353fe39SJulian Harnath 38e353fe39SJulian Harnath #if DEBUG_DRAW_BITMAP 39e353fe39SJulian Harnath if (left - offset.x < 0 40e353fe39SJulian Harnath || left - offset.x >= (int32)bitmap.width() 41e353fe39SJulian Harnath || right - offset.x >= (int32)srcBuffer.width() 42e353fe39SJulian Harnath || top - offset.y < 0 43e353fe39SJulian Harnath || top - offset.y >= (int32)bitmap.height() 44e353fe39SJulian Harnath || bottom - offset.y >= (int32)bitmap.height()) { 45e353fe39SJulian Harnath char message[256]; 46e353fe39SJulian Harnath sprintf(message, "reading outside of bitmap (%ld, %ld, %ld, %ld) " 47e353fe39SJulian Harnath "(%d, %d) (%ld, %ld)", 48e353fe39SJulian Harnath left - offset.x, top - offset.y, 49e353fe39SJulian Harnath right - offset.x, bottom - offset.y, 50e353fe39SJulian Harnath bitmap.width(), bitmap.height(), offset.x, offset.y); 51e353fe39SJulian Harnath debugger(message); 52e353fe39SJulian Harnath } 53e353fe39SJulian Harnath #endif 54e353fe39SJulian Harnath 5579a483ebSJulian Harnath fColorMap = SystemPalette(); 5679a483ebSJulian Harnath fAlphaMask = aggInterface.fClippedAlphaMask; 57e353fe39SJulian Harnath renderer_base& baseRenderer = aggInterface.fBaseRenderer; 58e353fe39SJulian Harnath 59e353fe39SJulian Harnath // copy rects, iterate over clipping boxes 60e353fe39SJulian Harnath baseRenderer.first_clip_box(); 61e353fe39SJulian Harnath do { 6279a483ebSJulian Harnath fRect.left = max_c(baseRenderer.xmin(), left); 6379a483ebSJulian Harnath fRect.right = min_c(baseRenderer.xmax(), right); 6479a483ebSJulian Harnath if (fRect.left <= fRect.right) { 6579a483ebSJulian Harnath fRect.top = max_c(baseRenderer.ymin(), top); 6679a483ebSJulian Harnath fRect.bottom = min_c(baseRenderer.ymax(), bottom); 6779a483ebSJulian Harnath if (fRect.top <= fRect.bottom) { 6879a483ebSJulian Harnath uint8* dstHandle = dst + fRect.top * dstBPR 6979a483ebSJulian Harnath + fRect.left * 4; 7079a483ebSJulian Harnath const uint8* srcHandle = src 7179a483ebSJulian Harnath + (fRect.top - offset.y) * srcBPR 7279a483ebSJulian Harnath + (fRect.left - offset.x) * bytesPerSourcePixel; 73e353fe39SJulian Harnath 7479a483ebSJulian Harnath for (; fRect.top <= fRect.bottom; fRect.top++) { 7579a483ebSJulian Harnath static_cast<BlendType*>(this)->BlendRow(dstHandle, 7679a483ebSJulian Harnath srcHandle, fRect.right - fRect.left + 1); 77e353fe39SJulian Harnath 78e353fe39SJulian Harnath dstHandle += dstBPR; 79e353fe39SJulian Harnath srcHandle += srcBPR; 80e353fe39SJulian Harnath } 81e353fe39SJulian Harnath } 82e353fe39SJulian Harnath } 83e353fe39SJulian Harnath } while (baseRenderer.next_clip_box()); 84e353fe39SJulian Harnath } 8579a483ebSJulian Harnath 8679a483ebSJulian Harnath protected: 8779a483ebSJulian Harnath IntRect fRect; 8879a483ebSJulian Harnath const rgb_color* fColorMap; 8979a483ebSJulian Harnath const agg::clipped_alpha_mask* fAlphaMask; 90e353fe39SJulian Harnath }; 91e353fe39SJulian Harnath 92e353fe39SJulian Harnath 93e353fe39SJulian Harnath struct CMap8Copy : public DrawBitmapNoScale<CMap8Copy> 94e353fe39SJulian Harnath { BlendRowCMap8Copy9579a483ebSJulian Harnath void BlendRow(uint8* dst, const uint8* src, int32 numPixels) 96e353fe39SJulian Harnath { 97e353fe39SJulian Harnath uint32* d = (uint32*)dst; 98e353fe39SJulian Harnath const uint8* s = src; 99e353fe39SJulian Harnath while (numPixels--) { 10079a483ebSJulian Harnath const rgb_color c = fColorMap[*s++]; 101e353fe39SJulian Harnath *d++ = (c.alpha << 24) | (c.red << 16) | (c.green << 8) | (c.blue); 102e353fe39SJulian Harnath } 103e353fe39SJulian Harnath } 104e353fe39SJulian Harnath }; 105e353fe39SJulian Harnath 106e353fe39SJulian Harnath 107e353fe39SJulian Harnath struct CMap8Over : public DrawBitmapNoScale<CMap8Over> 108e353fe39SJulian Harnath { BlendRowCMap8Over10979a483ebSJulian Harnath void BlendRow(uint8* dst, const uint8* src, int32 numPixels) 110e353fe39SJulian Harnath { 111e353fe39SJulian Harnath uint32* d = (uint32*)dst; 112e353fe39SJulian Harnath const uint8* s = src; 113e353fe39SJulian Harnath while (numPixels--) { 11479a483ebSJulian Harnath const rgb_color c = fColorMap[*s++]; 115e353fe39SJulian Harnath if (c.alpha) 116e353fe39SJulian Harnath *d = (c.alpha << 24) | (c.red << 16) 117e353fe39SJulian Harnath | (c.green << 8) | (c.blue); 118e353fe39SJulian Harnath d++; 119e353fe39SJulian Harnath } 120e353fe39SJulian Harnath } 121e353fe39SJulian Harnath }; 122e353fe39SJulian Harnath 123e353fe39SJulian Harnath 124e353fe39SJulian Harnath struct Bgr32Copy : public DrawBitmapNoScale<Bgr32Copy> 125e353fe39SJulian Harnath { BlendRowBgr32Copy12679a483ebSJulian Harnath void BlendRow(uint8* dst, const uint8* src, int32 numPixels) 127e353fe39SJulian Harnath { 128e353fe39SJulian Harnath memcpy(dst, src, numPixels * 4); 129e353fe39SJulian Harnath } 130e353fe39SJulian Harnath }; 131e353fe39SJulian Harnath 132e353fe39SJulian Harnath 133e353fe39SJulian Harnath struct Bgr32Over : public DrawBitmapNoScale<Bgr32Over> 134e353fe39SJulian Harnath { BlendRowBgr32Over13579a483ebSJulian Harnath void BlendRow(uint8* dst, const uint8* src, int32 numPixels) 136e353fe39SJulian Harnath { 137e353fe39SJulian Harnath uint32* d = (uint32*)dst; 138e353fe39SJulian Harnath uint32* s = (uint32*)src; 139e353fe39SJulian Harnath while (numPixels--) { 140e353fe39SJulian Harnath if (*s != B_TRANSPARENT_MAGIC_RGBA32) 141e353fe39SJulian Harnath *(uint32*)d = *(uint32*)s; 142e353fe39SJulian Harnath d++; 143e353fe39SJulian Harnath s++; 144e353fe39SJulian Harnath } 145e353fe39SJulian Harnath } 146e353fe39SJulian Harnath }; 147e353fe39SJulian Harnath 148e353fe39SJulian Harnath 149e353fe39SJulian Harnath struct Bgr32Alpha : public DrawBitmapNoScale<Bgr32Alpha> 150e353fe39SJulian Harnath { BlendRowBgr32Alpha15179a483ebSJulian Harnath void BlendRow(uint8* dst, const uint8* src, int32 numPixels) 152e353fe39SJulian Harnath { 153e353fe39SJulian Harnath uint32* d = (uint32*)dst; 154e353fe39SJulian Harnath int32 bytes = numPixels * 4; 155e353fe39SJulian Harnath uint8 buffer[bytes]; 156e353fe39SJulian Harnath uint8* b = buffer; 157e353fe39SJulian Harnath while (numPixels--) { 158e353fe39SJulian Harnath if (src[3] == 255) { 159e353fe39SJulian Harnath *(uint32*)b = *(uint32*)src; 160e353fe39SJulian Harnath } else { 161e353fe39SJulian Harnath *(uint32*)b = *d; 162e353fe39SJulian Harnath b[0] = ((src[0] - b[0]) * src[3] + (b[0] << 8)) >> 8; 163e353fe39SJulian Harnath b[1] = ((src[1] - b[1]) * src[3] + (b[1] << 8)) >> 8; 164e353fe39SJulian Harnath b[2] = ((src[2] - b[2]) * src[3] + (b[2] << 8)) >> 8; 165e353fe39SJulian Harnath } 166e353fe39SJulian Harnath d++; 167e353fe39SJulian Harnath b += 4; 168e353fe39SJulian Harnath src += 4; 169e353fe39SJulian Harnath } 170e353fe39SJulian Harnath memcpy(dst, buffer, bytes); 171e353fe39SJulian Harnath } 172e353fe39SJulian Harnath }; 173e353fe39SJulian Harnath 174e353fe39SJulian Harnath 17579a483ebSJulian Harnath struct Bgr32CopyMasked : public DrawBitmapNoScale<Bgr32CopyMasked> 17679a483ebSJulian Harnath { BlendRowBgr32CopyMasked17779a483ebSJulian Harnath void BlendRow(uint8* dst, const uint8* src, int32 numPixels) 17879a483ebSJulian Harnath { 17979a483ebSJulian Harnath uint8 covers[numPixels]; 18079a483ebSJulian Harnath fAlphaMask->get_hspan(fRect.left, fRect.top, covers, numPixels); 18179a483ebSJulian Harnath 18279a483ebSJulian Harnath uint32* destination = (uint32*)dst; 18379a483ebSJulian Harnath uint32* source = (uint32*)src; 18479a483ebSJulian Harnath uint8* mask = (uint8*)&covers[0]; 18579a483ebSJulian Harnath 18679a483ebSJulian Harnath while (numPixels--) { 18779a483ebSJulian Harnath if (*mask != 0) 18879a483ebSJulian Harnath *destination = *source; 18979a483ebSJulian Harnath destination++; 19079a483ebSJulian Harnath source++; 19179a483ebSJulian Harnath mask++; 19279a483ebSJulian Harnath } 19379a483ebSJulian Harnath } 19479a483ebSJulian Harnath }; 19579a483ebSJulian Harnath 19679a483ebSJulian Harnath 197e353fe39SJulian Harnath #endif // DRAW_BITMAP_NO_SCALE_H 198