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