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