1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 //=============================================================================
24 //
25 // Allegro lib based bitmap
26 //
27 // TODO: probably should be moved to the Engine; check again when (if) it is
28 // clear that AGS.Native does not need allegro for drawing.
29 //
30 //=============================================================================
31 
32 #ifndef AGS_SHARED_GFX_ALLEGRO_BITMAP_H
33 #define AGS_SHARED_GFX_ALLEGRO_BITMAP_H
34 
35 #include "graphics/screen.h"
36 #include "ags/lib/allegro.h" // BITMAP
37 #include "ags/shared/core/types.h"
38 #include "ags/shared/gfx/bitmap.h"
39 #include "ags/shared/util/string.h"
40 
41 namespace AGS3 {
42 namespace AGS {
43 namespace Shared {
44 
45 class Bitmap {
46 public:
47 	Bitmap();
48 	Bitmap(int width, int height, int color_depth = 0);
49 	Bitmap(Bitmap *src, const Rect &rc);
50 	Bitmap(BITMAP *al_bmp, bool shared_data);
51 	~Bitmap();
52 
53 	// Allocate new bitmap
54 	// CHECKME: color_depth = 0 is used to call Allegro's create_bitmap, which uses
55 	// some global color depth setting; not sure if this is OK to use for generic class,
56 	// revise this in future
57 	bool    Create(int width, int height, int color_depth = 0);
58 	bool    CreateTransparent(int width, int height, int color_depth = 0);
59 	// Allow this object to share existing bitmap data
60 	bool    CreateSubBitmap(Bitmap *src, const Rect &rc);
61 	// Create a copy of given bitmap
62 	bool    CreateCopy(Bitmap *src, int color_depth = 0);
63 	// TODO: a temporary solution for plugin support
64 	bool    WrapAllegroBitmap(BITMAP *al_bmp, bool shared_data);
65 	// Deallocate bitmap
66 	void    Destroy();
67 
LoadFromFile(const String & filename)68 	bool    LoadFromFile(const String &filename) {
69 		return LoadFromFile(filename.GetCStr());
70 	}
71 	bool    LoadFromFile(const char *filename);
SaveToFile(const String & filename,const void * palette)72 	bool    SaveToFile(const String &filename, const void *palette) {
73 		return SaveToFile(filename.GetCStr(), palette);
74 	}
75 	bool    SaveToFile(Common::WriteStream &out, const void *palette);
76 	bool    SaveToFile(const char *filename, const void *palette);
77 
78 	// TODO: This is temporary solution for cases when we cannot replace
79 	// use of raw BITMAP struct with Bitmap
GetAllegroBitmap()80 	inline BITMAP *GetAllegroBitmap() {
81 		return _alBitmap;
82 	}
83 
84 	// Is this a "normal" bitmap created by application which data can be directly accessed for reading and writing
IsMemoryBitmap()85 	inline bool IsMemoryBitmap() const {
86 		return true;
87 	}
88 	// Is this a video bitmap
IsVideoBitmap()89 	inline bool IsVideoBitmap() const {
90 		return dynamic_cast<Graphics::Screen *>(_alBitmap) != nullptr;
91 	}
92 	// Is this a linear bitmap, the one that can be accessed linearly within each scanline
IsLinearBitmap()93 	inline bool IsLinearBitmap() const {
94 		return true;
95 	}
96 
97 	// Is this a subbitmap, referencing a part of another, bigger one?
isSubBitmap()98 	inline bool isSubBitmap() const {
99 		return _alBitmap->isSubBitmap();
100 	}
101 
102 	// Checks if bitmap cannot be used
IsNull()103 	inline bool IsNull() const {
104 		return !_alBitmap;
105 	}
106 	// Checks if bitmap has zero size: either width or height (or both) is zero
IsEmpty()107 	inline bool IsEmpty() const {
108 		return GetWidth() == 0 || GetHeight() == 0;
109 	}
GetWidth()110 	inline int  GetWidth() const {
111 		return _alBitmap->w;
112 	}
GetHeight()113 	inline int  GetHeight() const {
114 		return _alBitmap->h;
115 	}
GetSize()116 	inline Size GetSize() const {
117 		return Size(_alBitmap->w, _alBitmap->h);
118 	}
119 	// Get sub-bitmap's offset position within its parent
GetSubOffset()120 	inline Point GetSubOffset() const {
121 		Common::Point pt = _alBitmap->getOffsetFromOwner();
122 		return Point(pt.x, pt.y);
123 	}
GetColorDepth()124 	inline int  GetColorDepth() const {
125 		return bitmap_color_depth(_alBitmap);
126 	}
127 	// BPP: bytes per pixel
GetBPP()128 	inline int  GetBPP() const {
129 		return (GetColorDepth() + 7) / 8;
130 	}
131 
132 	// CHECKME: probably should not be exposed, see comment to GetData()
GetDataSize()133 	inline int  GetDataSize() const {
134 		return GetWidth() * GetHeight() * GetBPP();
135 	}
136 	// Gets scanline length in bytes (is the same for any scanline)
GetLineLength()137 	inline int  GetLineLength() const {
138 		return GetWidth() * GetBPP();
139 	}
140 
141 	// TODO: replace with byte *
142 	// Gets a pointer to underlying graphic data
143 	// FIXME: actually not a very good idea, since there's no 100% guarantee the scanline positions in memory are sequential
GetData()144 	inline const unsigned char *GetData() const {
145 		return _alBitmap->getPixels();
146 	}
147 
148 	// Get scanline for direct reading
GetScanLine(int index)149 	inline const unsigned char *GetScanLine(int index) const {
150 		return (index >= 0 && index < GetHeight()) ? _alBitmap->getBasePtr(0, index) : nullptr;
151 	}
GetScanLine(int index)152 	inline unsigned char *GetScanLine(int index) {
153 		return (index >= 0 && index < GetHeight()) ? (unsigned char *)_alBitmap->getBasePtr(0, index) : nullptr;
154 	}
155 
156 	void    SetMaskColor(color_t color);
GetMaskColor()157 	inline color_t GetMaskColor() const {
158 		return bitmap_mask_color(_alBitmap);
159 	}
160 
161 	// Converts AGS color-index into RGB color according to the bitmap format.
162 	// TODO: this method was added to the Bitmap class during large refactoring,
163 	// but that's a mistake, because in retrospect is has nothing to do with
164 	// bitmap itself and should rather be a part of the game data logic.
165 	color_t GetCompatibleColor(color_t color);
166 
167 	//=========================================================================
168 	// Clipping
169 	//=========================================================================
170 	void    SetClip(const Rect &rc);
171 	void    ResetClip();
172 	Rect    GetClip() const;
173 
174 	//=========================================================================
175 	// Blitting operations (drawing one bitmap over another)
176 	//=========================================================================
177 	// Draw other bitmap over current one
178 	void    Blit(Bitmap *src, int dst_x = 0, int dst_y = 0, BitmapMaskOption mask = kBitmap_Copy);
179 	void    Blit(Bitmap *src, int src_x, int src_y, int dst_x, int dst_y, int width, int height, BitmapMaskOption mask = kBitmap_Copy);
180 	// Copy other bitmap, stretching or shrinking its size to given values
181 	void    StretchBlt(Bitmap *src, const Rect &dst_rc, BitmapMaskOption mask = kBitmap_Copy);
182 	void    StretchBlt(Bitmap *src, const Rect &src_rc, const Rect &dst_rc, BitmapMaskOption mask = kBitmap_Copy);
183 	// Antia-aliased stretch-blit
184 	void    AAStretchBlt(Bitmap *src, const Rect &dst_rc, BitmapMaskOption mask = kBitmap_Copy);
185 	void    AAStretchBlt(Bitmap *src, const Rect &src_rc, const Rect &dst_rc, BitmapMaskOption mask = kBitmap_Copy);
186 	// TODO: find more general way to call these operations, probably require pointer to Blending data struct?
187 	// Draw bitmap using translucency preset
188 	void    TransBlendBlt(Bitmap *src, int dst_x, int dst_y);
189 	// Draw bitmap using lighting preset
190 	void    LitBlendBlt(Bitmap *src, int dst_x, int dst_y, int light_amount);
191 	// TODO: generic "draw transformed" function? What about mask option?
192 	void    FlipBlt(Bitmap *src, int dst_x, int dst_y, BitmapFlip flip);
193 	void    RotateBlt(Bitmap *src, int dst_x, int dst_y, fixed_t angle);
194 	void    RotateBlt(Bitmap *src, int dst_x, int dst_y, int pivot_x, int pivot_y, fixed_t angle);
195 
196 	//=========================================================================
197 	// Pixel operations
198 	//=========================================================================
199 	// Fills the whole bitmap with given color (black by default)
200 	void    Clear(color_t color = 0);
201 	void    ClearTransparent();
202 	// The PutPixel and GetPixel are supposed to be safe and therefore
203 	// relatively slow operations. They should not be used for changing large
204 	// blocks of bitmap memory - reading/writing from/to scan lines should be
205 	// done in such cases.
206 	void    PutPixel(int x, int y, color_t color);
207 	int     GetPixel(int x, int y) const;
208 
209 	//=========================================================================
210 	// Vector drawing operations
211 	//=========================================================================
212 	void    DrawLine(const Line &ln, color_t color);
213 	void    DrawTriangle(const Triangle &tr, color_t color);
214 	void    DrawRect(const Rect &rc, color_t color);
215 	void    FillRect(const Rect &rc, color_t color);
216 	void    FillCircle(const Circle &circle, color_t color);
217 	// Fills the whole bitmap with given color
218 	void    Fill(color_t color);
219 	void    FillTransparent();
220 	// Floodfills an enclosed area, starting at point
221 	void    FloodFill(int x, int y, color_t color);
222 
223 	//=========================================================================
224 	// Direct access operations
225 	//=========================================================================
226 	// TODO: think how to increase safety over this (some fixed memory buffer class with iterator?)
227 	// Gets scanline for directly writing into it
GetScanLineForWriting(int index)228 	inline unsigned char *GetScanLineForWriting(int index) {
229 		return (index >= 0 && index < GetHeight()) ? _alBitmap->line[index] : nullptr;
230 	}
GetDataForWriting()231 	inline unsigned char *GetDataForWriting() {
232 		return _alBitmap->line[0];
233 	}
234 	// Copies buffer contents into scanline
235 	void    SetScanLine(int index, unsigned char *data, int data_size = -1);
236 
237 private:
238 	BITMAP *_alBitmap;
239 	bool _isDataOwner;
240 };
241 
242 
243 
244 namespace BitmapHelper {
245 // TODO: revise those functions later (currently needed in a few very specific cases)
246 // NOTE: the resulting object __owns__ bitmap data from now on
247 Bitmap *CreateRawBitmapOwner(BITMAP *al_bmp);
248 // NOTE: the resulting object __does not own__ bitmap data
249 Bitmap *CreateRawBitmapWrapper(BITMAP *al_bmp);
250 } // namespace BitmapHelper
251 
252 } // namespace Shared
253 } // namespace AGS
254 } // namespace AGS3
255 
256 #endif
257