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 17 template<class BlendType> 18 struct DrawBitmapNoScale { 19 public: 20 void DrawDrawBitmapNoScale21 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 86 protected: 87 IntRect fRect; 88 const rgb_color* fColorMap; 89 const agg::clipped_alpha_mask* fAlphaMask; 90 }; 91 92 93 struct CMap8Copy : public DrawBitmapNoScale<CMap8Copy> 94 { BlendRowCMap8Copy95 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 107 struct CMap8Over : public DrawBitmapNoScale<CMap8Over> 108 { BlendRowCMap8Over109 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 124 struct Bgr32Copy : public DrawBitmapNoScale<Bgr32Copy> 125 { BlendRowBgr32Copy126 void BlendRow(uint8* dst, const uint8* src, int32 numPixels) 127 { 128 memcpy(dst, src, numPixels * 4); 129 } 130 }; 131 132 133 struct Bgr32Over : public DrawBitmapNoScale<Bgr32Over> 134 { BlendRowBgr32Over135 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 149 struct Bgr32Alpha : public DrawBitmapNoScale<Bgr32Alpha> 150 { BlendRowBgr32Alpha151 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 175 struct Bgr32CopyMasked : public DrawBitmapNoScale<Bgr32CopyMasked> 176 { BlendRowBgr32CopyMasked177 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