xref: /haiku/src/servers/app/drawing/Painter/bitmap_painter/DrawBitmapGeneric.h (revision c67dde0f2ccb45d550af410cf6d73fee39d10504)
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_GENERIC_H
9e353fe39SJulian Harnath #define DRAW_BITMAP_GENERIC_H
10e353fe39SJulian Harnath 
11e353fe39SJulian Harnath #include "Painter.h"
12e353fe39SJulian Harnath 
13e353fe39SJulian Harnath 
14*c67dde0fSKacper Kasper struct Fill {};
15*c67dde0fSKacper Kasper struct Tile {};
16*c67dde0fSKacper Kasper 
17*c67dde0fSKacper Kasper template<typename PixFmt, typename Mode>
18*c67dde0fSKacper Kasper struct ImageAccessor {};
19*c67dde0fSKacper Kasper 
20*c67dde0fSKacper Kasper template<typename PixFmt>
21*c67dde0fSKacper Kasper struct ImageAccessor<PixFmt, Fill> {
22*c67dde0fSKacper Kasper 	typedef agg::image_accessor_clone<PixFmt> type;
23*c67dde0fSKacper Kasper };
24*c67dde0fSKacper Kasper 
25*c67dde0fSKacper Kasper template<typename PixFmt>
26*c67dde0fSKacper Kasper struct ImageAccessor<PixFmt, Tile> {
27*c67dde0fSKacper Kasper 	typedef agg::image_accessor_wrap<PixFmt,
28*c67dde0fSKacper Kasper 		agg::wrap_mode_repeat, agg::wrap_mode_repeat> type;
29*c67dde0fSKacper Kasper };
30*c67dde0fSKacper Kasper 
31*c67dde0fSKacper Kasper 
32*c67dde0fSKacper Kasper template<typename FillMode>
33e353fe39SJulian Harnath struct DrawBitmapGeneric {
34e353fe39SJulian Harnath 	static void
35e353fe39SJulian Harnath 	Draw(const Painter* painter, PainterAggInterface& aggInterface,
36e353fe39SJulian Harnath 		agg::rendering_buffer& bitmap, BPoint offset,
37e353fe39SJulian Harnath 		double scaleX, double scaleY, BRect destinationRect, uint32 options)
38e353fe39SJulian Harnath 	{
39e353fe39SJulian Harnath 		// pixel format attached to bitmap
40e353fe39SJulian Harnath 		typedef agg::pixfmt_bgra32 pixfmt_image;
41e353fe39SJulian Harnath 		pixfmt_image pixf_img(bitmap);
42e353fe39SJulian Harnath 
43e353fe39SJulian Harnath 		agg::trans_affine srcMatrix;
44e353fe39SJulian Harnath 		// NOTE: R5 seems to ignore this offset when drawing bitmaps
45e353fe39SJulian Harnath 		//	srcMatrix *= agg::trans_affine_translation(-actualBitmapRect.left,
46e353fe39SJulian Harnath 		//		-actualBitmapRect.top);
47e353fe39SJulian Harnath 		srcMatrix *= painter->Transform();
48e353fe39SJulian Harnath 
49e353fe39SJulian Harnath 		agg::trans_affine imgMatrix;
50e353fe39SJulian Harnath 		imgMatrix *= agg::trans_affine_translation(
51e353fe39SJulian Harnath 			offset.x - destinationRect.left, offset.y - destinationRect.top);
52e353fe39SJulian Harnath 		imgMatrix *= agg::trans_affine_scaling(scaleX, scaleY);
53e353fe39SJulian Harnath 		imgMatrix *= agg::trans_affine_translation(destinationRect.left,
54e353fe39SJulian Harnath 			destinationRect.top);
55e353fe39SJulian Harnath 		imgMatrix *= painter->Transform();
56e353fe39SJulian Harnath 		imgMatrix.invert();
57e353fe39SJulian Harnath 
58e353fe39SJulian Harnath 		// image interpolator
59e353fe39SJulian Harnath 		typedef agg::span_interpolator_linear<> interpolator_type;
60e353fe39SJulian Harnath 		interpolator_type interpolator(imgMatrix);
61e353fe39SJulian Harnath 
62e353fe39SJulian Harnath 		// scanline allocator
63e353fe39SJulian Harnath 		agg::span_allocator<pixfmt_image::color_type> spanAllocator;
64e353fe39SJulian Harnath 
65e353fe39SJulian Harnath 		// image accessor attached to pixel format of bitmap
66*c67dde0fSKacper Kasper 		typedef
67*c67dde0fSKacper Kasper 			typename ImageAccessor<pixfmt_image, FillMode>::type source_type;
68e353fe39SJulian Harnath 		source_type source(pixf_img);
69e353fe39SJulian Harnath 
70e353fe39SJulian Harnath 		// clip to the current clipping region's frame
71e353fe39SJulian Harnath 		if (painter->IsIdentityTransform()) {
72e353fe39SJulian Harnath 			destinationRect = destinationRect
73e353fe39SJulian Harnath 				& painter->ClippingRegion()->Frame();
74e353fe39SJulian Harnath 		}
75e353fe39SJulian Harnath 		// convert to pixel coords (versus pixel indices)
76e353fe39SJulian Harnath 		destinationRect.right++;
77e353fe39SJulian Harnath 		destinationRect.bottom++;
78e353fe39SJulian Harnath 
79e353fe39SJulian Harnath 		// path enclosing the bitmap
80e353fe39SJulian Harnath 		agg::path_storage& path = aggInterface.fPath;
81e353fe39SJulian Harnath 		rasterizer_type& rasterizer = aggInterface.fRasterizer;
82e353fe39SJulian Harnath 
83e353fe39SJulian Harnath 		path.remove_all();
84e353fe39SJulian Harnath 		path.move_to(destinationRect.left, destinationRect.top);
85e353fe39SJulian Harnath 		path.line_to(destinationRect.right, destinationRect.top);
86e353fe39SJulian Harnath 		path.line_to(destinationRect.right, destinationRect.bottom);
87e353fe39SJulian Harnath 		path.line_to(destinationRect.left, destinationRect.bottom);
88e353fe39SJulian Harnath 		path.close_polygon();
89e353fe39SJulian Harnath 
90e353fe39SJulian Harnath 		agg::conv_transform<agg::path_storage> transformedPath(path,
91e353fe39SJulian Harnath 			srcMatrix);
92e353fe39SJulian Harnath 		rasterizer.reset();
93e353fe39SJulian Harnath 		rasterizer.add_path(transformedPath);
94e353fe39SJulian Harnath 
95e353fe39SJulian Harnath 		if ((options & B_FILTER_BITMAP_BILINEAR) != 0) {
96e353fe39SJulian Harnath 			// image filter (bilinear)
97e353fe39SJulian Harnath 			typedef agg::span_image_filter_rgba_bilinear<
98e353fe39SJulian Harnath 				source_type, interpolator_type> span_gen_type;
99e353fe39SJulian Harnath 			span_gen_type spanGenerator(source, interpolator);
100e353fe39SJulian Harnath 
101e353fe39SJulian Harnath 			// render the path with the bitmap as scanline fill
102e353fe39SJulian Harnath 			if (aggInterface.fMaskedUnpackedScanline != NULL) {
103e353fe39SJulian Harnath 				agg::render_scanlines_aa(rasterizer,
104e353fe39SJulian Harnath 					*aggInterface.fMaskedUnpackedScanline,
105e353fe39SJulian Harnath 					aggInterface.fBaseRenderer, spanAllocator, spanGenerator);
106e353fe39SJulian Harnath 			} else {
107e353fe39SJulian Harnath 				agg::render_scanlines_aa(rasterizer,
108e353fe39SJulian Harnath 					aggInterface.fUnpackedScanline,
109e353fe39SJulian Harnath 					aggInterface.fBaseRenderer, spanAllocator, spanGenerator);
110e353fe39SJulian Harnath 			}
111e353fe39SJulian Harnath 		} else {
112e353fe39SJulian Harnath 			// image filter (nearest neighbor)
113e353fe39SJulian Harnath 			typedef agg::span_image_filter_rgba_nn<
114e353fe39SJulian Harnath 				source_type, interpolator_type> span_gen_type;
115e353fe39SJulian Harnath 			span_gen_type spanGenerator(source, interpolator);
116e353fe39SJulian Harnath 
117e353fe39SJulian Harnath 			// render the path with the bitmap as scanline fill
118e353fe39SJulian Harnath 			if (aggInterface.fMaskedUnpackedScanline != NULL) {
119e353fe39SJulian Harnath 				agg::render_scanlines_aa(rasterizer,
120e353fe39SJulian Harnath 					*aggInterface.fMaskedUnpackedScanline,
121e353fe39SJulian Harnath 					aggInterface.fBaseRenderer, spanAllocator, spanGenerator);
122e353fe39SJulian Harnath 			} else {
123e353fe39SJulian Harnath 				agg::render_scanlines_aa(rasterizer,
124e353fe39SJulian Harnath 					aggInterface.fUnpackedScanline,
125e353fe39SJulian Harnath 					aggInterface.fBaseRenderer, spanAllocator, spanGenerator);
126e353fe39SJulian Harnath 			}
127e353fe39SJulian Harnath 		}
128e353fe39SJulian Harnath 	}
129e353fe39SJulian Harnath };
130e353fe39SJulian Harnath 
131e353fe39SJulian Harnath 
132e353fe39SJulian Harnath #endif // DRAW_BITMAP_GENERIC_H
133