Files
2026-02-02 04:50:13 +01:00

219 lines
5.5 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/>.
*
*/
/*
* aastr.c --- anti-aliased stretching for Allegro
*
* This file is gift-ware. This file is given to you freely
* as a gift. You may use, modify, redistribute, and generally hack
* it about in any way you like, and you do not have to give anyone
* anything in return.
*
* I do not accept any responsibility for any effects, adverse or
* otherwise, that this code may have on just about anything that
* you can think of. Use it at your own risk.
*
* Copyright (C) 1998, 1999 Michael Bukin
*/
#include "ags/lib/aastr-0.1.1/aastr.h"
#include "ags/lib/aastr-0.1.1/aautil.h"
namespace AGS3 {
/*
* Engine of anti-aliased stretching.
*/
static void _aa_stretch_blit(BITMAP *_src, BITMAP *_dst,
int _sx, int _sy, int _sw, int _sh,
int _dx, int _dy, int _dw, int _dh, int _masked) {
int sx, sy, dx, dy, ydx, ysx;
int xinc, yinc, dsx, dsy;
int xi1, xi2, xdd, yxdd;
int yi1, yi2, ydd;
int dxbeg, dxend, dybeg, dyend;
uint32_t num;
void (*add)(BITMAP * _src, int _sx1, int _sx2, int _sy1, int _sy2, uint32_t _num);
void (*put)(byte * _addr, int _x);
if ((_dw <= 0) || (_dh <= 0) || (_sw <= 0) || (_sh <= 0))
return;
if (_dst->clip) {
dybeg = ((_dy > _dst->ct) ? _dy : _dst->ct);
dyend = (((_dy + _dh) < _dst->cb) ? (_dy + _dh) : _dst->cb);
if (dybeg >= dyend)
return;
dxbeg = ((_dx > _dst->cl) ? _dx : _dst->cl);
dxend = (((_dx + _dw) < _dst->cr) ? (_dx + _dw) : _dst->cr);
if (dxbeg >= dxend)
return;
} else {
dxbeg = _dx;
dybeg = _dy;
dxend = _dx + _dw;
dyend = _dy + _dh;
}
_sx <<= aa_BITS;
_sw <<= aa_BITS;
dsx = _sw / _dw;
if (dsx < (int)aa_SIZE) {
/* Exploding by x. */
_dw--;
_sw -= aa_SIZE;
dsx = aa_SIZE;
}
_sy <<= aa_BITS;
_sh <<= aa_BITS;
dsy = _sh / _dh;
if (dsy < (int)aa_SIZE) {
/* Exploding by y. */
_dh--;
_sh -= aa_SIZE;
dsy = aa_SIZE;
}
num = dsx * dsy;
if (num > aa_MAX_NUM) {
if (dsx > (int)aa_MAX_SIZE)
dsx = aa_MAX_SIZE;
if (dsy > (int)aa_MAX_SIZE)
dsy = aa_MAX_SIZE;
num = dsx * dsy;
}
/* Walk in x direction up to dxbeg and save Bresenham state there.
* Later, it will be used to restart at any line. */
aa_PREPARE(xinc, yxdd, xi1, xi2, _sw, _dw);
for (ydx = _dx, ysx = _sx; ydx < dxbeg; ydx++) {
aa_ADVANCE(ysx, xinc, yxdd, xi1, xi2);
}
/* Color manipulation routines. */
if (is_screen_bitmap(_src))
return;
else {
switch (bitmap_color_depth(_src)) {
case 8:
add = ((_masked != 0) ? _aa_masked_add_rgb8 : _aa_add_rgb8);
break;
#ifdef ALLEGRO_COLOR16
case 15:
add = ((_masked != 0) ? _aa_masked_add_rgb15 : _aa_add_rgb15);
break;
case 16:
add = ((_masked != 0) ? _aa_masked_add_rgb16 : _aa_add_rgb16);
break;
#endif
#ifdef ALLEGRO_COLOR24
case 24:
add = ((_masked != 0) ? _aa_masked_add_rgb24 : _aa_add_rgb24);
_aa_prepare_for_24bpp();
break;
#endif
#ifdef ALLEGRO_COLOR32
case 32:
add = ((_masked != 0) ? _aa_masked_add_rgb32 : _aa_add_rgb32);
break;
#endif
default:
return;
}
}
if (is_planar_bitmap(_dst))
return;
else {
switch (bitmap_color_depth(_dst)) {
case 8:
put = ((_masked != 0) ? _aa_masked_put_rgb8 : _aa_put_rgb8);
break;
#ifdef ALLEGRO_COLOR16
case 15:
put = ((_masked != 0) ? _aa_masked_put_rgb15 : _aa_put_rgb15);
break;
case 16:
put = ((_masked != 0) ? _aa_masked_put_rgb16 : _aa_put_rgb16);
break;
#endif
#ifdef ALLEGRO_COLOR24
case 24:
put = ((_masked != 0) ? _aa_masked_put_rgb24 : _aa_put_rgb24);
_aa_prepare_for_24bpp();
break;
#endif
#ifdef ALLEGRO_COLOR32
case 32:
put = ((_masked != 0) ? _aa_masked_put_rgb32 : _aa_put_rgb32);
break;
#endif
default:
return;
}
}
/* Walk in y until we reach first non-clipped line. */
aa_PREPARE(yinc, ydd, yi1, yi2, _sh, _dh);
for (dy = _dy, sy = _sy; dy < dybeg; dy++) {
aa_ADVANCE(sy, yinc, ydd, yi1, yi2);
}
bmp_select(_dst);
/* Stretch all non-clipped lines. */
for (; dy < dyend; dy++) {
byte *daddr = bmp_write_line(_dst, dy);
for (dx = ydx, sx = ysx, xdd = yxdd; dx < dxend; dx++) {
(*add)(_src, sx, sx + dsx, sy, sy + dsy, num);
(*put)(daddr, dx);
aa_ADVANCE(sx, xinc, xdd, xi1, xi2);
}
aa_ADVANCE(sy, yinc, ydd, yi1, yi2);
}
}
/*
* Anti-aliased bitmap stretching with blit.
*/
void aa_stretch_blit(BITMAP *_src, BITMAP *_dst,
int _sx, int _sy, int _sw, int _sh,
int _dx, int _dy, int _dw, int _dh) {
_aa_stretch_blit(_src, _dst, _sx, _sy, _sw, _sh, _dx, _dy, _dw, _dh, 0);
}
/*
* Anti-aliased bitmap stretching with blit (masked).
*/
void aa_stretch_sprite(BITMAP *_dst, BITMAP *_src, int _dx, int _dy, int _dw, int _dh) {
_aa_stretch_blit(_src, _dst, 0, 0, _src->w, _src->h, _dx, _dy, _dw, _dh, 1);
}
} // namespace AGS3