2019-10-05 17:28:05 +00:00
# pragma once
# include <stdint.h>
# include "zstring.h"
# include "tarray.h"
# include "textures.h"
# include "bitmap.h"
# include "memarena.h"
class FImageSource ;
using PrecacheInfo = TMap < int , std : : pair < int , int > > ;
2020-05-23 21:46:44 +00:00
// Doom patch format header
struct patch_t
{
int16_t width ; // bounding box size
int16_t height ;
int16_t leftoffset ; // pixels to the left of origin
int16_t topoffset ; // pixels below the origin
uint32_t columnofs [ 1 ] ; // only [width] used
} ;
2019-10-05 17:28:05 +00:00
struct PalettedPixels
{
friend class FImageSource ;
TArrayView < uint8_t > Pixels ;
private :
TArray < uint8_t > PixelStore ;
bool ownsPixels ( ) const
{
return Pixels . Data ( ) = = PixelStore . Data ( ) ;
}
} ;
// This represents a naked image. It has no high level logic attached to it.
// All it can do is provide raw image data to its users.
class FImageSource
{
2020-05-23 21:46:44 +00:00
friend class FBrightmapTexture ;
2019-10-05 17:28:05 +00:00
protected :
2020-05-23 21:46:44 +00:00
static FMemArena ImageArena ;
static TArray < FImageSource * > ImageForLump ;
2019-10-05 17:28:05 +00:00
static int NextID ;
int SourceLump ;
int Width = 0 , Height = 0 ;
int LeftOffset = 0 , TopOffset = 0 ; // Offsets stored in the image.
bool bUseGamePalette = false ; // true if this is an image without its own color set.
int ImageID = - 1 ;
// Internal image creation functions. All external access should go through the cache interface,
// so that all code can benefit from future improvements to that.
2020-05-23 21:46:44 +00:00
virtual TArray < uint8_t > CreatePalettedPixels ( int conversion ) ;
virtual int CopyPixels ( FBitmap * bmp , int conversion ) ; // This will always ignore 'luminance'.
int CopyTranslatedPixels ( FBitmap * bmp , const PalEntry * remap ) ;
2019-10-05 17:28:05 +00:00
public :
void CopySize ( FImageSource & other )
{
Width = other . Width ;
Height = other . Height ;
LeftOffset = other . LeftOffset ;
TopOffset = other . TopOffset ;
SourceLump = other . SourceLump ;
}
2020-05-23 21:46:44 +00:00
// Images are statically allocated and freed in bulk. None of the subclasses may hold any destructible data.
void * operator new ( size_t block ) { return ImageArena . Alloc ( block ) ; }
void operator delete ( void * block ) { }
2019-10-05 17:28:05 +00:00
bool bMasked = true ; // Image (might) have holes (Assume true unless proven otherwise!)
int8_t bTranslucent = - 1 ; // Image has pixels with a non-0/1 value. (-1 means the user needs to do a real check)
int GetId ( ) const { return ImageID ; }
// 'noremap0' will only be looked at by FPatchTexture and forwarded by FMultipatchTexture.
2020-05-23 21:46:44 +00:00
// Either returns a reference to the cache, or a newly created item. The return of this has to be considered transient. If you need to store the result, use GetPalettedPixels
PalettedPixels GetCachedPalettedPixels ( int conversion ) ;
// tries to get a buffer from the cache. If not available, create a new one. If further references are pending, create a copy.
TArray < uint8_t > GetPalettedPixels ( int conversion ) ;
// Unlile for paletted images there is no variant here that returns a persistent bitmap, because all users have to process the returned image into another format.
FBitmap GetCachedBitmap ( const PalEntry * remap , int conversion , int * trans = nullptr ) ;
static void ClearImages ( ) { ImageArena . FreeAll ( ) ; ImageForLump . Clear ( ) ; NextID = 0 ; }
static FImageSource * GetImage ( int lumpnum , bool checkflat ) ;
2019-10-05 17:28:05 +00:00
// Conversion option
enum EType
{
normal = 0 ,
luminance = 1 ,
noremap0 = 2
} ;
FImageSource ( int sourcelump = - 1 ) : SourceLump ( sourcelump ) { ImageID = + + NextID ; }
2020-05-23 21:46:44 +00:00
virtual ~ FImageSource ( ) { }
2019-10-05 17:28:05 +00:00
int GetWidth ( ) const
{
return Width ;
}
int GetHeight ( ) const
{
return Height ;
}
std : : pair < int , int > GetSize ( ) const
{
return std : : make_pair ( Width , Height ) ;
}
std : : pair < int , int > GetOffsets ( ) const
{
return std : : make_pair ( LeftOffset , TopOffset ) ;
}
void SetOffsets ( int x , int y )
{
LeftOffset = x ;
TopOffset = y ;
}
int LumpNum ( ) const
{
return SourceLump ;
}
bool UseGamePalette ( ) const
{
return bUseGamePalette ;
}
2020-05-23 21:46:44 +00:00
virtual void CollectForPrecache ( PrecacheInfo & info , bool requiretruecolor ) ;
static void BeginPrecaching ( ) ;
static void EndPrecaching ( ) ;
static void RegisterForPrecache ( FImageSource * img , bool requiretruecolor ) ;
2019-10-05 17:28:05 +00:00
} ;
2020-05-23 22:38:10 +00:00
//==========================================================================
//
// A texture defined in a Build TILESxxx.ART file
//
//==========================================================================
struct FRemapTable ;
class FBuildTexture : public FImageSource
{
public :
FBuildTexture ( const FString & pathprefix , int tilenum , const uint8_t * pixels , FRemapTable * translation , int width , int height , int left , int top ) ;
TArray < uint8_t > CreatePalettedPixels ( int conversion ) override ;
int CopyPixels ( FBitmap * bmp , int conversion ) override ;
protected :
const uint8_t * RawPixels ;
FRemapTable * Translation ;
} ;
2019-10-05 17:28:05 +00:00
//==========================================================================
//
// a TGA texture
//
//==========================================================================
class FImageTexture : public FTexture
{
FImageSource * mImage ;
public :
FImageTexture ( FImageSource * image , const char * name = nullptr ) ;
2019-12-24 18:47:34 +00:00
~ FImageTexture ( )
2019-10-05 17:28:05 +00:00
{
2019-12-24 18:47:34 +00:00
if ( mImage ) delete mImage ;
2019-10-05 17:28:05 +00:00
}
2019-12-24 18:47:34 +00:00
void Create8BitPixels ( uint8_t * buffer ) override ;
2019-10-05 17:28:05 +00:00
FImageSource * GetImage ( ) const override { return mImage ; }
2019-10-18 17:06:57 +00:00
FBitmap GetBgraBitmap ( const PalEntry * p , int * trans ) override ;
2019-10-05 17:28:05 +00:00
} ;