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