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 Fill {}; 15 struct Tile {}; 16 17 template<typename PixFmt, typename Mode> 18 struct ImageAccessor {}; 19 20 template<typename PixFmt> 21 struct ImageAccessor<PixFmt, Fill> { 22 typedef agg::image_accessor_clone<PixFmt> type; 23 }; 24 25 template<typename PixFmt> 26 struct ImageAccessor<PixFmt, Tile> { 27 typedef agg::image_accessor_wrap<PixFmt, 28 agg::wrap_mode_repeat, agg::wrap_mode_repeat> type; 29 }; 30 31 32 template<typename FillMode> 33 struct 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