xref: /haiku/src/servers/app/drawing/Painter/bitmap_painter/DrawBitmapNoScale.h (revision c302a243e15e640fae0f689e32cdf0c18749afee)
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