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