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