2006-03-20 17:12:09 +00:00
/*
2014-06-01 17:55:23 +00:00
* Portions of this file are copyright Rebirth contributors and licensed as
* described in COPYING . txt .
* Portions of this file are copyright Parallax Software and licensed
* according to the Parallax license below .
* See COPYING . txt for license details .
2006-03-20 17:12:09 +00:00
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
SOFTWARE CORPORATION ( " PARALLAX " ) . PARALLAX , IN DISTRIBUTING THE CODE TO
END - USERS , AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN , GRANTS A
ROYALTY - FREE , PERPETUAL LICENSE TO SUCH END - USERS FOR USE BY SUCH END - USERS
IN USING , DISPLAYING , AND CREATING DERIVATIVE WORKS THEREOF , SO LONG AS
SUCH USE , DISPLAY OR CREATION IS FOR NON - COMMERCIAL , ROYALTY OR REVENUE
FREE PURPOSES . IN NO EVENT SHALL THE END - USER USE THE COMPUTER CODE
CONTAINED HEREIN FOR REVENUE - BEARING PURPOSES . THE END - USER UNDERSTANDS
AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE .
COPYRIGHT 1993 - 1999 PARALLAX SOFTWARE CORPORATION . ALL RIGHTS RESERVED .
*/
/*
*
* Routines for bitblt ' s .
*
2009-11-30 22:42:55 +00:00
*/
2006-03-20 17:12:09 +00:00
2014-08-08 02:44:27 +00:00
# include <algorithm>
2014-07-01 00:23:30 +00:00
# include <utility>
2007-06-10 16:21:53 +00:00
# include <string.h>
2006-03-20 17:12:09 +00:00
# include "u_mem.h"
# include "gr.h"
# include "rle.h"
2012-07-07 18:35:06 +00:00
# include "dxxerror.h"
2014-07-03 01:47:29 +00:00
# include "byteutil.h"
2016-09-24 18:06:11 +00:00
# if DXX_USE_OGL
2006-03-20 17:12:09 +00:00
# include "ogl_init.h"
# endif
2019-05-04 18:27:37 +00:00
# include "compiler-range_for.h"
# include "d_range.h"
2020-05-02 21:18:42 +00:00
# include <array>
2014-07-01 02:30:39 +00:00
2015-12-13 18:00:49 +00:00
namespace dcx {
2015-12-05 22:57:23 +00:00
2020-12-26 21:17:29 +00:00
namespace {
2014-11-30 22:09:19 +00:00
static void gr_bm_ubitblt00_rle ( unsigned w , unsigned h , int dx , int dy , int sx , int sy , const grs_bitmap & src , grs_bitmap & dest ) ;
2016-09-24 18:06:11 +00:00
# if !DXX_USE_OGL
2014-11-30 22:09:22 +00:00
static void gr_bm_ubitblt00m_rle ( unsigned w , unsigned h , int dx , int dy , int sx , int sy , const grs_bitmap & src , grs_bitmap & dest ) ;
2017-02-11 21:42:33 +00:00
static void gr_bm_ubitblt0x_rle ( grs_canvas & dest , unsigned w , unsigned h , int dx , int dy , int sx , int sy , const grs_bitmap & src ) ;
2015-12-04 03:36:31 +00:00
# endif
2006-03-20 17:12:09 +00:00
2014-11-30 22:09:19 +00:00
# define gr_linear_movsd(S,D,L) memcpy(D,S,L)
2006-03-20 17:12:09 +00:00
2016-09-24 18:06:11 +00:00
# if !DXX_USE_OGL
2016-12-29 03:27:10 +00:00
static void gr_linear_rep_movsdm ( uint8_t * const dest , const uint8_t * const src , const uint_fast32_t num_pixels )
2014-12-05 02:42:43 +00:00
{
auto predicate = [ & ] ( uint8_t s , uint8_t d ) {
return s = = 255 ? d : s ;
} ;
std : : transform ( src , src + num_pixels , dest , dest , predicate ) ;
2006-03-20 17:12:09 +00:00
}
2015-12-04 03:36:31 +00:00
# endif
2006-03-20 17:12:09 +00:00
2016-12-29 03:27:10 +00:00
template < typename F >
static void gr_for_each_bitmap_line ( grs_canvas & canvas , const unsigned x , const unsigned y , const grs_bitmap & bm , F f )
2006-03-20 17:12:09 +00:00
{
2016-05-28 17:31:26 +00:00
const size_t src_width = bm . bm_w ;
const uintptr_t src_rowsize = bm . bm_rowsize ;
2017-11-01 02:01:20 +00:00
const uintptr_t dest_rowsize = canvas . cv_bitmap . bm_rowsize ;
2016-12-29 03:27:10 +00:00
auto dest = & ( canvas . cv_bitmap . get_bitmap_data ( ) [ dest_rowsize * y + x ] ) ;
2014-12-02 03:24:38 +00:00
auto src = bm . get_bitmap_data ( ) ;
2015-02-14 22:48:27 +00:00
for ( uint_fast32_t y1 = bm . bm_h ; y1 - - ; )
{
2016-12-29 03:27:10 +00:00
f ( dest , src , src_width ) ;
2016-05-28 17:31:26 +00:00
src + = src_rowsize ;
2015-02-05 03:03:49 +00:00
dest + = dest_rowsize ;
2006-03-20 17:12:09 +00:00
}
}
2019-07-22 00:51:01 +00:00
static void gr_ubitmap00 ( grs_canvas & canvas , const unsigned x , const unsigned y , const grs_bitmap & bm )
{
2021-01-17 22:23:23 +00:00
# if defined(WIN32) && defined(__GNUC__) && (__GNUC__ >= 6 && __GNUC__ <= 10)
2017-04-22 21:23:55 +00:00
/*
* When using memcpy directly , i686 - w64 - mingw32 - g + + - 6.3 .0 fails to
* deduce the template instantiation correctly , leading to a compiler
* crash . i686 - w64 - mingw32 - g + + - 5.4 .0 works correctly . Other platforms
2018-08-20 00:34:16 +00:00
* work correctly . For the affected cases , define a trivial wrapper ,
* which gcc deduces correctly .
*
2019-07-22 00:51:01 +00:00
* This appears to be gcc bug # 71740.
* < https : //gcc.gnu.org/bugzilla/show_bug.cgi?id=71740>
*
2018-08-20 00:34:16 +00:00
* Known affected :
* - i686 - w64 - mingw32 - g + + - 6.3 .0
* - i686 - w64 - mingw32 - g + + - 7.3 .0
2021-01-17 22:23:23 +00:00
* - i686 - w64 - mingw32 - g + + - 10.2 .0
2018-08-20 00:34:16 +00:00
*
2019-07-22 00:51:01 +00:00
* Restrict this workaround to known broken versions .
2017-04-22 21:23:55 +00:00
*/
2019-07-22 00:51:01 +00:00
void * ( __attribute__ ( ( __cdecl__ ) ) * d_memcpy ) ( void * , const void * , size_t ) = memcpy ;
2017-04-22 21:23:55 +00:00
# else
# define d_memcpy memcpy
# endif
gr_for_each_bitmap_line ( canvas , x , y , bm , d_memcpy ) ;
2016-12-29 03:27:10 +00:00
}
2016-09-24 18:06:11 +00:00
# if !DXX_USE_OGL
2016-12-29 03:27:11 +00:00
static void gr_ubitmap00m ( grs_canvas & canvas , const unsigned x , const unsigned y , const grs_bitmap & bm )
2006-03-20 17:12:09 +00:00
{
2016-12-29 03:27:11 +00:00
gr_for_each_bitmap_line ( canvas , x , y , bm , gr_linear_rep_movsdm ) ;
2006-03-20 17:12:09 +00:00
}
2015-12-04 03:36:31 +00:00
# endif
2006-03-20 17:12:09 +00:00
2014-12-05 02:44:01 +00:00
template < typename F >
2016-12-29 03:27:12 +00:00
static inline void gr_for_each_bitmap_byte ( grs_canvas & canvas , const uint_fast32_t bx , const uint_fast32_t by , const grs_bitmap & bm , F f )
2006-03-20 17:12:09 +00:00
{
2014-11-30 22:09:18 +00:00
auto src = bm . bm_data ;
2014-12-05 02:44:01 +00:00
const auto ey = by + bm . bm_h ;
const auto ex = bx + bm . bm_w ;
2019-05-04 18:27:37 +00:00
range_for ( const auto iy , xrange ( by , ey ) )
range_for ( const auto ix , xrange ( bx , ex ) )
2016-12-29 03:27:12 +00:00
f ( canvas , src + + , ix , iy ) ;
2014-12-05 02:44:01 +00:00
}
2016-12-29 03:27:12 +00:00
static void gr_ubitmap012 ( grs_canvas & canvas , const unsigned x , const unsigned y , const grs_bitmap & bm )
2014-12-05 02:44:01 +00:00
{
2020-07-16 02:31:04 +00:00
const auto a = [ ] ( grs_canvas & cv , const color_palette_index * const src , const uint_fast32_t px , const uint_fast32_t py ) {
2016-02-12 04:02:28 +00:00
const auto color = * src ;
2017-03-11 19:56:23 +00:00
gr_upixel ( cv . cv_bitmap , px , py , color ) ;
2014-12-05 02:44:01 +00:00
} ;
2016-12-29 03:27:12 +00:00
gr_for_each_bitmap_byte ( canvas , x , y , bm , a ) ;
2006-03-20 17:12:09 +00:00
}
2016-09-24 18:06:11 +00:00
# if !DXX_USE_OGL
2016-12-29 03:27:12 +00:00
static void gr_ubitmap012m ( grs_canvas & canvas , const unsigned x , const unsigned y , const grs_bitmap & bm )
2006-03-20 17:12:09 +00:00
{
2020-07-16 02:31:04 +00:00
const auto a = [ ] ( grs_canvas & cv , const color_palette_index * const src , const uint_fast32_t px , const uint_fast32_t py ) {
2014-12-05 02:44:01 +00:00
const uint8_t c = * src ;
if ( c ! = 255 )
{
2017-03-11 19:56:23 +00:00
gr_upixel ( cv . cv_bitmap , px , py , c ) ;
2006-03-20 17:12:09 +00:00
}
2014-12-05 02:44:01 +00:00
} ;
2016-12-29 03:27:12 +00:00
gr_for_each_bitmap_byte ( canvas , x , y , bm , a ) ;
2006-03-20 17:12:09 +00:00
}
2015-12-04 03:36:31 +00:00
# endif
2006-03-20 17:12:09 +00:00
2019-05-04 18:27:36 +00:00
static void gr_ubitmapGENERIC ( grs_canvas & canvas , const unsigned x , const unsigned y , const grs_bitmap & bm )
2006-03-20 17:12:09 +00:00
{
2015-02-14 22:48:27 +00:00
const uint_fast32_t bm_h = bm . bm_h ;
const uint_fast32_t bm_w = bm . bm_w ;
2019-05-04 18:27:37 +00:00
range_for ( const uint_fast32_t y1 , xrange ( bm_h ) )
2015-02-14 22:48:27 +00:00
{
2019-05-04 18:27:37 +00:00
range_for ( const uint_fast32_t x1 , xrange ( bm_w ) )
2015-02-14 22:48:27 +00:00
{
2016-02-12 04:02:28 +00:00
const auto color = gr_gpixel ( bm , x1 , y1 ) ;
2017-03-11 19:56:23 +00:00
gr_upixel ( canvas . cv_bitmap , x + x1 , y + y1 , color ) ;
2006-03-20 17:12:09 +00:00
}
}
}
2016-09-24 18:06:11 +00:00
# if !DXX_USE_OGL
2016-12-29 03:27:12 +00:00
static void gr_ubitmapGENERICm ( grs_canvas & canvas , const unsigned x , const unsigned y , const grs_bitmap & bm )
2006-03-20 17:12:09 +00:00
{
2015-02-14 22:48:27 +00:00
const uint_fast32_t bm_h = bm . bm_h ;
const uint_fast32_t bm_w = bm . bm_w ;
2019-05-04 18:27:37 +00:00
range_for ( const uint_fast32_t y1 , xrange ( bm_h ) )
2015-02-14 22:48:27 +00:00
{
2019-05-04 18:27:37 +00:00
range_for ( const uint_fast32_t x1 , xrange ( bm_w ) )
2015-02-14 22:48:27 +00:00
{
2016-02-12 04:02:28 +00:00
const auto c = gr_gpixel ( bm , x1 , y1 ) ;
2020-07-16 02:31:04 +00:00
if ( c ! = TRANSPARENCY_COLOR )
{
2017-03-11 19:56:23 +00:00
gr_upixel ( canvas . cv_bitmap , x + x1 , y + y1 , c ) ;
2006-03-20 17:12:09 +00:00
}
}
}
}
2015-12-04 03:36:31 +00:00
# endif
2006-03-20 17:12:09 +00:00
2020-12-26 21:17:29 +00:00
}
2016-12-29 03:27:12 +00:00
void gr_ubitmap ( grs_canvas & canvas , grs_bitmap & bm )
2015-07-25 23:10:47 +00:00
{
2014-11-30 22:09:19 +00:00
const unsigned x = 0 ;
const unsigned y = 0 ;
2009-11-30 22:42:55 +00:00
2015-07-25 23:10:47 +00:00
const auto source = bm . get_type ( ) ;
2016-12-29 03:27:12 +00:00
const auto dest = canvas . cv_bitmap . get_type ( ) ;
2009-11-30 22:42:55 +00:00
2016-05-28 17:31:26 +00:00
if ( source = = bm_mode : : linear ) {
2009-11-30 22:42:55 +00:00
switch ( dest )
{
2016-05-28 17:31:26 +00:00
case bm_mode : : linear :
2017-01-15 00:03:13 +00:00
if ( bm . get_flag_mask ( BM_FLAG_RLE ) )
2016-12-29 03:27:12 +00:00
gr_bm_ubitblt00_rle ( bm . bm_w , bm . bm_h , x , y , 0 , 0 , bm , canvas . cv_bitmap ) ;
2009-11-30 22:42:55 +00:00
else
2016-12-29 03:27:12 +00:00
gr_ubitmap00 ( canvas , x , y , bm ) ;
2009-11-30 22:42:55 +00:00
return ;
2016-09-24 18:06:11 +00:00
# if DXX_USE_OGL
2016-05-28 17:31:26 +00:00
case bm_mode : : ogl :
2021-11-01 03:37:18 +00:00
ogl_ubitmapm_cs ( canvas , x , y , opengl_bitmap_use_dst_canvas , opengl_bitmap_use_dst_canvas , bm , ogl_colors : : white ) ;
2009-11-30 22:42:55 +00:00
return ;
# endif
default :
2016-12-29 03:27:12 +00:00
gr_ubitmap012 ( canvas , x , y , bm ) ;
2009-11-30 22:42:55 +00:00
return ;
}
} else {
2016-12-29 03:27:12 +00:00
gr_ubitmapGENERIC ( canvas , x , y , bm ) ;
2009-11-30 22:42:55 +00:00
}
}
2016-09-24 18:06:11 +00:00
# if !DXX_USE_OGL
2016-12-29 03:27:13 +00:00
void gr_ubitmapm ( grs_canvas & canvas , const unsigned x , const unsigned y , grs_bitmap & bm )
2014-12-02 03:35:01 +00:00
{
2015-07-25 23:10:47 +00:00
const auto source = bm . get_type ( ) ;
2016-05-28 17:31:26 +00:00
if ( source = = bm_mode : : linear ) {
2016-12-29 03:27:13 +00:00
switch ( canvas . cv_bitmap . get_type ( ) )
2009-11-30 22:42:55 +00:00
{
2016-05-28 17:31:26 +00:00
case bm_mode : : linear :
2017-01-15 00:03:13 +00:00
if ( bm . get_flag_mask ( BM_FLAG_RLE ) )
2016-12-29 03:27:13 +00:00
gr_bm_ubitblt00m_rle ( bm . bm_w , bm . bm_h , x , y , 0 , 0 , bm , canvas . cv_bitmap ) ;
2009-11-30 22:42:55 +00:00
else
2016-12-29 03:27:13 +00:00
gr_ubitmap00m ( canvas , x , y , bm ) ;
2009-11-30 22:42:55 +00:00
return ;
default :
2016-12-29 03:27:13 +00:00
gr_ubitmap012m ( canvas , x , y , bm ) ;
2009-11-30 22:42:55 +00:00
return ;
}
} else {
2016-12-29 03:27:13 +00:00
gr_ubitmapGENERICm ( canvas , x , y , bm ) ;
2009-11-30 22:42:55 +00:00
}
}
2020-12-26 21:17:29 +00:00
namespace {
2006-03-20 17:12:09 +00:00
// From Linear to Linear
2019-05-04 18:27:36 +00:00
static void gr_bm_ubitblt00 ( const unsigned w , const unsigned h , const unsigned dx , const unsigned dy , const unsigned sx , const unsigned sy , const grs_bitmap & src , grs_bitmap & dest )
2006-03-20 17:12:09 +00:00
{
2009-11-30 22:42:55 +00:00
//int src_bm_rowsize_2, dest_bm_rowsize_2;
2014-12-02 03:35:01 +00:00
auto sbits = & src . get_bitmap_data ( ) [ ( src . bm_rowsize * sy ) + sx ] ;
auto dbits = & dest . get_bitmap_data ( ) [ ( dest . bm_rowsize * dy ) + dx ] ;
2017-11-01 02:01:20 +00:00
const auto dstep = dest . bm_rowsize ;
2006-03-20 17:12:09 +00:00
// No interlacing, copy the whole buffer.
2015-02-14 22:48:27 +00:00
for ( uint_fast32_t i = h ; i - - ; )
{
2009-11-30 22:42:55 +00:00
gr_linear_movsd ( sbits , dbits , w ) ;
//memcpy(dbits, sbits, w);
2014-12-02 03:35:01 +00:00
sbits + = src . bm_rowsize ;
2009-11-30 22:42:55 +00:00
dbits + = dstep ;
}
2006-03-20 17:12:09 +00:00
}
2009-11-30 22:42:55 +00:00
2006-03-20 17:12:09 +00:00
// From Linear to Linear Masked
2019-05-04 18:27:36 +00:00
static void gr_bm_ubitblt00m ( const unsigned w , const uint_fast32_t h , const unsigned dx , const unsigned dy , const unsigned sx , const unsigned sy , const grs_bitmap & src , grs_bitmap & dest )
2006-03-20 17:12:09 +00:00
{
2009-11-30 22:42:55 +00:00
//int src_bm_rowsize_2, dest_bm_rowsize_2;
2014-12-02 03:35:01 +00:00
auto sbits = & src . get_bitmap_data ( ) [ ( src . bm_rowsize * sy ) + sx ] ;
auto dbits = & dest . get_bitmap_data ( ) [ ( dest . bm_rowsize * dy ) + dx ] ;
2006-03-20 17:12:09 +00:00
// No interlacing, copy the whole buffer.
2015-07-21 02:57:27 +00:00
{
2014-12-05 03:31:07 +00:00
for ( auto i = h ; i ; - - i )
{
2016-12-29 03:27:10 +00:00
gr_linear_rep_movsdm ( dbits , sbits , w ) ;
2014-12-02 03:35:01 +00:00
sbits + = src . bm_rowsize ;
dbits + = dest . bm_rowsize ;
2006-03-20 17:12:09 +00:00
}
}
}
2020-12-26 21:17:29 +00:00
}
2017-02-11 21:42:32 +00:00
void gr_bm_ubitblt ( grs_canvas & canvas , const unsigned w , const unsigned h , const int dx , const int dy , const int sx , const int sy , const grs_bitmap & src )
2006-03-20 17:12:09 +00:00
{
2017-02-11 21:42:32 +00:00
auto & dest = canvas . cv_bitmap ;
2016-05-28 17:31:26 +00:00
if ( src . get_type ( ) = = bm_mode : : linear & & dest . get_type ( ) = = bm_mode : : linear )
2006-03-20 17:12:09 +00:00
{
2017-01-15 00:03:13 +00:00
if ( src . get_flag_mask ( BM_FLAG_RLE ) )
2014-12-02 03:35:01 +00:00
gr_bm_ubitblt00_rle ( w , h , dx , dy , sx , sy , src , dest ) ;
2006-03-20 17:12:09 +00:00
else
2014-12-02 03:35:01 +00:00
gr_bm_ubitblt00 ( w , h , dx , dy , sx , sy , src , dest ) ;
2006-03-20 17:12:09 +00:00
return ;
}
2017-01-15 00:03:13 +00:00
if ( src . get_flag_mask ( BM_FLAG_RLE ) & & src . get_type ( ) = = bm_mode : : linear )
2015-07-25 23:10:47 +00:00
{
2017-02-11 21:42:33 +00:00
gr_bm_ubitblt0x_rle ( canvas , w , h , dx , dy , sx , sy , src ) ;
2009-11-30 22:42:55 +00:00
return ;
2006-03-20 17:12:09 +00:00
}
2019-05-04 18:27:37 +00:00
range_for ( const uint_fast32_t y1 , xrange ( h ) )
range_for ( const uint_fast32_t x1 , xrange ( w ) )
2017-02-11 21:42:32 +00:00
gr_bm_pixel ( canvas , dest , dx + x1 , dy + y1 , gr_gpixel ( src , sx + x1 , sy + y1 ) ) ;
2006-03-20 17:12:09 +00:00
}
2015-12-04 03:36:31 +00:00
# endif
2006-03-20 17:12:09 +00:00
2010-06-18 07:31:06 +00:00
// Clipped bitmap ...
2016-12-29 03:27:13 +00:00
void gr_bitmap ( grs_canvas & canvas , const unsigned x , const unsigned y , grs_bitmap & bm )
2006-03-20 17:12:09 +00:00
{
2014-12-02 03:35:01 +00:00
int dx1 = x , dx2 = x + bm . bm_w - 1 ;
int dy1 = y , dy2 = y + bm . bm_h - 1 ;
2006-03-20 17:12:09 +00:00
2016-12-29 03:27:13 +00:00
if ( dx1 > = canvas . cv_bitmap . bm_w | | dx2 < 0 )
return ;
if ( dy1 > = canvas . cv_bitmap . bm_h | | dy2 < 0 )
return ;
2013-06-23 04:34:40 +00:00
// Draw bitmap bm[x,y] into (dx1,dy1)-(dx2,dy2)
2016-09-24 18:06:11 +00:00
# if DXX_USE_OGL
2021-11-01 03:37:18 +00:00
ogl_ubitmapm_cs ( canvas , x , y , opengl_bitmap_use_src_bitmap , opengl_bitmap_use_src_bitmap , bm , ogl_colors : : white ) ;
2013-06-23 04:34:40 +00:00
# else
2016-12-29 03:27:13 +00:00
int sx = 0 , sy = 0 ;
2012-04-15 14:15:21 +00:00
if ( dx1 < 0 )
{
sx = - dx1 ;
dx1 = 0 ;
}
if ( dy1 < 0 )
{
sy = - dy1 ;
dy1 = 0 ;
}
2016-12-29 03:27:13 +00:00
if ( dx2 > = canvas . cv_bitmap . bm_w )
dx2 = canvas . cv_bitmap . bm_w - 1 ;
if ( dy2 > = canvas . cv_bitmap . bm_h )
dy2 = canvas . cv_bitmap . bm_h - 1 ;
2010-06-18 07:31:06 +00:00
2017-02-11 21:42:32 +00:00
gr_bm_ubitblt ( canvas , dx2 - dx1 + 1 , dy2 - dy1 + 1 , dx1 , dy1 , sx , sy , bm ) ;
2012-04-09 09:30:40 +00:00
# endif
2006-03-20 17:12:09 +00:00
}
2016-09-24 18:06:11 +00:00
# if !DXX_USE_OGL
2017-01-01 00:45:43 +00:00
void gr_bitmapm ( grs_canvas & canvas , const unsigned x , const unsigned y , const grs_bitmap & bm )
2006-03-20 17:12:09 +00:00
{
2014-12-02 03:35:01 +00:00
int dx1 = x , dx2 = x + bm . bm_w - 1 ;
int dy1 = y , dy2 = y + bm . bm_h - 1 ;
2006-03-20 17:12:09 +00:00
int sx = 0 , sy = 0 ;
2017-01-01 00:45:43 +00:00
if ( dx1 > = canvas . cv_bitmap . bm_w | | dx2 < 0 )
return ;
if ( dy1 > = canvas . cv_bitmap . bm_h | | dy2 < 0 )
return ;
2006-03-20 17:12:09 +00:00
if ( dx1 < 0 ) { sx = - dx1 ; dx1 = 0 ; }
if ( dy1 < 0 ) { sy = - dy1 ; dy1 = 0 ; }
2017-01-01 00:45:43 +00:00
if ( dx2 > = canvas . cv_bitmap . bm_w )
dx2 = canvas . cv_bitmap . bm_w - 1 ;
if ( dy2 > = canvas . cv_bitmap . bm_h )
dy2 = canvas . cv_bitmap . bm_h - 1 ;
2010-06-18 07:31:06 +00:00
2006-03-20 17:12:09 +00:00
// Draw bitmap bm[x,y] into (dx1,dy1)-(dx2,dy2)
2017-01-01 00:45:43 +00:00
if ( bm . get_type ( ) = = bm_mode : : linear & & canvas . cv_bitmap . get_type ( ) = = bm_mode : : linear )
2006-03-20 17:12:09 +00:00
{
2017-01-15 00:03:13 +00:00
if ( bm . get_flag_mask ( BM_FLAG_RLE ) )
2017-01-01 00:45:43 +00:00
gr_bm_ubitblt00m_rle ( dx2 - dx1 + 1 , dy2 - dy1 + 1 , dx1 , dy1 , sx , sy , bm , canvas . cv_bitmap ) ;
2006-03-20 17:12:09 +00:00
else
2017-01-01 00:45:43 +00:00
gr_bm_ubitblt00m ( dx2 - dx1 + 1 , dy2 - dy1 + 1 , dx1 , dy1 , sx , sy , bm , canvas . cv_bitmap ) ;
2006-03-20 17:12:09 +00:00
return ;
}
2017-02-11 21:42:32 +00:00
gr_bm_ubitbltm ( canvas , dx2 - dx1 + 1 , dy2 - dy1 + 1 , dx1 , dy1 , sx , sy , bm ) ;
2006-03-20 17:12:09 +00:00
}
2017-02-11 21:42:32 +00:00
void gr_bm_ubitbltm ( grs_canvas & canvas , const unsigned w , const unsigned h , const unsigned dx , const unsigned dy , const unsigned sx , const unsigned sy , const grs_bitmap & src )
2006-03-20 17:12:09 +00:00
{
ubyte c ;
2017-02-11 21:42:32 +00:00
auto & dest = canvas . cv_bitmap ;
2019-05-04 18:27:37 +00:00
range_for ( const uint_fast32_t y1 , xrange ( h ) )
range_for ( const uint_fast32_t x1 , xrange ( w ) )
2014-12-02 03:35:01 +00:00
if ( ( c = gr_gpixel ( src , sx + x1 , sy + y1 ) ) ! = 255 )
2017-02-11 21:42:32 +00:00
gr_bm_pixel ( canvas , dest , dx + x1 , dy + y1 , c ) ;
2009-11-30 22:42:55 +00:00
}
2015-12-04 03:36:31 +00:00
# endif
2009-11-30 22:42:55 +00:00
2017-02-11 21:42:30 +00:00
namespace {
class bm_rle_window : bm_rle_src_stride
2009-11-30 22:42:55 +00:00
{
2017-02-11 21:42:30 +00:00
public :
bm_rle_window ( const grs_bitmap & src ) :
bm_rle_src_stride ( src , src . get_flag_mask ( BM_FLAG_RLE_BIG ) )
2014-12-05 03:31:07 +00:00
{
2009-11-30 22:42:55 +00:00
}
2017-02-11 21:42:30 +00:00
void skip_upper_rows ( uint_fast32_t ) ;
uint8_t * init ( uint_fast32_t dx , uint_fast32_t dy , uint_fast32_t sy , grs_bitmap & dest ) ;
template < typename F >
void apply ( uint_fast32_t w , uint_fast32_t h , uint_fast32_t sx , uint8_t * dbits , uint_fast32_t bm_rowsize , F & & f ) ;
# if !DXX_USE_OGL
using bm_rle_src_stride : : src_bits ;
using bm_rle_src_stride : : advance_src_bits ;
# endif
} ;
void bm_rle_window : : skip_upper_rows ( const uint_fast32_t sy )
{
for ( uint_fast32_t i = sy ; i ; - - i )
advance_src_bits ( ) ;
2006-03-20 17:12:09 +00:00
}
2017-02-11 21:42:30 +00:00
uint8_t * bm_rle_window : : init ( const uint_fast32_t dx , const uint_fast32_t dy , const uint_fast32_t sy , grs_bitmap & dest )
{
skip_upper_rows ( sy ) ;
return & dest . get_bitmap_data ( ) [ ( dest . bm_rowsize * dy ) + dx ] ;
}
template < typename F >
void bm_rle_window : : apply ( const uint_fast32_t w , const uint_fast32_t h , const uint_fast32_t sx , uint8_t * dbits , const uint_fast32_t bm_rowsize , F & & f )
2009-11-30 22:42:55 +00:00
{
// No interlacing, copy the whole buffer.
2017-02-11 21:42:30 +00:00
for ( uint_fast32_t i = h ; i ; - - i )
2014-12-05 03:31:07 +00:00
{
2020-05-02 21:18:42 +00:00
f ( std : : exchange ( dbits , dbits + bm_rowsize ) , src_bits , sx , w ) ;
2017-02-11 21:42:30 +00:00
advance_src_bits ( ) ;
2009-11-30 22:42:55 +00:00
}
}
2019-05-04 18:27:36 +00:00
static void gr_bm_ubitblt00_rle ( const unsigned w , const unsigned h , const int dx , const int dy , const int sx , const int sy , const grs_bitmap & src , grs_bitmap & dest )
2017-02-11 21:42:30 +00:00
{
bm_rle_window bw ( src ) ;
bw . apply ( sx + w - 1 , h , sx , bw . init ( dx , dy , sy , dest ) , dest . bm_rowsize , gr_rle_expand_scanline ) ;
}
# if !DXX_USE_OGL
2019-05-04 18:27:36 +00:00
static void gr_bm_ubitblt00m_rle ( const unsigned w , const unsigned h , const int dx , const int dy , const int sx , const int sy , const grs_bitmap & src , grs_bitmap & dest )
2017-02-11 21:42:30 +00:00
{
bm_rle_window bw ( src ) ;
bw . apply ( sx + w - 1 , h , sx , bw . init ( dx , dy , sy , dest ) , dest . bm_rowsize , gr_rle_expand_scanline_masked ) ;
}
2009-11-30 22:42:55 +00:00
// in rle.c
2019-05-04 18:27:36 +00:00
static void gr_bm_ubitblt0x_rle ( grs_canvas & canvas , const unsigned w , const unsigned h , const int dx , const int dy , const int sx , const int sy , const grs_bitmap & src )
2009-11-30 22:42:55 +00:00
{
2017-02-11 21:42:30 +00:00
bm_rle_window bw ( src ) ;
bw . skip_upper_rows ( sy ) ;
2019-05-04 18:27:37 +00:00
range_for ( const uint_fast32_t y1 , xrange ( h ) )
2014-12-05 03:31:07 +00:00
{
2017-02-11 21:42:30 +00:00
const auto sbits = bw . src_bits ;
2017-02-11 21:42:33 +00:00
gr_rle_expand_scanline_generic ( canvas , canvas . cv_bitmap , dx , dy + y1 , sbits , sx , sx + w - 1 ) ;
2017-02-11 21:42:30 +00:00
bw . advance_src_bits ( ) ;
2009-11-30 22:42:55 +00:00
}
}
2015-12-04 03:36:31 +00:00
# endif
2006-03-20 17:12:09 +00:00
// rescalling bitmaps, 10/14/99 Jan Bobrowski jb@wizard.ae.krakow.pl
2014-12-05 03:29:33 +00:00
static void scale_line ( const uint8_t * in , uint8_t * out , const uint_fast32_t ilen , const uint_fast32_t olen )
2006-03-20 17:12:09 +00:00
{
2014-12-05 03:29:33 +00:00
uint_fast32_t a = olen / ilen , b = olen % ilen , c = 0 ;
for ( uint8_t * const end = out + olen ; out ! = end ; )
{
uint_fast32_t i = a ;
2006-03-20 17:12:09 +00:00
c + = b ;
if ( c > = ilen ) {
c - = ilen ;
2014-12-05 03:29:33 +00:00
+ + i ;
2006-03-20 17:12:09 +00:00
}
2014-12-08 00:41:03 +00:00
auto e = out + i ;
2020-05-02 21:18:42 +00:00
std : : fill ( std : : exchange ( out , e ) , e , * in + + ) ;
2006-03-20 17:12:09 +00:00
}
}
2014-12-02 03:35:01 +00:00
static void gr_bitmap_scale_to ( const grs_bitmap & src , grs_bitmap & dst )
2006-03-20 17:12:09 +00:00
{
2014-12-02 03:35:01 +00:00
auto s = src . get_bitmap_data ( ) ;
auto d = dst . get_bitmap_data ( ) ;
int h = src . bm_h ;
int a = dst . bm_h / h , b = dst . bm_h % h ;
2014-09-26 02:42:13 +00:00
int c = 0 , i ;
2006-03-20 17:12:09 +00:00
2015-02-14 22:48:27 +00:00
for ( uint_fast32_t y = src . bm_h ; y ; - - y ) {
2006-03-20 17:12:09 +00:00
i = a ;
c + = b ;
if ( c > = h ) {
c - = h ;
goto inside ;
}
while ( - - i > = 0 ) {
2009-11-30 22:42:55 +00:00
inside :
2014-12-02 03:35:01 +00:00
scale_line ( s , d , src . bm_w , dst . bm_w ) ;
d + = dst . bm_rowsize ;
2006-03-20 17:12:09 +00:00
}
2014-12-02 03:35:01 +00:00
s + = src . bm_rowsize ;
2006-03-20 17:12:09 +00:00
}
}
2020-12-26 21:17:29 +00:00
}
2017-01-01 00:45:43 +00:00
void show_fullscr ( grs_canvas & canvas , grs_bitmap & bm )
2006-03-20 17:12:09 +00:00
{
2017-01-01 00:45:43 +00:00
auto & scr = canvas . cv_bitmap ;
2016-09-24 18:06:11 +00:00
# if DXX_USE_OGL
2016-05-28 17:31:26 +00:00
if ( bm . get_type ( ) = = bm_mode : : linear & & scr . get_type ( ) = = bm_mode : : ogl & &
2015-03-22 18:49:21 +00:00
bm . bm_w < = grd_curscreen - > get_screen_width ( ) & & bm . bm_h < = grd_curscreen - > get_screen_height ( ) ) // only scale with OGL if bitmap is not bigger than screen size
2007-02-06 19:23:33 +00:00
{
2021-11-01 03:37:18 +00:00
ogl_ubitmapm_cs ( canvas , 0 , 0 , opengl_bitmap_use_dst_canvas , opengl_bitmap_use_dst_canvas , bm , ogl_colors : : white ) ; //use opengl to scale, faster and saves ram. -MPM
2006-03-20 17:12:09 +00:00
return ;
}
# endif
2016-05-28 17:31:26 +00:00
if ( scr . get_type ( ) ! = bm_mode : : linear )
2015-07-25 23:10:47 +00:00
{
2014-12-02 03:35:01 +00:00
grs_bitmap_ptr p = gr_create_bitmap ( scr . bm_w , scr . bm_h ) ;
auto & tmp = * p . get ( ) ;
gr_bitmap_scale_to ( bm , tmp ) ;
2017-01-01 00:45:43 +00:00
gr_bitmap ( canvas , 0 , 0 , tmp ) ;
2006-03-20 17:12:09 +00:00
return ;
}
2014-12-02 03:35:01 +00:00
gr_bitmap_scale_to ( bm , scr ) ;
2006-03-20 17:12:09 +00:00
}
2010-06-18 07:31:06 +00:00
// Find transparent area in bitmap
2014-12-02 03:35:01 +00:00
void gr_bitblt_find_transparent_area ( const grs_bitmap & bm , unsigned & minx , unsigned & miny , unsigned & maxx , unsigned & maxy )
2010-06-18 07:31:06 +00:00
{
2014-07-01 02:30:39 +00:00
using std : : advance ;
2014-07-01 00:23:30 +00:00
using std : : min ;
using std : : max ;
2010-06-18 07:31:06 +00:00
2017-01-15 00:03:13 +00:00
if ( ! bm . get_flag_mask ( BM_FLAG_TRANSPARENT ) )
2010-06-18 07:31:06 +00:00
return ;
2014-12-02 03:35:01 +00:00
minx = bm . bm_w - 1 ;
2014-07-01 00:23:30 +00:00
maxx = 0 ;
2014-12-02 03:35:01 +00:00
miny = bm . bm_h - 1 ;
2014-07-01 00:23:30 +00:00
maxy = 0 ;
2010-06-18 07:31:06 +00:00
2014-07-01 02:30:39 +00:00
unsigned i = 0 , count = 0 ;
2020-07-16 02:31:04 +00:00
auto check = [ & ] ( unsigned x , unsigned y , const color_palette_index c ) {
2014-07-01 02:30:39 +00:00
if ( c = = TRANSPARENCY_COLOR ) { // don't look for transparancy color here.
count + + ;
minx = min ( x , minx ) ;
miny = min ( y , miny ) ;
maxx = max ( x , maxx ) ;
maxy = max ( y , maxy ) ;
}
} ;
2010-06-18 07:31:06 +00:00
// decode the bitmap
2015-02-14 22:48:27 +00:00
const uint_fast32_t bm_h = bm . bm_h ;
const uint_fast32_t bm_w = bm . bm_w ;
2017-01-15 00:03:13 +00:00
if ( bm . get_flag_mask ( BM_FLAG_RLE ) )
{
2017-02-11 21:42:30 +00:00
bm_rle_expand expander ( bm ) ;
for ( uint_fast32_t y = 0 ; ; + + y )
2014-07-01 02:30:39 +00:00
{
2020-05-02 21:18:42 +00:00
std : : array < uint8_t , 4096 > buf ;
2017-02-11 21:42:30 +00:00
if ( expander . step ( bm_rle_expand_range ( buf ) ) ! = bm_rle_expand : : again )
break ;
2019-05-04 18:27:37 +00:00
range_for ( const uint_fast32_t x , xrange ( bm_w ) )
2014-07-01 02:30:39 +00:00
check ( x , y , buf [ x ] ) ;
2010-06-18 07:31:06 +00:00
}
}
else
{
2019-05-04 18:27:37 +00:00
range_for ( const uint_fast32_t y , xrange ( bm_h ) )
range_for ( const uint_fast32_t x , xrange ( bm_w ) )
2014-12-02 03:35:01 +00:00
check ( x , y , bm . bm_data [ i + + ] ) ;
2010-06-18 07:31:06 +00:00
}
Assert ( count ) ;
}
2015-12-05 22:57:23 +00:00
}