1/* 2 * Copyright 2009, Christian Packmann. 3 * Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>. 4 * Copyright 2005-2014, Stephan A��mus <superstippi@gmx.de>. 5 * Copyright 2015, Julian Harnath <julian.harnath@rwth-aachen.de> 6 * All rights reserved. Distributed under the terms of the MIT License. 7 */ 8#ifndef DRAW_BITMAP_NO_SCALE_H 9#define DRAW_BITMAP_NO_SCALE_H 10 11#include "IntPoint.h" 12#include "IntRect.h" 13#include "Painter.h" 14#include "SystemPalette.h" 15 16 17template<class BlendType> 18struct DrawBitmapNoScale { 19public: 20 void 21 Draw(PainterAggInterface& aggInterface, agg::rendering_buffer& bitmap, 22 uint32 bytesPerSourcePixel, IntPoint offset, BRect destinationRect) 23 { 24 // NOTE: this would crash if destinationRect was large enough to read 25 // outside the bitmap, so make sure this is not the case before calling 26 // this function! 27 uint8* dst = aggInterface.fBuffer.row_ptr(0); 28 const uint32 dstBPR = aggInterface.fBuffer.stride(); 29 30 const uint8* src = bitmap.row_ptr(0); 31 const uint32 srcBPR = bitmap.stride(); 32 33 const int32 left = (int32)destinationRect.left; 34 const int32 top = (int32)destinationRect.top; 35 const int32 right = (int32)destinationRect.right; 36 const int32 bottom = (int32)destinationRect.bottom; 37 38#if DEBUG_DRAW_BITMAP 39 if (left - offset.x < 0 40 || left - offset.x >= (int32)bitmap.width() 41 || right - offset.x >= (int32)srcBuffer.width() 42 || top - offset.y < 0 43 || top - offset.y >= (int32)bitmap.height() 44 || bottom - offset.y >= (int32)bitmap.height()) { 45 char message[256]; 46 sprintf(message, "reading outside of bitmap (%ld, %ld, %ld, %ld) " 47 "(%d, %d) (%ld, %ld)", 48 left - offset.x, top - offset.y, 49 right - offset.x, bottom - offset.y, 50 bitmap.width(), bitmap.height(), offset.x, offset.y); 51 debugger(message); 52 } 53#endif 54 55 fColorMap = SystemPalette(); 56 fAlphaMask = aggInterface.fClippedAlphaMask; 57 renderer_base& baseRenderer = aggInterface.fBaseRenderer; 58 59 // copy rects, iterate over clipping boxes 60 baseRenderer.first_clip_box(); 61 do { 62 fRect.left = max_c(baseRenderer.xmin(), left); 63 fRect.right = min_c(baseRenderer.xmax(), right); 64 if (fRect.left <= fRect.right) { 65 fRect.top = max_c(baseRenderer.ymin(), top); 66 fRect.bottom = min_c(baseRenderer.ymax(), bottom); 67 if (fRect.top <= fRect.bottom) { 68 uint8* dstHandle = dst + fRect.top * dstBPR 69 + fRect.left * 4; 70 const uint8* srcHandle = src 71 + (fRect.top - offset.y) * srcBPR 72 + (fRect.left - offset.x) * bytesPerSourcePixel; 73 74 for (; fRect.top <= fRect.bottom; fRect.top++) { 75 static_cast<BlendType*>(this)->BlendRow(dstHandle, 76 srcHandle, fRect.right - fRect.left + 1); 77 78 dstHandle += dstBPR; 79 srcHandle += srcBPR; 80 } 81 } 82 } 83 } while (baseRenderer.next_clip_box()); 84 } 85 86protected: 87 IntRect fRect; 88 const rgb_color* fColorMap; 89 const agg::clipped_alpha_mask* fAlphaMask; 90}; 91 92 93struct CMap8Copy : public DrawBitmapNoScale<CMap8Copy> 94{ 95 void BlendRow(uint8* dst, const uint8* src, int32 numPixels) 96 { 97 uint32* d = (uint32*)dst; 98 const uint8* s = src; 99 while (numPixels--) { 100 const rgb_color c = fColorMap[*s++]; 101 *d++ = (c.alpha << 24) | (c.red << 16) | (c.green << 8) | (c.blue); 102 } 103 } 104}; 105 106 107struct CMap8Over : public DrawBitmapNoScale<CMap8Over> 108{ 109 void BlendRow(uint8* dst, const uint8* src, int32 numPixels) 110 { 111 uint32* d = (uint32*)dst; 112 const uint8* s = src; 113 while (numPixels--) { 114 const rgb_color c = fColorMap[*s++]; 115 if (c.alpha) 116 *d = (c.alpha << 24) | (c.red << 16) 117 | (c.green << 8) | (c.blue); 118 d++; 119 } 120 } 121}; 122 123 124struct Bgr32Copy : public DrawBitmapNoScale<Bgr32Copy> 125{ 126 void BlendRow(uint8* dst, const uint8* src, int32 numPixels) 127 { 128 memcpy(dst, src, numPixels * 4); 129 } 130}; 131 132 133struct Bgr32Over : public DrawBitmapNoScale<Bgr32Over> 134{ 135 void BlendRow(uint8* dst, const uint8* src, int32 numPixels) 136 { 137 uint32* d = (uint32*)dst; 138 uint32* s = (uint32*)src; 139 while (numPixels--) { 140 if (*s != B_TRANSPARENT_MAGIC_RGBA32) 141 *(uint32*)d = *(uint32*)s; 142 d++; 143 s++; 144 } 145 } 146}; 147 148 149struct Bgr32Alpha : public DrawBitmapNoScale<Bgr32Alpha> 150{ 151 void BlendRow(uint8* dst, const uint8* src, int32 numPixels) 152 { 153 uint32* d = (uint32*)dst; 154 int32 bytes = numPixels * 4; 155 uint8 buffer[bytes]; 156 uint8* b = buffer; 157 while (numPixels--) { 158 if (src[3] == 255) { 159 *(uint32*)b = *(uint32*)src; 160 } else { 161 *(uint32*)b = *d; 162 b[0] = ((src[0] - b[0]) * src[3] + (b[0] << 8)) >> 8; 163 b[1] = ((src[1] - b[1]) * src[3] + (b[1] << 8)) >> 8; 164 b[2] = ((src[2] - b[2]) * src[3] + (b[2] << 8)) >> 8; 165 } 166 d++; 167 b += 4; 168 src += 4; 169 } 170 memcpy(dst, buffer, bytes); 171 } 172}; 173 174 175struct Bgr32CopyMasked : public DrawBitmapNoScale<Bgr32CopyMasked> 176{ 177 void BlendRow(uint8* dst, const uint8* src, int32 numPixels) 178 { 179 uint8 covers[numPixels]; 180 fAlphaMask->get_hspan(fRect.left, fRect.top, covers, numPixels); 181 182 uint32* destination = (uint32*)dst; 183 uint32* source = (uint32*)src; 184 uint8* mask = (uint8*)&covers[0]; 185 186 while (numPixels--) { 187 if (*mask != 0) 188 *destination = *source; 189 destination++; 190 source++; 191 mask++; 192 } 193 } 194}; 195 196 197#endif // DRAW_BITMAP_NO_SCALE_H 198