X Tutup
Skip to content

Commit 7f054ed

Browse files
committed
Engine: add safety fixups to DynamicSprite.Crop()
1 parent 2020ddd commit 7f054ed

File tree

1 file changed

+35
-19
lines changed

1 file changed

+35
-19
lines changed

Engine/ac/dynamicsprite.cpp

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -126,11 +126,12 @@ int DynamicSprite_GetColorDepth(ScriptDynamicSprite *sds) {
126126
return depth;
127127
}
128128

129-
void DynamicSprite_Resize(ScriptDynamicSprite *sds, int width, int height) {
130-
if ((width < 1) || (height < 1))
131-
quit("!DynamicSprite.Resize: width and height must be greater than zero");
129+
void DynamicSprite_Resize(ScriptDynamicSprite *sds, int width, int height)
130+
{
132131
if (sds->slot == 0)
133132
quit("!DynamicSprite.Resize: sprite has been deleted");
133+
if ((width < 1) || (height < 1))
134+
quit("!DynamicSprite.Resize: width and height must be greater than zero");
134135

135136
data_to_game_coords(&width, &height);
136137

@@ -147,11 +148,12 @@ void DynamicSprite_Resize(ScriptDynamicSprite *sds, int width, int height) {
147148
add_dynamic_sprite(sds->slot, std::move(new_pic), (game.SpriteInfos[sds->slot].Flags & SPF_ALPHACHANNEL) != 0);
148149
}
149150

150-
void DynamicSprite_Flip(ScriptDynamicSprite *sds, int direction) {
151-
if ((direction < 1) || (direction > 3))
152-
quit("!DynamicSprite.Flip: invalid direction");
151+
void DynamicSprite_Flip(ScriptDynamicSprite *sds, int direction)
152+
{
153153
if (sds->slot == 0)
154154
quit("!DynamicSprite.Flip: sprite has been deleted");
155+
if ((direction < 1) || (direction > 3))
156+
quit("!DynamicSprite.Flip: invalid direction");
155157

156158
// resize the sprite to the requested size
157159
Bitmap *sprite = spriteset[sds->slot];
@@ -164,7 +166,8 @@ void DynamicSprite_Flip(ScriptDynamicSprite *sds, int direction) {
164166
add_dynamic_sprite(sds->slot, std::move(new_pic), (game.SpriteInfos[sds->slot].Flags & SPF_ALPHACHANNEL) != 0);
165167
}
166168

167-
void DynamicSprite_CopyTransparencyMask(ScriptDynamicSprite *sds, int sourceSprite) {
169+
void DynamicSprite_CopyTransparencyMask(ScriptDynamicSprite *sds, int sourceSprite)
170+
{
168171
if (sds->slot == 0)
169172
quit("!DynamicSprite.CopyTransparencyMask: sprite has been deleted");
170173

@@ -200,7 +203,7 @@ void DynamicSprite_ChangeCanvasSize(ScriptDynamicSprite *sds, int width, int hei
200203
if (sds->slot == 0)
201204
quit("!DynamicSprite.ChangeCanvasSize: sprite has been deleted");
202205
if ((width < 1) || (height < 1))
203-
quit("!DynamicSprite.ChangeCanvasSize: new size is too small");
206+
quit("!DynamicSprite.ChangeCanvasSize: width and height must be greater than zero");
204207

205208
data_to_game_coords(&x, &y);
206209
data_to_game_coords(&width, &height);
@@ -210,23 +213,31 @@ void DynamicSprite_ChangeCanvasSize(ScriptDynamicSprite *sds, int width, int hei
210213
return; // same canvas size and no offset: no need to do anything
211214

212215
std::unique_ptr<Bitmap> new_pic(BitmapHelper::CreateTransparentBitmap(width, height, sprite->GetColorDepth()));
213-
// blit it into the enlarged image
214216
new_pic->Blit(sprite, 0, 0, x, y, sprite->GetWidth(), sprite->GetHeight());
215217

218+
// replace the bitmap in the sprite set
216219
add_dynamic_sprite(sds->slot, std::move(new_pic), (game.SpriteInfos[sds->slot].Flags & SPF_ALPHACHANNEL) != 0);
217220
}
218221

219-
void DynamicSprite_Crop(ScriptDynamicSprite *sds, int x, int y, int width, int height) {
220-
if ((width < 1) || (height < 1))
221-
quit("!DynamicSprite.Crop: co-ordinates do not make sense");
222+
void DynamicSprite_Crop(ScriptDynamicSprite *sds, int x, int y, int width, int height)
223+
{
222224
if (sds->slot == 0)
223225
quit("!DynamicSprite.Crop: sprite has been deleted");
226+
if ((width < 1) || (height < 1))
227+
quit("!DynamicSprite.Crop: width and height must be greater than zero");
224228

225229
data_to_game_coords(&x, &y);
226230
data_to_game_coords(&width, &height);
227231

228-
if ((width > game.SpriteInfos[sds->slot].Width) || (height > game.SpriteInfos[sds->slot].Height))
229-
quit("!DynamicSprite.Crop: requested to crop an area larger than the source");
232+
// Clamp the cropped size to the valid area of the original image
233+
if ((x < 0) || (y < 0) || (width > game.SpriteInfos[sds->slot].Width - x) || (height > game.SpriteInfos[sds->slot].Height - y))
234+
debug_script_warn("DynamicSprite.Crop: requested to crop to an area outside of the source image: image is %dx%d, crop area %d,%d %dx%d",
235+
game.SpriteInfos[sds->slot].Width, game.SpriteInfos[sds->slot].Height, x, y, width, height);
236+
Math::ClampLength(x, width, 0, game.SpriteInfos[sds->slot].Width);
237+
Math::ClampLength(y, height, 0, game.SpriteInfos[sds->slot].Height);
238+
239+
if (width <= 0 || height <= 0)
240+
return; // cannot crop to zero size
230241

231242
Bitmap *sprite = spriteset[sds->slot];
232243
if (sprite->GetWidth() == width && sprite->GetHeight() == height && x == 0 && y == 0)
@@ -239,20 +250,25 @@ void DynamicSprite_Crop(ScriptDynamicSprite *sds, int x, int y, int width, int h
239250
add_dynamic_sprite(sds->slot, std::move(new_pic), (game.SpriteInfos[sds->slot].Flags & SPF_ALPHACHANNEL) != 0);
240251
}
241252

242-
void DynamicSprite_Rotate(ScriptDynamicSprite *sds, int angle, int width, int height) {
243-
if ((angle < 1) || (angle > 359))
244-
quit("!DynamicSprite.Rotate: invalid angle (must be 1-359)");
253+
void DynamicSprite_Rotate(ScriptDynamicSprite *sds, int angle, int width, int height)
254+
{
245255
if (sds->slot == 0)
246256
quit("!DynamicSprite.Rotate: sprite has been deleted");
257+
if ((angle < 1) || (angle > 359))
258+
quit("!DynamicSprite.Rotate: invalid angle (must be 1-359)");
259+
if ((width != SCR_NO_VALUE) && (width < 1) || (height != SCR_NO_VALUE) && (height < 1))
260+
quit("!DynamicSprite.Rotate: width and height must be greater than zero");
247261

248262
const int src_width = game.SpriteInfos[sds->slot].Width;
249263
const int src_height = game.SpriteInfos[sds->slot].Height;
250-
if ((width == SCR_NO_VALUE) || (height == SCR_NO_VALUE)) {
264+
if ((width == SCR_NO_VALUE) || (height == SCR_NO_VALUE))
265+
{
251266
Size rot_sz = RotateSize(Size(src_width, src_height), angle);
252267
width = rot_sz.Width;
253268
height = rot_sz.Height;
254269
}
255-
else {
270+
else
271+
{
256272
data_to_game_coords(&width, &height);
257273
}
258274

0 commit comments

Comments
 (0)
X Tutup