Files
scummvm-cursorfix/engines/ags/shared/gfx/allegro_bitmap.h
2026-02-02 04:50:13 +01:00

278 lines
11 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
//=============================================================================
//
// Allegro lib based bitmap
//
// TODO: probably should be moved to the Engine; check again when (if) it is
// clear that AGS.Native does not need allegro for drawing.
//
//=============================================================================
#ifndef AGS_SHARED_GFX_ALLEGRO_BITMAP_H
#define AGS_SHARED_GFX_ALLEGRO_BITMAP_H
#include "graphics/screen.h"
#include "ags/lib/allegro.h" // BITMAP
#include "ags/shared/core/types.h"
#include "ags/shared/gfx/bitmap.h"
#include "ags/shared/util/string.h"
namespace AGS3 {
namespace AGS {
namespace Shared {
class Bitmap {
public:
Bitmap();
Bitmap(int width, int height, int color_depth = 0);
Bitmap(Bitmap *src, const Rect &rc);
Bitmap(BITMAP *al_bmp, bool shared_data);
~Bitmap();
// Allocate new bitmap.
// NOTE: color_depth is in BITS per pixel (i.e. 8, 16, 24, 32...).
// NOTE: in all of these color_depth may be passed as 0 in which case a default
// color depth will be used (as previously set for the system).
// TODO: color_depth = 0 is used to call Allegro's create_bitmap, which uses
// some global color depth setting; not sure if this is OK to use for generic class,
// revise this in future
bool Create(int width, int height, int color_depth = 0);
// Create Bitmap and clear to transparent color
bool CreateTransparent(int width, int height, int color_depth = 0);
// Creates a sub-bitmap of the given bitmap; the sub-bitmap is a reference to
// particular region inside a parent.
// WARNING: the parent bitmap MUST be kept in memory for as long as sub-bitmap exists!
bool CreateSubBitmap(Bitmap *src, const Rect &rc);
// Resizes existing sub-bitmap within the borders of its parent
bool ResizeSubBitmap(int width, int height);
// Creates a plain copy of the given bitmap, optionally converting to a different color depth;
// pass color depth 0 to keep the original one.
bool CreateCopy(Bitmap *src, int color_depth = 0);
// TODO: this is a temporary solution for plugin support
// Wraps a raw allegro BITMAP object, optionally owns it (will delete on disposal)
bool WrapAllegroBitmap(BITMAP *al_bmp, bool shared_data);
// Deallocate bitmap
void Destroy();
bool LoadFromFile(const String &filename) {
return LoadFromFile(filename.GetCStr());
}
bool LoadFromFile(const char *filename);
bool LoadFromFile(PACKFILE *pf);
bool SaveToFile(const String &filename, const void *palette) {
return SaveToFile(filename.GetCStr(), palette);
}
bool SaveToFile(Common::WriteStream &out, const void *palette);
bool SaveToFile(const char *filename, const void *palette);
// TODO: This is temporary solution for cases when we cannot replace
// use of raw BITMAP struct with Bitmap
inline BITMAP *GetAllegroBitmap() {
return _alBitmap;
}
// Is this a "normal" bitmap created by application which data can be directly accessed for reading and writing
inline bool IsMemoryBitmap() const {
return true;
}
// Is this a video bitmap
inline bool IsVideoBitmap() const {
return dynamic_cast<Graphics::Screen *>(_alBitmap) != nullptr;
}
// Is this a linear bitmap, the one that can be accessed linearly within each scanline
inline bool IsLinearBitmap() const {
return true;
}
// Is this a subbitmap, referencing a part of another, bigger one?
inline bool isSubBitmap() const {
return _alBitmap->isSubBitmap();
}
// Do both bitmaps share same data (usually: subbitmaps, or parent/subbitmap)
inline bool IsSameBitmap(Bitmap *other) const {
return is_same_bitmap(_alBitmap, other->_alBitmap) != 0;
}
// Checks if bitmap cannot be used
inline bool IsNull() const {
return !_alBitmap;
}
// Checks if bitmap has zero size: either width or height (or both) is zero
inline bool IsEmpty() const {
return GetWidth() == 0 || GetHeight() == 0;
}
inline int GetWidth() const {
return _alBitmap->w;
}
inline int GetHeight() const {
return _alBitmap->h;
}
inline Size GetSize() const {
return Size(_alBitmap->w, _alBitmap->h);
}
// Get sub-bitmap's offset position within its parent
inline Point GetSubOffset() const {
Common::Point pt = _alBitmap->getOffsetFromOwner();
return Point(pt.x, pt.y);
}
inline int GetColorDepth() const {
return bitmap_color_depth(_alBitmap);
}
// BPP: bytes per pixel
inline int GetBPP() const {
return (GetColorDepth() + 7) / 8;
}
// CHECKME: probably should not be exposed, see comment to GetData()
inline int GetDataSize() const {
return GetWidth() * GetHeight() * GetBPP();
}
// Gets scanline length in bytes (is the same for any scanline)
inline int GetLineLength() const {
return GetWidth() * GetBPP();
}
// TODO: replace with byte *
// Gets a pointer to underlying graphic data
// FIXME: actually not a very good idea, since there's no 100% guarantee the scanline positions in memory are sequential
inline const unsigned char *GetData() const {
return _alBitmap->getPixels();
}
// Get scanline for direct reading
inline const unsigned char *GetScanLine(int index) const {
assert(index >= 0 && index < GetHeight());
return _alBitmap->getBasePtr(0, index);
}
inline unsigned char *GetScanLine(int index) {
assert(index >= 0 && index < GetHeight());
return (unsigned char *)_alBitmap->getBasePtr(0, index);
}
// Get bitmap's mask color (transparent color)
inline color_t GetMaskColor() const {
return bitmap_mask_color(_alBitmap);
}
// Converts AGS color-index into RGB color according to the bitmap format.
// TODO: this method was added to the Bitmap class during large refactoring,
// but that's a mistake, because in retrospect is has nothing to do with
// bitmap itself and should rather be a part of the game data logic.
color_t GetCompatibleColor(color_t color);
//=========================================================================
// Clipping
// TODO: consider implementing push-pop clipping stack logic.
//=========================================================================
void SetClip(const Rect &rc);
void ResetClip();
Rect GetClip() const;
//=========================================================================
// Blitting operations (drawing one bitmap over another)
//=========================================================================
// Draw other bitmap over current one
void Blit(Bitmap *src, int dst_x = 0, int dst_y = 0, BitmapMaskOption mask = kBitmap_Copy);
void Blit(Bitmap *src, int src_x, int src_y, int dst_x, int dst_y, int width, int height, BitmapMaskOption mask = kBitmap_Copy);
// Draw other bitmap in a masked mode (kBitmap_Transparency)
void MaskedBlit(Bitmap *src, int dst_x, int dst_y);
// Draw other bitmap, stretching or shrinking its size to given values
void StretchBlt(Bitmap *src, const Rect &dst_rc, BitmapMaskOption mask = kBitmap_Copy);
void StretchBlt(Bitmap *src, const Rect &src_rc, const Rect &dst_rc, BitmapMaskOption mask = kBitmap_Copy);
// Antia-aliased stretch-blit
void AAStretchBlt(Bitmap *src, const Rect &dst_rc, BitmapMaskOption mask = kBitmap_Copy);
void AAStretchBlt(Bitmap *src, const Rect &src_rc, const Rect &dst_rc, BitmapMaskOption mask = kBitmap_Copy);
// TODO: find more general way to call these operations, probably require pointer to Blending data struct?
// Draw bitmap using translucency preset
void TransBlendBlt(Bitmap *src, int dst_x, int dst_y);
// Draw bitmap using lighting preset
void LitBlendBlt(Bitmap *src, int dst_x, int dst_y, int light_amount);
// TODO: generic "draw transformed" function? What about mask option?
void FlipBlt(Bitmap *src, int dst_x, int dst_y, GraphicFlip flip);
void RotateBlt(Bitmap *src, int dst_x, int dst_y, fixed_t angle);
void RotateBlt(Bitmap *src, int dst_x, int dst_y, int pivot_x, int pivot_y, fixed_t angle);
//=========================================================================
// Pixel operations
//=========================================================================
// Fills the whole bitmap with given color (black by default)
void Clear(color_t color = 0);
void ClearTransparent();
// The PutPixel and GetPixel are supposed to be safe and therefore
// relatively slow operations. They should not be used for changing large
// blocks of bitmap memory - reading/writing from/to scan lines should be
// done in such cases.
void PutPixel(int x, int y, color_t color);
int GetPixel(int x, int y) const;
//=========================================================================
// Vector drawing operations
//=========================================================================
void DrawLine(const Line &ln, color_t color);
void DrawTriangle(const Triangle &tr, color_t color);
void DrawRect(const Rect &rc, color_t color);
void FillRect(const Rect &rc, color_t color);
void FillCircle(const Circle &circle, color_t color);
// Fills the whole bitmap with given color
void Fill(color_t color);
void FillTransparent();
// Floodfills an enclosed area, starting at point
void FloodFill(int x, int y, color_t color);
//=========================================================================
// Direct access operations
//=========================================================================
// TODO: think how to increase safety over this (some fixed memory buffer class with iterator?)
// Gets scanline for directly writing into it
inline unsigned char *GetScanLineForWriting(int index) {
assert(index >= 0 && index < GetHeight());
return _alBitmap->line[index];
}
inline unsigned char *GetDataForWriting() {
return _alBitmap->line[0];
}
// Copies buffer contents into scanline
void SetScanLine(int index, unsigned char *data, int data_size = -1);
private:
BITMAP *_alBitmap;
bool _isDataOwner;
};
namespace BitmapHelper {
// TODO: revise those functions later (currently needed in a few very specific cases)
// NOTE: the resulting object __owns__ bitmap data from now on
Bitmap *CreateRawBitmapOwner(BITMAP *al_bmp);
// NOTE: the resulting object __does not own__ bitmap data
Bitmap *CreateRawBitmapWrapper(BITMAP *al_bmp);
} // namespace BitmapHelper
} // namespace Shared
} // namespace AGS
} // namespace AGS3
#endif