Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

View File

@@ -0,0 +1,551 @@
/* 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/>.
*
*/
/*
* aarot.c --- anti-aliased rotation 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 rotation.
*/
static void _aa_rotate_bitmap(BITMAP *_src, BITMAP *_dst, int _x, int _y, fixed _angle,
fixed _scalex, fixed _scaley, int _masked) {
int sw, sh, dw, dh;
fixed fx0, fy0, fux, fuy, fvx, fvy;
fixed fdw, fdh, fsinangle, fcosangle;
struct {
int dx, dy;
int sx, sy;
} point[4], *lpoint1, *lpoint2, *rpoint1, *rpoint2;
int ledge[4], redge[4], lindex, rindex;
int xbeg, xend, ybeg, yend;
int sx, sy, dx, dy, dsx, dsy;
int ldx, lsx, lsy, *lsc;
int rdx, rsx, rsy, *rsc;
int ldxinc, ldxdd, ldxi1, ldxi2;
int rdxinc, rdxdd, rdxi1, rdxi2;
int lscinc, lscdd, lsci1, lsci2;
int rscinc, rscdd, rsci1, rsci2;
int sxinc, sxdd, sxi1, sxi2;
int syinc, sydd, syi1, syi2;
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 (_dst->clip) {
xbeg = _dst->cl;
xend = _dst->cr;
ybeg = _dst->ct;
yend = _dst->cb;
} else {
xbeg = 0;
xend = _dst->w;
ybeg = 0;
yend = _dst->h;
}
if ((xbeg >= xend) || (ybeg >= yend))
return;
/* Convert angle to [0, 256) range. */
_angle %= itofix(256);
if (_angle < 0)
_angle += itofix(256);
/* Width and height of source and destination. */
sw = _src->w;
sh = _src->h;
fdw = fixmul(ABS(_scalex), itofix(sw));
fdh = fixmul(ABS(_scaley), itofix(sh));
dw = fixtoi(fdw);
dh = fixtoi(fdh);
if ((dw <= 0) || (dh <= 0))
return;
fdw /= 2;
fdh /= 2;
/* Center of destination. */
fx0 = itofix(_x);
fy0 = itofix(_y);
fsinangle = fixsin(_angle);
fcosangle = fixcos(_angle);
/* Map source (half) edges onto destination. */
fux = fixmul(fdw, fcosangle);
fuy = fixmul(fdw, fsinangle);
fvx = -fixmul(fdh, fsinangle);
fvy = fixmul(fdh, fcosangle);
/* Coordinates of corners in destination. */
point[0].dx = fixtoi(fx0 - fux - fvx);
point[1].dx = fixtoi(fx0 + fux - fvx);
point[2].dx = fixtoi(fx0 - fux + fvx);
point[3].dx = fixtoi(fx0 + fux + fvx);
point[0].dy = fixtoi(fy0 - fuy - fvy);
point[1].dy = fixtoi(fy0 + fuy - fvy);
point[2].dy = fixtoi(fy0 - fuy + fvy);
point[3].dy = fixtoi(fy0 + fuy + fvy);
sw <<= aa_BITS;
dsx = sw / dw;
if (dsx < (int)aa_SIZE)
dsx = aa_SIZE;
sw -= dsx;
sh <<= aa_BITS;
dsy = sh / dh;
if (dsy < (int)aa_SIZE)
dsy = aa_SIZE;
sh -= dsy;
num = dsx * dsy;
/* Avoid overflow. */
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;
}
/* Coordinates of corners in source. */
if (_scalex < 0) {
point[0].sx = sw;
point[1].sx = 0;
point[2].sx = sw;
point[3].sx = 0;
} else {
point[0].sx = 0;
point[1].sx = sw;
point[2].sx = 0;
point[3].sx = sw;
}
if (_scaley < 0) {
point[0].sy = sh;
point[1].sy = sh;
point[2].sy = 0;
point[3].sy = 0;
} else {
point[0].sy = 0;
point[1].sy = 0;
point[2].sy = sh;
point[3].sy = sh;
}
/* Sort left and right edges. */
if ((_angle < itofix(32)) || (_angle >= itofix(128 + 64 + 32))) {
if (point[0].dy < point[1].dy) {
ledge[0] = 0;
ledge[1] = 2;
ledge[2] = 3;
redge[0] = 0;
redge[1] = 1;
redge[2] = 3;
} else if (point[0].dy > point[1].dy) {
ledge[0] = 1;
ledge[1] = 0;
ledge[2] = 2;
redge[0] = 1;
redge[1] = 3;
redge[2] = 2;
} else {
ledge[0] = 0;
ledge[1] = 2;
ledge[2] = 3;
redge[0] = 1;
redge[1] = 3;
redge[2] = 2;
}
} else if (_angle < itofix(64 + 32)) {
if (point[0].dy < point[2].dy) {
ledge[0] = 0;
ledge[1] = 2;
ledge[2] = 3;
redge[0] = 0;
redge[1] = 1;
redge[2] = 3;
} else if (point[0].dy > point[2].dy) {
ledge[0] = 2;
ledge[1] = 3;
ledge[2] = 1;
redge[0] = 2;
redge[1] = 0;
redge[2] = 1;
} else {
ledge[0] = 2;
ledge[1] = 3;
ledge[2] = 1;
redge[0] = 0;
redge[1] = 1;
redge[2] = 3;
}
} else if (_angle < itofix(128 + 32)) {
if (point[2].dy < point[3].dy) {
ledge[0] = 2;
ledge[1] = 3;
ledge[2] = 1;
redge[0] = 2;
redge[1] = 0;
redge[2] = 1;
} else if (point[2].dy > point[3].dy) {
ledge[0] = 3;
ledge[1] = 1;
ledge[2] = 0;
redge[0] = 3;
redge[1] = 2;
redge[2] = 0;
} else {
ledge[0] = 3;
ledge[1] = 1;
ledge[2] = 0;
redge[0] = 2;
redge[1] = 0;
redge[2] = 1;
}
} else {
if (point[1].dy < point[3].dy) {
ledge[0] = 1;
ledge[1] = 0;
ledge[2] = 2;
redge[0] = 1;
redge[1] = 3;
redge[2] = 2;
} else if (point[1].dy > point[3].dy) {
ledge[0] = 3;
ledge[1] = 1;
ledge[2] = 0;
redge[0] = 3;
redge[1] = 2;
redge[2] = 0;
} else {
ledge[0] = 1;
ledge[1] = 0;
ledge[2] = 2;
redge[0] = 3;
redge[1] = 2;
redge[2] = 0;
}
}
/* Remove wrong edges on bottom. */
if (point[ledge[0]].dy == point[ledge[1]].dy) {
ledge[0] = ledge[1];
ledge[1] = ledge[2];
}
if (point[ledge[1]].dy >= point[ledge[2]].dy)
ledge[2] = -1;
ledge[3] = -1;
if (point[redge[0]].dy == point[redge[1]].dy) {
redge[0] = redge[1];
redge[1] = redge[2];
}
if (point[redge[1]].dy >= point[redge[2]].dy)
redge[2] = -1;
redge[3] = -1;
/* Completely clipped by y? */
if ((point[ledge[0]].dy >= yend)
|| ((ledge[2] == -1) && (point[ledge[1]].dy < ybeg))
|| (point[ledge[2]].dy < ybeg))
return;
/* 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;
}
}
lindex = 1;
rindex = 1;
lpoint1 = &point[ledge[0]];
lpoint2 = &point[ledge[1]];
rpoint1 = &point[redge[0]];
rpoint2 = &point[redge[1]];
dy = lpoint1->dy;
if (ledge[2] == -1) {
if (point[ledge[1]].dy < yend)
yend = point[ledge[1]].dy + 1;
} else if (point[ledge[2]].dy < yend)
yend = point[ledge[2]].dy + 1;
ldx = lpoint1->dx;
aa_PREPARE(ldxinc, ldxdd, ldxi1, ldxi2,
lpoint2->dx - lpoint1->dx, lpoint2->dy - lpoint1->dy);
lsx = lpoint1->sx;
lsy = lpoint1->sy;
if (lpoint1->sx != lpoint2->sx) {
lsc = &lsx;
aa_PREPARE(lscinc, lscdd, lsci1, lsci2,
lpoint2->sx - lpoint1->sx, lpoint2->dy - lpoint1->dy);
} else {
lsc = &lsy;
aa_PREPARE(lscinc, lscdd, lsci1, lsci2,
lpoint2->sy - lpoint1->sy, lpoint2->dy - lpoint1->dy);
}
rdx = rpoint1->dx;
aa_PREPARE(rdxinc, rdxdd, rdxi1, rdxi2,
rpoint2->dx - rpoint1->dx, rpoint2->dy - rpoint1->dy);
rsx = rpoint1->sx;
rsy = rpoint1->sy;
if (rpoint1->sx != rpoint2->sx) {
rsc = &rsx;
aa_PREPARE(rscinc, rscdd, rsci1, rsci2,
rpoint2->sx - rpoint1->sx, rpoint2->dy - rpoint1->dy);
} else {
rsc = &rsy;
aa_PREPARE(rscinc, rscdd, rsci1, rsci2,
rpoint2->sy - rpoint1->sy, rpoint2->dy - rpoint1->dy);
}
/* Skip region clipped on top. */
while (dy < ybeg) {
dy++;
if (dy > lpoint2->dy) {
if (ledge[++lindex] == -1)
return;
lpoint1 = lpoint2;
lpoint2 = &point[ledge[lindex]];
if (lpoint1->sx != lpoint2->sx) {
lsc = &lsx;
aa_PREPARE(lscinc, lscdd, lsci1, lsci2,
lpoint2->sx - lpoint1->sx, lpoint2->dy - lpoint1->dy);
} else {
lsc = &lsy;
aa_PREPARE(lscinc, lscdd, lsci1, lsci2,
lpoint2->sy - lpoint1->sy, lpoint2->dy - lpoint1->dy);
}
aa_PREPARE(ldxinc, ldxdd, ldxi1, ldxi2,
lpoint2->dx - lpoint1->dx, lpoint2->dy - lpoint1->dy);
}
aa_ADVANCE(*lsc, lscinc, lscdd, lsci1, lsci2);
aa_ADVANCE(ldx, ldxinc, ldxdd, ldxi1, ldxi2);
if (dy > rpoint2->dy) {
if (redge[++rindex] == -1)
return;
rpoint1 = rpoint2;
rpoint2 = &point[redge[rindex]];
if (rpoint1->sx != rpoint2->sx) {
rsc = &rsx;
aa_PREPARE(rscinc, rscdd, rsci1, rsci2,
rpoint2->sx - rpoint1->sx, rpoint2->dy - rpoint1->dy);
} else {
rsc = &rsy;
aa_PREPARE(rscinc, rscdd, rsci1, rsci2,
rpoint2->sy - rpoint1->sy, rpoint2->dy - rpoint1->dy);
}
aa_PREPARE(rdxinc, rdxdd, rdxi1, rdxi2,
rpoint2->dx - rpoint1->dx, rpoint2->dy - rpoint1->dy);
}
aa_ADVANCE(*rsc, rscinc, rscdd, rsci1, rsci2);
aa_ADVANCE(rdx, rdxinc, rdxdd, rdxi1, rdxi2);
}
bmp_select(_dst);
/* Stretch lines. */
while (dy < yend) {
byte *daddr = bmp_write_line(_dst, dy);
if ((ldx < xend) && (rdx >= xbeg)) {
int curxend;
aa_PREPARE(sxinc, sxdd, sxi1, sxi2,
rsx - lsx, rdx - ldx);
aa_PREPARE(syinc, sydd, syi1, syi2,
rsy - lsy, rdx - ldx);
for (sx = lsx, sy = lsy, dx = ldx; dx < xbeg; dx++) {
aa_ADVANCE(sx, sxinc, sxdd, sxi1, sxi2);
aa_ADVANCE(sy, syinc, sydd, syi1, syi2);
}
curxend = (rdx < xend) ? (rdx + 1) : xend;
for (; dx < curxend; dx++) {
(*add)(_src, sx, sx + dsx, sy, sy + dsy, num);
(*put)(daddr, dx);
aa_ADVANCE(sx, sxinc, sxdd, sxi1, sxi2);
aa_ADVANCE(sy, syinc, sydd, syi1, syi2);
}
}
dy++;
if (dy > lpoint2->dy) {
if (ledge[++lindex] == -1)
return;
lpoint1 = lpoint2;
lpoint2 = &point[ledge[lindex]];
if (lpoint1->sx != lpoint2->sx) {
lsc = &lsx;
aa_PREPARE(lscinc, lscdd, lsci1, lsci2,
lpoint2->sx - lpoint1->sx, lpoint2->dy - lpoint1->dy);
} else {
lsc = &lsy;
aa_PREPARE(lscinc, lscdd, lsci1, lsci2,
lpoint2->sy - lpoint1->sy, lpoint2->dy - lpoint1->dy);
}
aa_PREPARE(ldxinc, ldxdd, ldxi1, ldxi2,
lpoint2->dx - lpoint1->dx, lpoint2->dy - lpoint1->dy);
}
aa_ADVANCE(*lsc, lscinc, lscdd, lsci1, lsci2);
aa_ADVANCE(ldx, ldxinc, ldxdd, ldxi1, ldxi2);
if (dy > rpoint2->dy) {
if (redge[++rindex] == -1)
return;
rpoint1 = rpoint2;
rpoint2 = &point[redge[rindex]];
if (rpoint1->sx != rpoint2->sx) {
rsc = &rsx;
aa_PREPARE(rscinc, rscdd, rsci1, rsci2,
rpoint2->sx - rpoint1->sx, rpoint2->dy - rpoint1->dy);
} else {
rsc = &rsy;
aa_PREPARE(rscinc, rscdd, rsci1, rsci2,
rpoint2->sy - rpoint1->sy, rpoint2->dy - rpoint1->dy);
}
aa_PREPARE(rdxinc, rdxdd, rdxi1, rdxi2,
rpoint2->dx - rpoint1->dx, rpoint2->dy - rpoint1->dy);
}
aa_ADVANCE(*rsc, rscinc, rscdd, rsci1, rsci2);
aa_ADVANCE(rdx, rdxinc, rdxdd, rdxi1, rdxi2);
}
}
/*
* Anti-aliased bitmap rotation with scaling.
*/
void aa_rotate_scaled_bitmap(BITMAP *_src, BITMAP *_dst, int _x, int _y, fixed _angle,
fixed _scalex, fixed _scaley) {
_aa_rotate_bitmap(_src, _dst, _x, _y, _angle, _scalex, _scaley, 0);
}
/*
* Anti-aliased bitmap rotation with scaling (masked).
*/
void aa_rotate_scaled_sprite(BITMAP *_dst, BITMAP *_src, int _x, int _y, fixed _angle,
fixed _scalex, fixed _scaley) {
_aa_rotate_bitmap(_src, _dst, _x, _y, _angle, _scalex, _scaley, 1);
}
/*
* Anti-aliased bitmap rotation.
*/
void aa_rotate_bitmap(BITMAP *_src, BITMAP *_dst, int _x, int _y, fixed _angle) {
_aa_rotate_bitmap(_src, _dst, _x, _y, _angle, itofix(1), itofix(1), 0);
}
/*
* Anti-aliased bitmap rotation (masked).
*/
void aa_rotate_sprite(BITMAP *_dst, BITMAP *_src, int _x, int _y, fixed _angle) {
_aa_rotate_bitmap(_src, _dst, _x, _y, _angle, itofix(1), itofix(1), 1);
}
} // namespace AGS3

View File

@@ -0,0 +1,218 @@
/* 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

View File

@@ -0,0 +1,73 @@
/* 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.h --- anti-aliased stretching and rotation 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
*/
#ifndef AGS_LIB_AASTR_AASTR_H
#define AGS_LIB_AASTR_AASTR_H
#include "ags/lib/allegro.h"
namespace AGS3 {
#ifdef __cplusplus
extern "C" {
#endif
/* Stretching. */
void aa_stretch_blit(BITMAP *src, BITMAP *dst,
int sx, int sy, int sw, int sh,
int dx, int dy, int dw, int dh);
void aa_stretch_sprite(BITMAP *dst, BITMAP *src,
int dx, int dy, int dw, int dh);
/* Rotation. */
void aa_rotate_scaled_bitmap(BITMAP *src, BITMAP *dst,
int x, int y, fixed angle,
fixed scalex, fixed scaley);
void aa_rotate_scaled_sprite(BITMAP *dst, BITMAP *src,
int x, int y, fixed angle,
fixed scalex, fixed scaley);
void aa_rotate_bitmap(BITMAP *src, BITMAP *dst,
int x, int y, fixed angle);
void aa_rotate_sprite(BITMAP *dst, BITMAP *src,
int x, int y, fixed angle);
#ifdef __cplusplus
}
#endif
} // namespace AGS3
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,165 @@
/* 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/>.
*
*/
/*
* aautil.h --- helpers for anti-aliasing routines 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
*/
#ifndef AGS_LIB_AASTR_AAUTIL_H
#define AGS_LIB_AASTR_AAUTIL_H
#include "ags/lib/allegro.h"
namespace AGS3 {
/*
* Change aa_BITS, and never aa_SIZE or aa_MASK.
* 8 or 4 are probably the fastest for i386+.
* Recompile the package after changing aa_BITS.
*/
#ifdef aa_BITS
#undef aa_BITS
#endif
#define aa_BITS 8
#if ((aa_BITS < 0) || (aa_BITS > 12))
#error aa_BITS must be (0 <= aa_BITS <= 12)
#endif
#define aa_SIZE (1UL << aa_BITS)
#define aa_MASK (aa_SIZE - 1)
#define aa_MAX_SIZE (1UL << 12)
#define aa_MAX_NUM (aa_MAX_SIZE * aa_MAX_SIZE)
/* Prepare Bresenham line parameters. */
#define aa_PREPARE(inc,dd,i1,i2,_yw,_xw) \
{ \
int xw = (_xw); \
int yw = (_yw); \
\
if ((xw == 0) || ((yw < xw) && (yw > -xw))) { \
(inc) = 0; \
} \
else { \
(inc) = yw / xw; \
yw %= xw; \
} \
if (yw < 0) { \
(inc) -= 1; \
yw += xw; \
} \
(i2) = ((dd) = ((i1) = 2 * yw) - xw) - xw; \
}
/* Advance to the next point. */
#define aa_ADVANCE(y,inc,dd,i1,i2) \
{ \
if ((dd) >= 0) \
(y) += (inc) + 1, (dd) += (i2); \
else \
(y) += (inc), (dd) += (i1); \
}
#ifdef __cplusplus
extern "C" {
#endif
/* Prepare offsets for direct access to 24bpp bitmap. */
void _aa_prepare_for_24bpp(void);
/* Add r,g,b values from source bitmap. */
void _aa_add_rgb8(BITMAP *_src, int _sx1, int _sx2, int _sy1, int _sy2, uint32_t _num);
#ifdef ALLEGRO_COLOR16
void _aa_add_rgb15(BITMAP *_src, int _sx1, int _sx2, int _sy1, int _sy2, uint32_t _num);
void _aa_add_rgb16(BITMAP *_src, int _sx1, int _sx2, int _sy1, int _sy2, uint32_t _num);
#endif
#ifdef ALLEGRO_COLOR24
void _aa_add_rgb24(BITMAP *_src, int _sx1, int _sx2, int _sy1, int _sy2, uint32_t _num);
#endif
#ifdef ALLEGRO_COLOR32
void _aa_add_rgb32(BITMAP *_src, int _sx1, int _sx2, int _sy1, int _sy2, uint32_t _num);
#endif
/* Put pixel to destination bitmap. */
void _aa_put_rgb8(byte *addr, int _x);
#ifdef ALLEGRO_COLOR16
void _aa_put_rgb15(byte *addr, int _x);
void _aa_put_rgb16(byte *addr, int _x);
#endif
#ifdef ALLEGRO_COLOR24
void _aa_put_rgb24(byte *addr, int _x);
#endif
#ifdef ALLEGRO_COLOR32
void _aa_put_rgb32(byte *addr, int _x);
#endif
/* Add r,g,b and transparency values from source bitmap. */
void _aa_masked_add_rgb8(BITMAP *_src, int _sx1, int _sx2, int _sy1, int _sy2,
uint32_t _num);
#ifdef ALLEGRO_COLOR16
void _aa_masked_add_rgb15(BITMAP *_src, int _sx1, int _sx2, int _sy1, int _sy2,
uint32_t _num);
void _aa_masked_add_rgb16(BITMAP *_src, int _sx1, int _sx2, int _sy1, int _sy2,
uint32_t _num);
#endif
#ifdef ALLEGRO_COLOR24
void _aa_masked_add_rgb24(BITMAP *_src, int _sx1, int _sx2, int _sy1, int _sy2,
uint32_t _num);
#endif
#ifdef ALLEGRO_COLOR32
void _aa_masked_add_rgb32(BITMAP *_src, int _sx1, int _sx2, int _sy1, int _sy2,
uint32_t _num);
#endif
/* Put masked pixel to destination bitmap. */
void _aa_masked_put_rgb8(byte *addr, int _x);
#ifdef ALLEGRO_COLOR16
void _aa_masked_put_rgb15(byte *addr, int _x);
void _aa_masked_put_rgb16(byte *addr, int _x);
#endif
#ifdef ALLEGRO_COLOR24
void _aa_masked_put_rgb24(byte *addr, int _x);
#endif
#ifdef ALLEGRO_COLOR32
void _aa_masked_put_rgb32(byte *addr, int _x);
#endif
#ifdef __cplusplus
}
#endif
} // namespace AGS3
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,128 @@
/* 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/>.
*
*/
#ifndef AGS_LIB_ALFONT_H
#define AGS_LIB_ALFONT_H
#include "ags/lib/allegro/surface.h"
namespace AGS3 {
/* common define */
#define ALFONT_MAJOR_VERSION 1
#define ALFONT_MINOR_VERSION 9
#define ALFONT_SUB_VERSION 1
#define ALFONT_VERSION_STR "1.9.1"
#define ALFONT_DATE_STR "24/11/2002"
#define ALFONT_DATE 20021124 /* yyyymmdd */
/* error codes */
#define ALFONT_OK 0
#define ALFONT_ERROR -1
/* font adjustment flags (AGS compatibility hacks) */
// Force reupdate the font even if the face size matches the request
#define ALFONT_FLG_FORCE_RESIZE 0x01
// Make ascender equal to formal font height
#define ALFONT_FLG_ASCENDER_EQ_HEIGHT 0x02
// When resizing a font, select the first result even if the actual
// pixel height is different from the requested size;
// otherwise will search for the point size which results in pixel
// height closest to the requested size.
#define ALFONT_FLG_SELECT_NOMINAL_SZ 0x04
// Precalculate maximal glyph control box, that is maximal graphical
// extent of any glyph in the font (which may exceed font's height).
// Note that this requires FreeType to load each glyph one by one.
#define ALFONT_FLG_PRECALC_MAX_CBOX 0x08
/* structs */
typedef struct ALFONT_FONT ALFONT_FONT;
/* API */
#define ALFONT_DLL_DECLSPEC
ALFONT_DLL_DECLSPEC const char *alfont_get_name(ALFONT_FONT *f);
ALFONT_DLL_DECLSPEC int alfont_init(void);
ALFONT_DLL_DECLSPEC void alfont_exit(void);
ALFONT_DLL_DECLSPEC ALFONT_FONT *alfont_load_font(const char *filepathname);
ALFONT_DLL_DECLSPEC ALFONT_FONT *alfont_load_font_from_mem(const char *data, int data_len);
ALFONT_DLL_DECLSPEC void alfont_destroy_font(ALFONT_FONT *f);
ALFONT_DLL_DECLSPEC int alfont_set_font_size(ALFONT_FONT *f, int h);
ALFONT_DLL_DECLSPEC int alfont_set_font_size_ex(ALFONT_FONT *f, int h, int flags);
ALFONT_DLL_DECLSPEC int alfont_get_font_height(ALFONT_FONT *f);
/* Returns the real font graphical height */
ALFONT_DLL_DECLSPEC int alfont_get_font_real_height(ALFONT_FONT *f);
/* Returns the real font graphical extent (top, bottom) */
ALFONT_DLL_DECLSPEC void alfont_get_font_real_vextent(ALFONT_FONT *f, int *top, int *bottom);
ALFONT_DLL_DECLSPEC int alfont_text_mode(int mode);
ALFONT_DLL_DECLSPEC void alfont_textout_aa(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color);
ALFONT_DLL_DECLSPEC void alfont_textout(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color);
ALFONT_DLL_DECLSPEC void alfont_textout_aa_ex(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color, int bg);
ALFONT_DLL_DECLSPEC void alfont_textout_ex(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color, int bg);
ALFONT_DLL_DECLSPEC void alfont_textout_centre_aa(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color);
ALFONT_DLL_DECLSPEC void alfont_textout_centre(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color);
ALFONT_DLL_DECLSPEC void alfont_textout_centre_aa_ex(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color, int bg);
ALFONT_DLL_DECLSPEC void alfont_textout_centre_ex(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color, int bg);
ALFONT_DLL_DECLSPEC void alfont_textout_right_aa(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color);
ALFONT_DLL_DECLSPEC void alfont_textout_right(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color);
ALFONT_DLL_DECLSPEC void alfont_textout_right_aa_ex(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color, int bg);
ALFONT_DLL_DECLSPEC void alfont_textout_right_ex(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color, int bg);
ALFONT_DLL_DECLSPEC void alfont_textprintf(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, const char *format, ...);
ALFONT_DLL_DECLSPEC void alfont_textprintf_aa(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, const char *format, ...);
ALFONT_DLL_DECLSPEC void alfont_textprintf_ex(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, int bg, const char *format, ...);
ALFONT_DLL_DECLSPEC void alfont_textprintf_aa_ex(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, int bg, const char *format, ...);
ALFONT_DLL_DECLSPEC void alfont_textprintf_centre(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, const char *format, ...);
ALFONT_DLL_DECLSPEC void alfont_textprintf_centre_aa(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, const char *format, ...);
ALFONT_DLL_DECLSPEC void alfont_textprintf_centre_ex(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, int bg, const char *format, ...);
ALFONT_DLL_DECLSPEC void alfont_textprintf_centre_aa_ex(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, int bg, const char *format, ...);
ALFONT_DLL_DECLSPEC void alfont_textprintf_right(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, const char *format, ...);
ALFONT_DLL_DECLSPEC void alfont_textprintf_right_aa(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, const char *format, ...);
ALFONT_DLL_DECLSPEC void alfont_textprintf_right_ex(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, int bg, const char *format, ...);
ALFONT_DLL_DECLSPEC void alfont_textprintf_right_aa_ex(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, int bg, const char *format, ...);
ALFONT_DLL_DECLSPEC int alfont_text_height(ALFONT_FONT *f);
ALFONT_DLL_DECLSPEC int alfont_text_length(ALFONT_FONT *f, const char *str);
ALFONT_DLL_DECLSPEC int alfont_is_fixed_font(ALFONT_FONT *f);
ALFONT_DLL_DECLSPEC int alfont_is_scalable_font(ALFONT_FONT *f);
ALFONT_DLL_DECLSPEC const int *alfont_get_available_fixed_sizes(ALFONT_FONT *f);
ALFONT_DLL_DECLSPEC int alfont_get_nof_available_fixed_sizes(ALFONT_FONT *f);
ALFONT_DLL_DECLSPEC int alfont_get_char_extra_spacing(ALFONT_FONT *f);
ALFONT_DLL_DECLSPEC void alfont_set_char_extra_spacing(ALFONT_FONT *f, int spacing);
} // namespace AGS3
#endif

50
engines/ags/lib/allegro.h Normal file
View File

@@ -0,0 +1,50 @@
/* 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/>.
*
*/
#ifndef AGS_LIB_ALLEGRO_H
#define AGS_LIB_ALLEGRO_H
#define ALLEGRO_H
#include "ags/lib/allegro/alconfig.h"
#include "ags/lib/allegro/base.h"
#include "ags/lib/allegro/color.h"
#include "ags/lib/allegro/config.h"
#include "ags/lib/allegro/draw.h"
#include "ags/lib/allegro/error.h"
#include "ags/lib/allegro/file.h"
#include "ags/lib/allegro/fixed.h"
#include "ags/lib/allegro/fmaths.h"
#include "ags/lib/allegro/gfx.h"
#include "ags/lib/allegro/system.h"
#include "ags/lib/allegro/unicode.h"
namespace AGS3 {
inline int install_allegro() {
return 0;
}
inline void allegro_exit() {}
} // namespace AGS3
#endif

View File

@@ -0,0 +1,47 @@
/* 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/>.
*
*/
#ifndef AGS_LIB_ALLEGRO_AINTERN_H
#define AGS_LIB_ALLEGRO_AINTERN_H
#include "ags/lib/allegro/base.h"
#include "ags/lib/allegro/color.h"
/* default truecolor pixel format */
#define DEFAULT_RGB_R_SHIFT_15 0
#define DEFAULT_RGB_G_SHIFT_15 5
#define DEFAULT_RGB_B_SHIFT_15 10
#define DEFAULT_RGB_R_SHIFT_16 0
#define DEFAULT_RGB_G_SHIFT_16 5
#define DEFAULT_RGB_B_SHIFT_16 11
#define DEFAULT_RGB_R_SHIFT_24 0
#define DEFAULT_RGB_G_SHIFT_24 8
#define DEFAULT_RGB_B_SHIFT_24 16
#define DEFAULT_RGB_R_SHIFT_32 0
#define DEFAULT_RGB_G_SHIFT_32 8
#define DEFAULT_RGB_B_SHIFT_32 16
#define DEFAULT_RGB_A_SHIFT_32 24
namespace AGS3 {
} // namespace AGS3
#endif

View File

@@ -0,0 +1,83 @@
/* 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/>.
*
*/
#ifndef AGS_LIB_ALLEGRO_ALCONFIG_H
#define AGS_LIB_ALLEGRO_ALCONFIG_H
namespace AGS3 {
/* which color depths to include? */
#define ALLEGRO_COLOR8
#define ALLEGRO_COLOR16
#define ALLEGRO_COLOR24
#define ALLEGRO_COLOR32
#ifndef INLINE
#define INLINE
#endif
#ifndef RET_VOLATILE
#define RET_VOLATILE volatile
#endif
#ifndef ZERO_SIZE_ARRAY
#define ZERO_SIZE_ARRAY(type, name) type name[]
#endif
#ifndef AL_CONST
#define AL_CONST const
#endif
#ifndef AL_VAR
#define AL_VAR(type, name) extern type name
#endif
#ifndef AL_ARRAY
#define AL_ARRAY(type, name) extern type name[]
#endif
#ifndef AL_FUNC
#define AL_FUNC(type, name, args) type name args
#endif
#ifndef AL_PRINTFUNC
#define AL_PRINTFUNC(type, name, args, a, b) AL_FUNC(type, name, args)
#endif
#ifndef AL_METHOD
#define AL_METHOD(type, name, args) type (*name) args
#endif
#ifndef AL_FUNCPTR
#define AL_FUNCPTR(type, name, args) extern type (*name) args
#endif
#ifndef AL_FUNCPTRARRAY
#define AL_FUNCPTRARRAY(type, name, args) extern type (*name[]) args
#endif
#ifndef AL_INLINE
#define AL_INLINE(type, name, args, code) type name args;
#endif
} // namespace AGS3
#endif

View File

@@ -0,0 +1,52 @@
/* 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/>.
*
*/
#ifndef AGS_LIB_ALLEGRO_BASE_H
#define AGS_LIB_ALLEGRO_BASE_H
#include "common/scummsys.h"
#include "common/algorithm.h"
#include "common/endian.h"
#include "ags/lib/allegro/error.h"
namespace AGS3 {
#define ALLEGRO_VERSION 4
#define ALLEGRO_SUB_VERSION 4
#define ALLEGRO_WIP_VERSION 2
#define ALLEGRO_VERSION_STR "4.4.2"
#define ALLEGRO_DATE_STR "2011"
#define ALLEGRO_DATE 20110519 /* yyyymmdd */
/* Returns the median of x, y, z */
#define MID(x,y,z) ((x) > (y) ? ((y) > (z) ? (y) : ((x) > (z) ? \
(z) : (x))) : ((y) > (z) ? ((z) > (x) ? (z) : \
(x)): (y)))
#define AL_ID MKTAG
#define AL_FUNC(type, name, args) type name args
#define SCUMMVM_ID MKTAG('S', 'C', 'V', 'M')
} // namespace AGS3
#endif

View File

@@ -0,0 +1,974 @@
/* 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/>.
*
*/
#include "ags/lib/allegro/color.h"
#include "ags/lib/allegro/system.h"
#include "ags/lib/allegro/aintern.h"
#include "ags/shared/core/types.h"
#include "ags/shared/util/stream.h"
#include "ags/globals.h"
#include "common/textconsole.h"
#include "common/system.h"
#include "graphics/paletteman.h"
namespace AGS3 {
#define VGA_COLOR_TRANS(x) ((x) * 255 / 63)
void color::readFromFile(AGS::Shared::Stream *file) {
r = file->ReadByte();
g = file->ReadByte();
b = file->ReadByte();
filler = file->ReadByte();
}
void color::writeToFile(AGS::Shared::Stream *file) const {
file->WriteByte(r);
file->WriteByte(g);
file->WriteByte(b);
file->WriteByte(filler);
}
static void convertPalette(const PALETTE src, byte dest[Graphics::PALETTE_SIZE]) {
const color *cSrc = (const color *)src;
for (int i = 0; i < Graphics::PALETTE_COUNT; ++i, cSrc++, dest += 3) {
dest[0] = VGA_COLOR_TRANS(cSrc->r);
dest[1] = VGA_COLOR_TRANS(cSrc->g);
dest[2] = VGA_COLOR_TRANS(cSrc->b);
}
}
static void applyPalette() {
if (g_system->getScreenFormat().bytesPerPixel == 1) {
byte pal[Graphics::PALETTE_SIZE];
convertPalette(_G(current_palette), pal);
g_system->getPaletteManager()->setPalette(pal, 0, Graphics::PALETTE_COUNT);
}
}
void set_palette(const PALETTE p) {
for (int idx = 0; idx < PAL_SIZE; ++idx)
_G(current_palette)[idx] = p[idx];
applyPalette();
}
void set_palette_range(const PALETTE p, int from, int to, int retracesync) {
for (int i = from; i <= to; ++i) {
_G(current_palette)[i] = p[i];
}
applyPalette();
}
int makecol15(int r, int g, int b) {
return (((r >> 3) << _G(_rgb_r_shift_15)) |
((g >> 3) << _G(_rgb_g_shift_15)) |
((b >> 3) << _G(_rgb_b_shift_15)));
}
int makecol16(int r, int g, int b) {
return (((r >> 3) << _G(_rgb_r_shift_16)) |
((g >> 2) << _G(_rgb_g_shift_16)) |
((b >> 3) << _G(_rgb_b_shift_16)));
}
int makecol24(int r, int g, int b) {
return ((r << _G(_rgb_r_shift_24)) |
(g << _G(_rgb_g_shift_24)) |
(b << _G(_rgb_b_shift_24)));
}
int makecol32(int r, int g, int b) {
return ((r << _G(_rgb_r_shift_32)) |
(g << _G(_rgb_g_shift_32)) |
(b << _G(_rgb_b_shift_32)));
}
int makeacol32(int r, int g, int b, int a) {
return ((r << _G(_rgb_r_shift_32)) |
(g << _G(_rgb_g_shift_32)) |
(b << _G(_rgb_b_shift_32)) |
(a << _G(_rgb_a_shift_32)));
}
int getr8(int c) {
return (int)_G(current_palette)[c].r;
}
int getg8(int c) {
return (int)_G(current_palette)[c].g;
}
int getb8(int c) {
return (int)_G(current_palette)[c].b;
}
int getr15(int c) {
return _rgb_scale_5[(c >> _G(_rgb_r_shift_15)) & 0x1F];
}
int getg15(int c) {
return _rgb_scale_5[(c >> _G(_rgb_g_shift_15)) & 0x1F];
}
int getb15(int c) {
return _rgb_scale_5[(c >> _G(_rgb_b_shift_15)) & 0x1F];
}
int getr16(int c) {
return _rgb_scale_5[(c >> _G(_rgb_r_shift_16)) & 0x1F];
}
int getg16(int c) {
return _rgb_scale_6[(c >> _G(_rgb_g_shift_16)) & 0x3F];
}
int getb16(int c) {
return _rgb_scale_5[(c >> _G(_rgb_b_shift_16)) & 0x1F];
}
int getr24(int c) {
return ((c >> _G(_rgb_r_shift_24)) & 0xFF);
}
int getg24(int c) {
return ((c >> _G(_rgb_g_shift_24)) & 0xFF);
}
int getb24(int c) {
return ((c >> _G(_rgb_b_shift_24)) & 0xFF);
}
int getr32(int c) {
return ((c >> _G(_rgb_r_shift_32)) & 0xFF);
}
int getg32(int c) {
return ((c >> _G(_rgb_g_shift_32)) & 0xFF);
}
int getb32(int c) {
return ((c >> _G(_rgb_b_shift_32)) & 0xFF);
}
int geta32(int c) {
return ((c >> _G(_rgb_a_shift_32)) & 0xFF);
}
int makecol(byte r, byte g, byte b) {
return (b) | (g << 8) | (r << 16);
}
int makecol8(byte r, byte g, byte b) {
return (b) | (g << 8) | (r << 16);
}
void get_color(int idx, RGB *p) {
*p = _G(current_palette)[idx];
}
void get_palette_range(PALETTE p, int from, int to) {
Common::copy(&_G(current_palette)[from], &_G(current_palette)[to + 1], &p[from]);
}
void get_palette(PALETTE p) {
get_palette_range(p, 0, PAL_SIZE - 1);
}
void fade_interpolate(AL_CONST PALETTE source, AL_CONST PALETTE dest, PALETTE output, int pos, int from, int to) {
assert(pos >= 0 && pos <= 64);
assert(from >= 0 && from < PAL_SIZE);
assert(to >= 0 && to < PAL_SIZE);
for (int c = from; c <= to; c++) {
output[c].r = ((int)source[c].r * (63 - pos) + (int)dest[c].r * pos) / 64;
output[c].g = ((int)source[c].g * (63 - pos) + (int)dest[c].g * pos) / 64;
output[c].b = ((int)source[c].b * (63 - pos) + (int)dest[c].b * pos) / 64;
}
}
void select_palette(AL_CONST PALETTE p) {
int c;
for (c = 0; c < PAL_SIZE; c++) {
_G(prev_current_palette)[c] = _G(current_palette)[c];
_G(current_palette)[c] = p[c];
}
applyPalette();
}
void unselect_palette(void) {
int c;
for (c = 0; c < PAL_SIZE; c++)
_G(current_palette)[c] = _G(prev_current_palette)[c];
applyPalette();
}
void set_blender_mode(BlenderMode m, int r, int g, int b, int a) {
_G(_blender_mode) = m;
_G(trans_blend_alpha) = a;
_G(trans_blend_red) = r;
_G(trans_blend_green) = g;
_G(trans_blend_blue) = b;
}
void set_alpha_blender(void) {
set_blender_mode(kSourceAlphaBlender, 0, 0, 0, 0);
}
void set_trans_blender(int r, int g, int b, int a) {
set_blender_mode(kRgbToRgbBlender, r, g, b, a);
}
/* makecol_depth:
* Converts R, G, and B values (ranging 0-255) to whatever pixel format
* is required by the specified color depth.
*/
int makecol_depth(int color_depth, int r, int g, int b) {
switch (color_depth) {
case 8:
return makecol8(r, g, b);
case 15:
return makecol15(r, g, b);
case 16:
return makecol16(r, g, b);
case 24:
return makecol24(r, g, b);
case 32:
return makecol32(r, g, b);
}
return 0;
}
/* makeacol_depth:
* Converts R, G, B, and A values (ranging 0-255) to whatever pixel format
* is required by the specified color depth.
*/
int makeacol_depth(int color_depth, int r, int g, int b, int a) {
switch (color_depth) {
case 8:
return makecol8(r, g, b);
case 15:
return makecol15(r, g, b);
case 16:
return makecol16(r, g, b);
case 24:
return makecol24(r, g, b);
case 32:
return makeacol32(r, g, b, a);
}
return 0;
}
/* getr_depth:
* Extracts the red component (ranging 0-255) from a pixel in the format
* being used by the specified color depth.
*/
int getr_depth(int color_depth, int c) {
switch (color_depth) {
case 8:
return getr8(c);
case 15:
return getr15(c);
case 16:
return getr16(c);
case 24:
return getr24(c);
case 32:
return getr32(c);
}
return 0;
}
/* getg_depth:
* Extracts the green component (ranging 0-255) from a pixel in the format
* being used by the specified color depth.
*/
int getg_depth(int color_depth, int c) {
switch (color_depth) {
case 8:
return getg8(c);
case 15:
return getg15(c);
case 16:
return getg16(c);
case 24:
return getg24(c);
case 32:
return getg32(c);
}
return 0;
}
/* getb_depth:
* Extracts the blue component (ranging 0-255) from a pixel in the format
* being used by the specified color depth.
*/
int getb_depth(int color_depth, int c) {
switch (color_depth) {
case 8:
return getb8(c);
case 15:
return getb15(c);
case 16:
return getb16(c);
case 24:
return getb24(c);
case 32:
return getb32(c);
}
return 0;
}
/* geta_depth:
* Extracts the alpha component (ranging 0-255) from a pixel in the format
* being used by the specified color depth.
*/
int geta_depth(int color_depth, int c) {
if (color_depth == 32)
return geta32(c);
return 0;
}
/* getr:
* Extracts the red component (ranging 0-255) from a pixel in the format
* being used by the current video mode.
*/
int getr(int c) {
return getr_depth(_G(_color_depth), c);
}
/* getg:
* Extracts the green component (ranging 0-255) from a pixel in the format
* being used by the current video mode.
*/
int getg(int c) {
return getg_depth(_G(_color_depth), c);
}
/* getb:
* Extracts the blue component (ranging 0-255) from a pixel in the format
* being used by the current video mode.
*/
int getb(int c) {
return getb_depth(_G(_color_depth), c);
}
/* geta:
* Extracts the alpha component (ranging 0-255) from a pixel in the format
* being used by the current video mode.
*/
int geta(int c) {
return geta_depth(_G(_color_depth), c);
}
/* 1.5k lookup table for color matching */
static unsigned int col_diff[3 * 128];
/* bestfit_init:
* Color matching is done with weighted squares, which are much faster
* if we pregenerate a little lookup table...
*/
static void bestfit_init(void) {
int i;
for (i = 1; i < 64; i++) {
int k = i * i;
col_diff[0 + i] = col_diff[0 + 128 - i] = k * (59 * 59);
col_diff[128 + i] = col_diff[128 + 128 - i] = k * (30 * 30);
col_diff[256 + i] = col_diff[256 + 128 - i] = k * (11 * 11);
}
}
/* bestfit_color:
* Searches a palette for the color closest to the requested R, G, B value.
*/
int bestfit_color(AL_CONST PALETTE pal, int r, int g, int b) {
int i, coldiff, lowest, bestfit;
assert(r >= 0 && r <= 63);
assert(g >= 0 && g <= 63);
assert(b >= 0 && b <= 63);
if (col_diff[1] == 0)
bestfit_init();
bestfit = 0;
lowest = INT_MAX;
/* only the transparent (pink) color can be mapped to index 0 */
if ((r == 63) && (g == 0) && (b == 63))
i = 0;
else
i = 1;
while (i < PAL_SIZE) {
AL_CONST RGB *rgb = &pal[i];
coldiff = (col_diff + 0)[(rgb->g - g) & 0x7F];
if (coldiff < lowest) {
coldiff += (col_diff + 128)[(rgb->r - r) & 0x7F];
if (coldiff < lowest) {
coldiff += (col_diff + 256)[(rgb->b - b) & 0x7F];
if (coldiff < lowest) {
bestfit = rgb - pal; /* faster than `bestfit = i;' */
if (coldiff == 0)
return bestfit;
lowest = coldiff;
}
}
}
i++;
}
return bestfit;
}
/* makecol8:
* Converts R, G, and B values (ranging 0-255) to an 8 bit paletted color.
* If the global _G(rgb_map) table is initialised, it uses that, otherwise
* it searches through the current palette to find the best match.
*/
int makecol8(int r, int g, int b) {
if (_G(rgb_map))
return _G(rgb_map)->data[r >> 3][g >> 3][b >> 3];
else
return bestfit_color(_G(current_palette), r >> 2, g >> 2, b >> 2);
}
/* hsv_to_rgb:
* Converts from HSV colorspace to RGB values.
*/
void hsv_to_rgb(float h, float s, float v, int *r, int *g, int *b) {
float f, x, y, z;
int i;
assert(s >= 0 && s <= 1);
assert(v >= 0 && v <= 1);
v *= 255.0f;
if (s == 0.0f) { /* ok since we don't divide by s, and faster */
*r = *g = *b = v + 0.5f;
} else {
h = fmod(h, 360.0f) / 60.0f;
if (h < 0.0f)
h += 6.0f;
i = (int)h;
f = h - i;
x = v * s;
y = x * f;
v += 0.5f; /* round to the nearest integer below */
z = v - x;
switch (i) {
case 6:
case 0:
*r = v;
*g = z + y;
*b = z;
break;
case 1:
*r = v - y;
*g = v;
*b = z;
break;
case 2:
*r = z;
*g = v;
*b = z + y;
break;
case 3:
*r = z;
*g = v - y;
*b = v;
break;
case 4:
*r = z + y;
*g = z;
*b = v;
break;
case 5:
*r = v;
*g = z;
*b = v - y;
break;
}
}
}
/* rgb_to_hsv:
* Converts an RGB value into the HSV colorspace.
*/
void rgb_to_hsv(int r, int g, int b, float *h, float *s, float *v) {
int delta;
assert(r >= 0 && r <= 255);
assert(g >= 0 && g <= 255);
assert(b >= 0 && b <= 255);
if (r > g) {
if (b > r) {
/* b>r>g */
delta = b - g;
*h = 240.0f + ((r - g) * 60) / (float)delta;
*s = (float)delta / (float)b;
*v = (float)b * (1.0f / 255.0f);
} else {
/* r>g and r>b */
delta = r - MIN(g, b);
*h = ((g - b) * 60) / (float)delta;
if (*h < 0.0f)
*h += 360.0f;
*s = (float)delta / (float)r;
*v = (float)r * (1.0f / 255.0f);
}
} else {
if (b > g) {
/* b>g>=r */
delta = b - r;
*h = 240.0f + ((r - g) * 60) / (float)delta;
*s = (float)delta / (float)b;
*v = (float)b * (1.0f / 255.0f);
} else {
/* g>=b and g>=r */
delta = g - MIN(r, b);
if (delta == 0) {
*h = 0.0f;
if (g == 0)
*s = *v = 0.0f;
else {
*s = (float)delta / (float)g;
*v = (float)g * (1.0f / 255.0f);
}
} else {
*h = 120.0f + ((b - r) * 60) / (float)delta;
*s = (float)delta / (float)g;
*v = (float)g * (1.0f / 255.0f);
}
}
}
}
/* create_rgb_table:
* Fills an RGB_MAP lookup table with conversion data for the specified
* palette. This is the faster version by Jan Hubicka.
*
* Uses alg. similar to floodfill - it adds one seed per every color in
* palette to its best position. Then areas around seed are filled by
* same color because it is best approximation for them, and then areas
* about them etc...
*
* It does just about 80000 tests for distances and this is about 100
* times better than normal 256*32000 tests so the calculation time
* is now less than one second at all computers I tested.
*/
void create_rgb_table(RGB_MAP *table, AL_CONST PALETTE pal, void (*callback)(int pos)) {
#define UNUSED 65535
#define LAST 65532
/* macro add adds to single linked list */
#define add(i) (next[(i)] == UNUSED ? (next[(i)] = LAST, \
(first != LAST ? (next[last] = (i)) : (first = (i))), \
(last = (i))) : 0)
/* same but w/o checking for first element */
#define add1(i) (next[(i)] == UNUSED ? (next[(i)] = LAST, \
next[last] = (i), \
(last = (i))) : 0)
/* calculates distance between two colors */
#define dist(a1, a2, a3, b1, b2, b3) \
(col_diff[ ((a2) - (b2)) & 0x7F] + \
(col_diff + 128)[((a1) - (b1)) & 0x7F] + \
(col_diff + 256)[((a3) - (b3)) & 0x7F])
/* converts r,g,b to position in array and back */
#define pos(r, g, b) \
(((r) / 2) * 32 * 32 + ((g) / 2) * 32 + ((b) / 2))
#define depos(pal, r, g, b) \
((b) = ((pal) & 31) * 2, \
(g) = (((pal) >> 5) & 31) * 2, \
(r) = (((pal) >> 10) & 31) * 2)
/* is current color better than pal1? */
#define better(r1, g1, b1, pal1) \
(((int)dist((r1), (g1), (b1), \
(pal1).r, (pal1).g, (pal1).b)) > (int)dist2)
/* checking of position */
#define dopos(rp, gp, bp, ts) \
if ((rp > -1 || r > 0) && (rp < 1 || r < 61) && \
(gp > -1 || g > 0) && (gp < 1 || g < 61) && \
(bp > -1 || b > 0) && (bp < 1 || b < 61)) { \
i = first + rp * 32 * 32 + gp * 32 + bp; \
if (!data[i]) { \
data[i] = val; \
add1(i); \
} \
else if ((ts) && (data[i] != val)) { \
dist2 = (rp ? (col_diff+128)[(r+2*rp-pal[val].r) & 0x7F] : r2) + \
(gp ? (col_diff )[(g+2*gp-pal[val].g) & 0x7F] : g2) + \
(bp ? (col_diff+256)[(b+2*bp-pal[val].b) & 0x7F] : b2); \
if (better((r+2*rp), (g+2*gp), (b+2*bp), pal[data[i]])) { \
data[i] = val; \
add1(i); \
} \
} \
}
int i, curr, r, g, b, val, dist2;
unsigned int r2, g2, b2;
unsigned short next[32 * 32 * 32];
unsigned char *data;
int first = LAST;
int last = LAST;
int count = 0;
int cbcount = 0;
#define AVERAGE_COUNT 18000
if (col_diff[1] == 0)
bestfit_init();
memset(next, 255, sizeof(next));
memset(table->data, 0, sizeof(char) * 32 * 32 * 32);
data = (unsigned char *)table->data;
/* add starting seeds for floodfill */
for (i = 1; i < PAL_SIZE; i++) {
curr = pos(pal[i].r, pal[i].g, pal[i].b);
if (next[curr] == UNUSED) {
data[curr] = i;
add(curr);
}
}
/* main floodfill: two versions of loop for faster growing in blue axis */
while (first != LAST) {
depos(first, r, g, b);
/* calculate distance of current color */
val = data[first];
r2 = (col_diff + 128)[((pal[val].r) - (r)) & 0x7F];
g2 = (col_diff)[((pal[val].g) - (g)) & 0x7F];
b2 = (col_diff + 256)[((pal[val].b) - (b)) & 0x7F];
/* try to grow to all directions */
dopos(0, 0, 1, 1);
dopos(0, 0, -1, 1);
dopos(1, 0, 0, 1);
dopos(-1, 0, 0, 1);
dopos(0, 1, 0, 1);
dopos(0, -1, 0, 1);
/* faster growing of blue direction */
if ((b > 0) && (data[first - 1] == val)) {
b -= 2;
first--;
b2 = (col_diff + 256)[((pal[val].b) - (b)) & 0x7F];
dopos(-1, 0, 0, 0);
dopos(1, 0, 0, 0);
dopos(0, -1, 0, 0);
dopos(0, 1, 0, 0);
first++;
}
/* get next from list */
i = first;
first = next[first];
next[i] = UNUSED;
/* second version of loop */
if (first != LAST) {
depos(first, r, g, b);
val = data[first];
r2 = (col_diff + 128)[((pal[val].r) - (r)) & 0x7F];
g2 = (col_diff)[((pal[val].g) - (g)) & 0x7F];
b2 = (col_diff + 256)[((pal[val].b) - (b)) & 0x7F];
dopos(0, 0, 1, 1);
dopos(0, 0, -1, 1);
dopos(1, 0, 0, 1);
dopos(-1, 0, 0, 1);
dopos(0, 1, 0, 1);
dopos(0, -1, 0, 1);
if ((b < 61) && (data[first + 1] == val)) {
b += 2;
first++;
b2 = (col_diff + 256)[((pal[val].b) - (b)) & 0x7f];
dopos(-1, 0, 0, 0);
dopos(1, 0, 0, 0);
dopos(0, -1, 0, 0);
dopos(0, 1, 0, 0);
first--;
}
i = first;
first = next[first];
next[i] = UNUSED;
}
count++;
if (count == (cbcount + 1) * AVERAGE_COUNT / 256) {
if (cbcount < 256) {
if (callback)
callback(cbcount);
cbcount++;
}
}
}
/* only the transparent (pink) color can be mapped to index 0 */
if ((pal[0].r == 63) && (pal[0].g == 0) && (pal[0].b == 63))
table->data[31][0][31] = 0;
if (callback)
while (cbcount < 256)
callback(cbcount++);
}
/* create_light_table:
* Constructs a lighting color table for the specified palette. At light
* intensity 255 the table will produce the palette colors directly, and
* at level 0 it will produce the specified R, G, B value for all colors
* (this is specified in 0-63 VGA format). If the callback function is
* not NULL, it will be called 256 times during the calculation, allowing
* you to display a progress indicator.
*/
void create_light_table(COLOR_MAP *table, AL_CONST PALETTE pal, int r, int g, int b, void (*callback)(int pos)) {
int r1, g1, b1, r2, g2, b2, x, y;
unsigned int t1, t2;
assert(table);
assert(r >= 0 && r <= 63);
assert(g >= 0 && g <= 63);
assert(b >= 0 && b <= 63);
if (_G(rgb_map)) {
for (x = 0; x < PAL_SIZE - 1; x++) {
t1 = x * 0x010101;
t2 = 0xFFFFFF - t1;
r1 = (1 << 24) + r * t2;
g1 = (1 << 24) + g * t2;
b1 = (1 << 24) + b * t2;
for (y = 0; y < PAL_SIZE; y++) {
r2 = (r1 + pal[y].r * t1) >> 25;
g2 = (g1 + pal[y].g * t1) >> 25;
b2 = (b1 + pal[y].b * t1) >> 25;
table->data[x][y] = _G(rgb_map)->data[r2][g2][b2];
}
}
if (callback)
(*callback)(x);
} else {
for (x = 0; x < PAL_SIZE - 1; x++) {
t1 = x * 0x010101;
t2 = 0xFFFFFF - t1;
r1 = (1 << 23) + r * t2;
g1 = (1 << 23) + g * t2;
b1 = (1 << 23) + b * t2;
for (y = 0; y < PAL_SIZE; y++) {
r2 = (r1 + pal[y].r * t1) >> 24;
g2 = (g1 + pal[y].g * t1) >> 24;
b2 = (b1 + pal[y].b * t1) >> 24;
table->data[x][y] = bestfit_color(pal, r2, g2, b2);
}
}
if (callback)
(*callback)(x);
}
for (y = 0; y < PAL_SIZE; y++)
table->data[255][y] = y;
}
/* create_trans_table:
* Constructs a translucency color table for the specified palette. The
* r, g, and b parameters specifiy the solidity of each color component,
* ranging from 0 (totally transparent) to 255 (totally solid). Source
* color #0 is a special case, and is set to leave the destination
* unchanged, so that masked sprites will draw correctly. If the callback
* function is not NULL, it will be called 256 times during the calculation,
* allowing you to display a progress indicator.
*/
void create_trans_table(COLOR_MAP *table, AL_CONST PALETTE pal, int r, int g, int b, void (*callback)(int pos)) {
int tmp[768], *q;
int x, y, i, j, k;
unsigned char *p;
int tr, tg, tb;
int add;
assert(table);
assert(r >= 0 && r <= 255);
assert(g >= 0 && g <= 255);
assert(b >= 0 && b <= 255);
/* This is a bit ugly, but accounts for the solidity parameters
being in the range 0-255 rather than 0-256. Given that the
precision of r,g,b components is only 6 bits it shouldn't do any
harm. */
if (r > 128)
r++;
if (g > 128)
g++;
if (b > 128)
b++;
if (_G(rgb_map))
add = 255;
else
add = 127;
for (x = 0; x < 256; x++) {
tmp[x * 3] = pal[x].r * (256 - r) + add;
tmp[x * 3 + 1] = pal[x].g * (256 - g) + add;
tmp[x * 3 + 2] = pal[x].b * (256 - b) + add;
}
for (x = 1; x < PAL_SIZE; x++) {
i = pal[x].r * r;
j = pal[x].g * g;
k = pal[x].b * b;
p = table->data[x];
q = tmp;
if (_G(rgb_map)) {
for (y = 0; y < PAL_SIZE; y++) {
tr = (i + * (q++)) >> 9;
tg = (j + * (q++)) >> 9;
tb = (k + * (q++)) >> 9;
p[y] = _G(rgb_map)->data[tr][tg][tb];
}
} else {
for (y = 0; y < PAL_SIZE; y++) {
tr = (i + * (q++)) >> 8;
tg = (j + * (q++)) >> 8;
tb = (k + * (q++)) >> 8;
p[y] = bestfit_color(pal, tr, tg, tb);
}
}
if (callback)
(*callback)(x - 1);
}
for (y = 0; y < PAL_SIZE; y++) {
table->data[0][y] = y;
table->data[y][y] = y;
}
if (callback)
(*callback)(255);
}
} // namespace AGS3

View File

@@ -0,0 +1,155 @@
/* 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/>.
*
*/
#ifndef AGS_LIB_ALLEGRO_COLOR_H
#define AGS_LIB_ALLEGRO_COLOR_H
#include "common/scummsys.h"
#include "graphics/screen.h"
#include "ags/lib/allegro/base.h"
#include "ags/lib/allegro/alconfig.h"
namespace AGS3 {
#define PAL_SIZE 256
#define MASK_COLOR_8 0
#define MASK_COLOR_15 0x7C1F
#define MASK_COLOR_16 0xF81F
#define MASK_COLOR_24 0xFF00FF
#define MASK_COLOR_32 0xFF00FF
class BITMAP;
namespace AGS {
namespace Shared {
class Stream;
} // namespace Shared
} // namespace AGS
#include "common/pack-start.h" // START STRUCT PACKING
struct color {
byte r, g, b;
byte filler;
void readFromFile(AGS::Shared::Stream *file);
void writeToFile(AGS::Shared::Stream *file) const;
void clear() {
r = g = b = filler = 0;
}
} PACKED_STRUCT;
typedef color RGB;
typedef RGB PALETTE[PAL_SIZE];
#include "common/pack-end.h" // END STRUCT PACKING
struct RGB_MAP {
byte data[32][32][32];
};
struct COLOR_MAP {
byte data[PAL_SIZE][PAL_SIZE];
};
enum BlenderMode {
kSourceAlphaBlender,
kArgbToArgbBlender,
kArgbToRgbBlender,
kRgbToArgbBlender,
kRgbToRgbBlender,
kAlphaPreservedBlenderMode,
kOpaqueBlenderMode,
kAdditiveBlenderMode,
kTintBlenderMode,
kTintLightBlenderMode
};
extern int makecol(byte r, byte g, byte b);
AL_ARRAY(const int, _rgb_scale_5);
AL_ARRAY(const int, _rgb_scale_6);
AL_FUNC(void, set_palette, (AL_CONST PALETTE p));
AL_FUNC(void, set_palette_range, (AL_CONST PALETTE p, int from, int to, int retracesync));
AL_FUNC(void, get_color, (int idx, RGB *p));
AL_FUNC(void, get_palette, (PALETTE p));
AL_FUNC(void, get_palette_range, (PALETTE p, int from, int to));
AL_FUNC(void, fade_interpolate, (AL_CONST PALETTE source, AL_CONST PALETTE dest, PALETTE output, int pos, int from, int to));
AL_FUNC(void, select_palette, (AL_CONST PALETTE p));
AL_FUNC(void, unselect_palette, (void));
AL_FUNC(void, create_rgb_table, (RGB_MAP *table, AL_CONST PALETTE pal, AL_METHOD(void, callback, (int pos))));
AL_FUNC(void, create_light_table, (COLOR_MAP *table, AL_CONST PALETTE pal, int r, int g, int b, AL_METHOD(void, callback, (int pos))));
AL_FUNC(void, create_trans_table, (COLOR_MAP *table, AL_CONST PALETTE pal, int r, int g, int b, AL_METHOD(void, callback, (int pos))));
AL_FUNC(void, set_blender_mode, (BlenderMode, int r, int g, int b, int a));
AL_FUNC(void, set_alpha_blender, (void));
AL_FUNC(void, set_trans_blender, (int r, int g, int b, int a));
AL_FUNC(void, hsv_to_rgb, (float h, float s, float v, int *r, int *g, int *b));
AL_FUNC(void, rgb_to_hsv, (int r, int g, int b, float *h, float *s, float *v));
AL_FUNC(int, bestfit_color, (AL_CONST PALETTE pal, int r, int g, int b));
AL_FUNC(int, makecol8, (int r, int g, int b));
AL_FUNC(int, makecol_depth, (int color_depth, int r, int g, int b));
AL_FUNC(int, makeacol_depth, (int color_depth, int r, int g, int b, int a));
AL_FUNC(int, getr, (int c));
AL_FUNC(int, getg, (int c));
AL_FUNC(int, getb, (int c));
AL_FUNC(int, geta, (int c));
AL_FUNC(int, getr_depth, (int color_depth, int c));
AL_FUNC(int, getg_depth, (int color_depth, int c));
AL_FUNC(int, getb_depth, (int color_depth, int c));
AL_FUNC(int, geta_depth, (int color_depth, int c));
extern int makecol15(int r, int g, int b);
extern int makecol16(int r, int g, int b);
extern int makecol24(int r, int g, int b);
extern int makecol32(int r, int g, int b);
extern int makeacol32(int r, int g, int b, int a);
extern int getr8(int c);
extern int getg8(int c);
extern int getb8(int c);
extern int getr15(int c);
extern int getg15(int c);
extern int getb15(int c);
extern int getr16(int c);
extern int getg16(int c);
extern int getb16(int c);
extern int getr24(int c);
extern int getg24(int c);
extern int getb24(int c);
extern int getr32(int c);
extern int getg32(int c);
extern int getb32(int c);
extern int geta32(int c);
} // namespace AGS3
#endif

View File

@@ -0,0 +1,31 @@
/* 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/>.
*
*/
#include "ags/lib/allegro/config.h"
#include "common/textconsole.h"
namespace AGS3 {
void override_config_data(const char *data, int length) {
// No implementation
}
} // namespace AGS3

View File

@@ -0,0 +1,31 @@
/* 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/>.
*
*/
#ifndef AGS_LIB_ALLEGRO_CONFIG_H
#define AGS_LIB_ALLEGRO_CONFIG_H
namespace AGS3 {
extern void override_config_data(const char *data, int length);
} // namespace AGS3
#endif

View File

@@ -0,0 +1,115 @@
/* 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/>.
*
*/
#include "ags/lib/allegro/draw.h"
namespace AGS3 {
void drawing_mode(int mode, BITMAP *pattern, int x_anchor, int y_anchor) {
// TODO: Drawing mode
}
void xor_mode(int on) {
drawing_mode(on ? DRAW_MODE_XOR : DRAW_MODE_SOLID, NULL, 0, 0);
}
void solid_mode(void) {
drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
}
void do_line(BITMAP *bmp, int x1, int y1, int x2, int y2, int d, DrawMethod proc) {
int dx = x2 - x1;
int dy = y2 - y1;
int i1, i2;
int x, y;
int dd;
/* worker macro */
#define DO_LINE(pri_sign, pri_c, pri_cond, sec_sign, sec_c, sec_cond) \
{ \
if (d##pri_c == 0) { \
proc(bmp, x1, y1, d); \
return; \
} \
\
i1 = 2 * d##sec_c; \
dd = i1 - (sec_sign (pri_sign d##pri_c)); \
i2 = dd - (sec_sign (pri_sign d##pri_c)); \
\
x = x1; \
y = y1; \
\
while (pri_c pri_cond pri_c##2) { \
proc(bmp, x, y, d); \
\
if (dd sec_cond 0) { \
sec_c = sec_c sec_sign 1; \
dd += i2; \
} \
else \
dd += i1; \
\
pri_c = pri_c pri_sign 1; \
} \
}
if (dx >= 0) {
if (dy >= 0) {
if (dx >= dy) {
/* (x1 <= x2) && (y1 <= y2) && (dx >= dy) */
DO_LINE(+, x, <= , +, y, >=);
} else {
/* (x1 <= x2) && (y1 <= y2) && (dx < dy) */
DO_LINE(+, y, <= , +, x, >=);
}
} else {
if (dx >= -dy) {
/* (x1 <= x2) && (y1 > y2) && (dx >= dy) */
DO_LINE(+, x, <= , -, y, <=);
} else {
/* (x1 <= x2) && (y1 > y2) && (dx < dy) */
DO_LINE(-, y, >= , +, x, >=);
}
}
} else {
if (dy >= 0) {
if (-dx >= dy) {
/* (x1 > x2) && (y1 <= y2) && (dx >= dy) */
DO_LINE(-, x, >= , +, y, >=);
} else {
/* (x1 > x2) && (y1 <= y2) && (dx < dy) */
DO_LINE(+, y, <= , -, x, <=);
}
} else {
if (-dx >= -dy) {
/* (x1 > x2) && (y1 > y2) && (dx >= dy) */
DO_LINE(-, x, >= , -, y, <=);
} else {
/* (x1 > x2) && (y1 > y2) && (dx < dy) */
DO_LINE(-, y, >= , -, x, <=);
}
}
}
#undef DO_LINE
}
} // namespace AGS3

View File

@@ -0,0 +1,48 @@
/* 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/>.
*
*/
#include "ags/lib/allegro/base.h"
#include "ags/lib/allegro/gfx.h"
#include "ags/lib/allegro/surface.h"
#ifndef AGS_LIB_ALLEGRO_DRAW_H
#define AGS_LIB_ALLEGRO_DRAW_H
namespace AGS3 {
#define DRAW_MODE_SOLID 0 /* flags for drawing_mode() */
#define DRAW_MODE_XOR 1
#define DRAW_MODE_COPY_PATTERN 2
#define DRAW_MODE_SOLID_PATTERN 3
#define DRAW_MODE_MASKED_PATTERN 4
#define DRAW_MODE_TRANS 5
AL_FUNC(void, drawing_mode, (int mode, BITMAP *pattern, int x_anchor, int y_anchor));
AL_FUNC(void, xor_mode, (int on));
AL_FUNC(void, solid_mode, (void));
typedef void (*DrawMethod)(BITMAP *, int, int, int);
extern void do_line(BITMAP *bmp, int x1, int y1, int x2, int y2, int d, DrawMethod proc);
} // namespace AGS3
#endif

View File

@@ -0,0 +1,74 @@
/* 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/>.
*
*/
#ifndef AGS_LIB_ALLEGRO_ERROR_H
#define AGS_LIB_ALLEGRO_ERROR_H
#include "common/scummsys.h"
namespace AGS3 {
// Error codes
enum AllegroError {
AL_NOERROR = 0,
AL_EPERM = 1,
AL_ENOENT = 2,
AL_ESRCH = 3,
AL_EINTR = 4,
AL_EIO = 5,
AL_ENXIO = 6,
AL_E2BIG = 7,
AL_ENOEXEC = 8,
AL_EBADF = 9,
AL_ECHILD = 10,
AL_EAGAIN = 11,
AL_ENOMEM = 12,
AL_EACCES = 13,
AL_EFAULT = 14,
AL_EBUSY = 16,
AL_EEXIST = 17,
AL_EXDEV = 18,
AL_ENODEV = 19,
AL_ENOTDIR = 20,
AL_EISDIR = 21,
AL_EINVAL = 22,
AL_ENFILE = 23,
AL_EMFILE = 24,
AL_ENOTTY = 25,
AL_EFBIG = 27,
AL_ENOSPC = 28,
AL_ESPIPE = 29,
AL_EROFS = 30,
AL_EMLINK = 31,
AL_EPIPE = 32,
AL_EDOM = 33,
AL_ERANGE = 34,
AL_EDEADLK = 36,
AL_ENAMETOOLONG = 38,
AL_ENOLCK = 39,
AL_ENOSYS = 40,
AL_ENOTEMPTY = 41,
AL_EILSEQ = 42
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,261 @@
/* 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/>.
*
*/
#include "ags/lib/allegro/file.h"
#include "common/file.h"
#include "common/str.h"
#include "common/textconsole.h"
namespace AGS3 {
PACKFILE *PACKFILE::pack_fopen_chunk(int pack) {
error("TODO: pack_fopen_chunk is not yet supported");
}
PACKFILE *PACKFILE::pack_fclose_chunk() {
error("TODO: pack_fclose_chunk is not yet supported");
}
int PACKFILE::pack_igetw() {
byte buf[2];
return pack_fread(buf, 2) == 2 ? READ_LE_UINT16(buf) : 0;
}
int32_t PACKFILE::pack_igetl() {
byte buf[4];
return pack_fread(buf, 4) == 4 ? READ_LE_UINT32(buf) : 0;
}
int PACKFILE::pack_iputw(int w) {
byte buf[2];
WRITE_LE_UINT16(buf, w);
pack_fwrite(buf, 2);
return 0;
}
int32_t PACKFILE::pack_iputl(int32_t l) {
byte buf[4];
WRITE_LE_UINT32(buf, l);
pack_fwrite(buf, 4);
return 0;
}
int PACKFILE::pack_mgetw() {
byte buf[2];
return pack_fread(buf, 2) == 2 ? READ_BE_UINT16(buf) : 0;
}
int32_t PACKFILE::pack_mgetl() {
byte buf[4];
return pack_fread(buf, 4) == 4 ? READ_BE_UINT32(buf) : 0;
}
int PACKFILE::pack_mputw(int w) {
byte buf[2];
WRITE_BE_UINT16(buf, 2);
pack_fwrite(buf, 2);
return 0;
}
int32_t PACKFILE::pack_mputl(int32_t l) {
byte buf[4];
WRITE_BE_UINT16(buf, 4);
pack_fwrite(buf, 4);
return 0;
}
char *PACKFILE::pack_fgets(char *p, int max) {
int c;
char *dest = p;
while ((c = pack_getc()) != 0 && !pack_feof() && max-- > 0) {
*dest++ = c;
}
return p;
}
int PACKFILE::pack_fputs(AL_CONST char *p) {
pack_fwrite(p, strlen(p));
pack_putc(0);
return 0;
}
/*------------------------------------------------------------------*/
/* Use strictly UTF-8 encoding for the file paths
*/
#define U_CURRENT U_UTF8
#define ugetc utf8_getc
#define ugetx utf8_getx
#define ugetxc utf8_getx
#define usetc utf8_setc
#define uwidth utf8_width
#define ucwidth utf8_cwidth
#define uisok utf8_isok
void set_filename_encoding(int) {
// No implementation
}
char *fix_filename_case(char *path) {
return path;
}
char *fix_filename_slashes(char *path) {
return path;
}
char *append_filename(char *dest, const char *path, const char *filename, int size) {
strncpy(dest, path, size);
strncat(dest, filename, size);
return dest;
}
char *canonicalize_filename(char *dest, const char *filename, int size) {
strncpy(dest, filename, size);
return dest;
}
char *make_relative_filename(char *dest, const char *path, const char *filename, int size) {
strncpy(dest, filename, size);
return dest;
}
int is_relative_filename(const char *filename) {
// ScummVM doesn't have absolute paths
return true;
}
/*------------------------------------------------------------------*/
void packfile_password(AL_CONST char *password) {
error("TODO: packfile_password");
}
PACKFILE *pack_fopen(AL_CONST char *filename, AL_CONST char *mode) {
assert(!strcmp(mode, "r") || !strcmp(mode, "rb"));
Common::File *f = new Common::File();
if (f->open(filename)) {
return new ScummVMPackFile(f);
} else {
delete f;
return nullptr;
}
}
PACKFILE *pack_fopen_vtable(AL_CONST PACKFILE_VTABLE *vtable, void *userdata) {
return new VTablePackFile(vtable, userdata);
}
int pack_fclose(PACKFILE *f) {
f->close();
delete f;
return 0;
}
int pack_fseek(PACKFILE *f, int offset) {
return f->pack_fseek(offset);
}
PACKFILE *pack_fopen_chunk(PACKFILE *f, int pack) {
return f->pack_fopen_chunk(pack);
}
PACKFILE *pack_fclose_chunk(PACKFILE *f) {
return f->pack_fclose_chunk();
}
int pack_getc(PACKFILE *f) {
return f->pack_getc();
}
int pack_putc(int c, PACKFILE *f) {
return f->pack_putc(c);
}
int pack_feof(PACKFILE *f) {
return f->pack_feof();
}
int pack_ferror(PACKFILE *f) {
return f->pack_ferror();
}
int pack_igetw(PACKFILE *f) {
error("TODO: xxx");
}
int32_t pack_igetl(PACKFILE *f) {
return f->pack_igetl();
}
int pack_iputw(int w, PACKFILE *f) {
return f->pack_iputw(w);
}
int32_t pack_iputl(int32_t l, PACKFILE *f) {
return f->pack_iputl(l);
}
int pack_mgetw(PACKFILE *f) {
return f->pack_mgetw();
}
int32_t pack_mgetl(PACKFILE *f) {
return f->pack_mgetl();
}
int pack_mputw(int w, PACKFILE *f) {
return f->pack_mputw(w);
}
int32_t pack_mputl(int32_t l, PACKFILE *f) {
return f->pack_mputl(l);
}
long pack_fread(void *p, long n, PACKFILE *f) {
return f->pack_fread(p, n);
}
long pack_fwrite(AL_CONST void *p, long n, PACKFILE *f) {
return f->pack_fwrite(p, n);
}
int pack_ungetc(int c, PACKFILE *f) {
return f->pack_ungetc(c);
}
char *pack_fgets(char *p, int max, PACKFILE *f) {
return f->pack_fgets(p, max);
}
int pack_fputs(AL_CONST char *p, PACKFILE *f) {
return f->pack_fputs(p);
}
void *pack_get_userdata(PACKFILE *f) {
return f->pack_get_userdata();
}
} // namespace AGS3

View File

@@ -0,0 +1,227 @@
/* 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/>.
*
*/
#ifndef AGS_LIB_ALLEGRO_FILE_H
#define AGS_LIB_ALLEGRO_FILE_H
#include "ags/lib/allegro/alconfig.h"
#include "ags/shared/core/types.h"
#include "common/file.h"
namespace AGS3 {
#define F_READ "r"
#define F_WRITE "w"
#define F_BUF_SIZE 4096 /* 4K buffer for caching data */
struct _al_normal_packfile_details {
int hndl; /* DOS file handle */
int flags; /* PACKFILE_FLAG_* constants */
unsigned char *buf_pos; /* position in buffer */
int buf_size; /* number of bytes in the buffer */
long todo; /* number of bytes still on the disk */
struct PACKFILE *parent; /* nested, parent file */
char *filename; /* name of the file */
unsigned char buf[F_BUF_SIZE]; /* the actual data buffer */
};
struct PACKFILE_VTABLE {
AL_METHOD(int, pf_fclose, (void *userdata));
AL_METHOD(int, pf_getc, (void *userdata));
AL_METHOD(int, pf_ungetc, (int c, void *userdata));
AL_METHOD(long, pf_fread, (void *p, long n, void *userdata));
AL_METHOD(int, pf_putc, (int c, void *userdata));
AL_METHOD(long, pf_fwrite, (AL_CONST void *p, long n, void *userdata));
AL_METHOD(int, pf_fseek, (void *userdata, int offset));
AL_METHOD(int, pf_feof, (void *userdata));
AL_METHOD(int, pf_ferror, (void *userdata));
};
/**
* Allegro file class
*/
struct PACKFILE {
virtual ~PACKFILE() {
close();
}
virtual void close() {}
virtual int pack_fseek(int offset) = 0;
virtual int pack_getc() = 0;
virtual int pack_putc(int c) = 0;
virtual int pack_ungetc(int c) = 0;
virtual long pack_fread(void *p, long n) = 0;
virtual long pack_fwrite(AL_CONST void *p, long n) = 0;
virtual int pack_feof() = 0;
virtual int pack_ferror() = 0;
virtual void *pack_get_userdata() const {
return nullptr;
}
PACKFILE *pack_fopen_chunk(int pack);
PACKFILE *pack_fclose_chunk();
int pack_igetw();
int32_t pack_igetl();
int pack_iputw(int w);
int32_t pack_iputl(int32_t l);
int pack_mgetw();
int32_t pack_mgetl();
int pack_mputw(int w);
int32_t pack_mputl(int32_t l);
char *pack_fgets(char *p, int max);
int pack_fputs(AL_CONST char *p);
};
struct ScummVMPackFile : public PACKFILE {
public:
Common::SeekableReadStream *_stream;
ScummVMPackFile(Common::SeekableReadStream *rs) : PACKFILE(), _stream(rs) {
}
virtual ~ScummVMPackFile() {}
void close() override {
delete _stream;
_stream = nullptr;
}
int pack_fseek(int offset) override {
return _stream->seek(offset, SEEK_CUR);
}
int pack_getc() override {
return _stream->readByte();
}
int pack_putc(int c) override {
error("pack_putc is not yet supported");
}
int pack_ungetc(int c) override {
_stream->seek(-1, SEEK_CUR);
return 0;
}
long pack_fread(void *p, long n) override {
return _stream->read(p, n);
}
long pack_fwrite(AL_CONST void *p, long n) override {
error("pack_fwrite is not yet supported");
}
int pack_feof() override {
return _stream->eos();
}
int pack_ferror() override {
return _stream->err();
}
};
struct VTablePackFile : public PACKFILE {
AL_CONST PACKFILE_VTABLE *_vTable;
void *_userData;
VTablePackFile(AL_CONST PACKFILE_VTABLE *vTable, void *userData) :
_vTable(vTable), _userData(userData) {
}
void close() override {
_vTable->pf_fclose(_userData);
}
int pack_fseek(int offset) override {
return _vTable->pf_fseek(_userData, offset);
}
int pack_getc() override {
return _vTable->pf_getc(_userData);
}
int pack_putc(int c) override {
return _vTable->pf_putc(c, _userData);
}
int pack_ungetc(int c) override {
return _vTable->pf_ungetc(c, _userData);
}
long pack_fread(void *p, long n) override {
return _vTable->pf_fread(p, n, _userData);
}
long pack_fwrite(AL_CONST void *p, long n) override {
return _vTable->pf_fwrite(p, n, _userData);
}
int pack_feof() override {
return _vTable->pf_feof(_userData);
}
int pack_ferror() override {
return _vTable->pf_ferror(_userData);
}
void *pack_get_userdata() const override {
return _userData;
}
};
extern void set_filename_encoding(int);
extern char *fix_filename_case(char *path);
extern char *fix_filename_slashes(char *path);
extern char *append_filename(char *dest, const char *path, const char *filename, int size);
extern char *canonicalize_filename(char *dest, const char *filename, int size);
extern char *make_relative_filename(char *dest, const char *path, const char *filename, int size);
extern int is_relative_filename(const char *filename);
AL_FUNC(void, packfile_password, (AL_CONST char *password));
AL_FUNC(PACKFILE *, pack_fopen, (AL_CONST char *filename, AL_CONST char *mode));
AL_FUNC(PACKFILE *, pack_fopen_vtable, (AL_CONST PACKFILE_VTABLE *vtable, void *userdata));
AL_FUNC(int, pack_fclose, (PACKFILE *f));
AL_FUNC(int, pack_fseek, (PACKFILE *f, int offset));
AL_FUNC(PACKFILE *, pack_fopen_chunk, (PACKFILE *f, int pack));
AL_FUNC(PACKFILE *, pack_fclose_chunk, (PACKFILE *f));
AL_FUNC(int, pack_getc, (PACKFILE *f));
AL_FUNC(int, pack_putc, (int c, PACKFILE *f));
AL_FUNC(int, pack_feof, (PACKFILE *f));
AL_FUNC(int, pack_ferror, (PACKFILE *f));
AL_FUNC(int, pack_igetw, (PACKFILE *f));
AL_FUNC(int32_t, pack_igetl, (PACKFILE *f));
AL_FUNC(int, pack_iputw, (int w, PACKFILE *f));
AL_FUNC(int32_t, pack_iputl, (int32_t l, PACKFILE *f));
AL_FUNC(int, pack_mgetw, (PACKFILE *f));
AL_FUNC(int32_t, pack_mgetl, (PACKFILE *f));
AL_FUNC(int, pack_mputw, (int w, PACKFILE *f));
AL_FUNC(int32_t, pack_mputl, (int32_t l, PACKFILE *f));
AL_FUNC(long, pack_fread, (void *p, long n, PACKFILE *f));
AL_FUNC(long, pack_fwrite, (AL_CONST void *p, long n, PACKFILE *f));
AL_FUNC(int, pack_ungetc, (int c, PACKFILE *f));
AL_FUNC(char *, pack_fgets, (char *p, int max, PACKFILE *f));
AL_FUNC(int, pack_fputs, (AL_CONST char *p, PACKFILE *f));
AL_FUNC(void *, pack_get_userdata, (PACKFILE *f));
} // namespace AGS3
#endif

View File

@@ -0,0 +1,174 @@
/* 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/>.
*
*/
#include "ags/lib/allegro/fixed.h"
#include "ags/lib/allegro/error.h"
#include "ags/globals.h"
namespace AGS3 {
fixed ftofix(double x) {
if (x > 32767.0) {
*_G(allegro_errno) = AL_ERANGE;
return 0x7FFFFFFF;
}
if (x < -32767.0) {
*_G(allegro_errno) = AL_ERANGE;
return (fixed) - 0x7FFFFFFF;
}
return (fixed)(x * 65536.0 + (x < 0 ? -0.5 : 0.5));
}
double fixtof(fixed x) {
return (double)x / 65536.0;
}
fixed fixadd(fixed x, fixed y) {
fixed result = x + y;
if (result >= 0) {
if ((x < 0) && (y < 0)) {
*_G(allegro_errno) = AL_ERANGE;
return (fixed) - 0x7FFFFFFF;
} else
return result;
} else {
if ((x > 0) && (y > 0)) {
*_G(allegro_errno) = AL_ERANGE;
return 0x7FFFFFFF;
} else
return result;
}
}
fixed fixsub(fixed x, fixed y) {
fixed result = x - y;
if (result >= 0) {
if ((x < 0) && (y > 0)) {
*_G(allegro_errno) = AL_ERANGE;
return (fixed) - 0x7FFFFFFF;
} else
return result;
} else {
if ((x > 0) && (y < 0)) {
*_G(allegro_errno) = AL_ERANGE;
return 0x7FFFFFFF;
} else
return result;
}
}
fixed fixmul(fixed x, fixed y) {
int64 lx = x;
int64 ly = y;
int64 lres = (lx * ly);
if (lres > 0x7FFFFFFF0000LL) {
*_G(allegro_errno) = AL_ERANGE;
return 0x7FFFFFFF;
} else if (lres < -0x7FFFFFFF0000LL) {
*_G(allegro_errno) = AL_ERANGE;
return 0x80000000;
} else {
int res = lres >> 16;
return res;
}
}
fixed fixdiv(fixed x, fixed y) {
if (y == 0) {
*_G(allegro_errno) = AL_ERANGE;
return (fixed)(x < 0) ? -0x7FFFFFFF : 0x7FFFFFFF;
} else
return ftofix(fixtof(x) / fixtof(y));
}
int fixfloor(fixed x) {
// FIXME: GCC warning "this condition has identical branches [-Wduplicated-branches]" on this code i.e. both branches are functionally identical. Remove?
#if 0
/* (x >> 16) is not portable */
if (x >= 0)
return (x >> 16);
else
return ~((~x) >> 16);
#else
return (x >> 16);
#endif
}
int fixceil(fixed x) {
if (x > 0x7FFF0000) {
*_G(allegro_errno) = AL_ERANGE;
return 0x7FFF;
}
return fixfloor(x + 0xFFFF);
}
fixed itofix(int x) {
return x << 16;
}
int fixtoi(fixed x) {
return fixfloor(x) + ((x & 0x8000) >> 15);
}
fixed fixcos(fixed x) {
return _cos_tbl[((x + 0x4000) >> 15) & 0x1FF];
}
fixed fixsin(fixed x) {
return _cos_tbl[((x - 0x400000 + 0x4000) >> 15) & 0x1FF];
}
fixed fixtan(fixed x) {
return _tan_tbl[((x + 0x4000) >> 15) & 0xFF];
}
fixed fixacos(fixed x) {
if ((x < -65536) || (x > 65536)) {
*_G(allegro_errno) = AL_EDOM;
return 0;
}
return _acos_tbl[(x + 65536 + 127) >> 8];
}
fixed fixasin(fixed x) {
if ((x < -65536) || (x > 65536)) {
*_G(allegro_errno) = AL_EDOM;
return 0;
}
return 0x00400000 - _acos_tbl[(x + 65536 + 127) >> 8];
}
} // namespace AGS3

View File

@@ -0,0 +1,54 @@
/* 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/>.
*
*/
#ifndef AGS_LIB_ALLEGRO_FIXED_H
#define AGS_LIB_ALLEGRO_FIXED_H
#include "common/scummsys.h"
#include "ags/shared/core/types.h"
namespace AGS3 {
typedef int32_t fixed;
extern const fixed _cos_tbl[];
extern const fixed _tan_tbl[];
extern const fixed _acos_tbl[];
extern fixed ftofix(double x);
extern double fixtof(fixed x);
extern fixed fixadd(fixed x, fixed y);
extern fixed fixsub(fixed x, fixed y);
extern fixed fixmul(fixed x, fixed y);
extern fixed fixdiv(fixed x, fixed y);
extern int fixfloor(fixed x);
extern int fixceil(fixed x);
extern fixed itofix(int x);
extern int fixtoi(fixed x);
extern fixed fixcos(fixed x);
extern fixed fixsin(fixed x);
extern fixed fixtan(fixed x);
extern fixed fixacos(fixed x);
extern fixed fixasin(fixed x);
} // namespace AGS3
#endif

View File

@@ -0,0 +1,233 @@
/* 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/>.
*
*/
#include "ags/lib/allegro/flood.h"
#include "ags/lib/allegro/gfx.h"
#include "ags/shared/core/types.h"
#include "common/array.h"
namespace AGS3 {
struct FLOODED_LINE {
short flags; /* status of the segment */
short lpos, rpos; /* left and right ends of segment */
short y; /* y coordinate of the segment */
int next; /* linked list if several per line */
};
#define FLOOD_IN_USE 1
#define FLOOD_TODO_ABOVE 2
#define FLOOD_TODO_BELOW 4
#define FLOOD_LINE(c) (&scratchMem[c])
template<class SIZE>
static bool scanLine(BITMAP *bmp, int x, int y, int src_color, int &left, int &right) {
// check start pixel
const SIZE *pixel = (const SIZE *)bmp->getBasePtr(x, y);
if (*pixel != src_color)
return false;
// Work left from starting point
const SIZE *pixelLeft = pixel - 1;
for (left = x - 1; left >= bmp->cl; left--, pixelLeft--) {
if (*pixelLeft != src_color)
break;
}
// Work right from starting point
const SIZE *pixelRight = pixel + 1;
for (right = x + 1; right < bmp->cr; right++, pixelRight++) {
if (*pixelRight != src_color)
break;
}
return true;
}
/**
* Fills a horizontal line around the specified position, and adds it
* to the list of drawn segments. Returns the first x coordinate after
* the part of the line which it has dealt with.
*/
static int flooder(BITMAP *bmp, int x, int y, int src_color, int dest_color,
Common::Array<FLOODED_LINE> &scratchMem) {
FLOODED_LINE *p;
int left = 0, right = 0;
int c;
assert(bmp);
bool ret;
switch (bmp->format.bytesPerPixel) {
case 1:
ret = scanLine<byte>(bmp, x, y, src_color, left, right);
break;
case 2:
ret = scanLine<byte>(bmp, x, y, src_color, left, right);
break;
case 4:
ret = scanLine<byte>(bmp, x, y, src_color, left, right);
break;
default:
error("Unknown format");
}
if (!ret)
return x + 1;
left++;
right--;
/* draw the line */
bmp->hLine(left, y, right, dest_color);
/* store it in the list of flooded segments */
c = y;
p = FLOOD_LINE(c);
if (p->flags) {
while (p->next) {
c = p->next;
p = FLOOD_LINE(c);
}
p->next = c = scratchMem.size();
scratchMem.resize(scratchMem.size() + 1);
p = FLOOD_LINE(c);
}
p->flags = FLOOD_IN_USE;
p->lpos = left;
p->rpos = right;
p->y = y;
p->next = 0;
if (y > bmp->ct)
p->flags |= FLOOD_TODO_ABOVE;
if (y + 1 < bmp->cb)
p->flags |= FLOOD_TODO_BELOW;
return right + 2;
}
/**
* Checks a line segment, using the scratch buffer is to store a list of
* segments which have already been drawn in order to minimise the required
* number of tests.
*/
static bool check_flood_line(BITMAP *bmp, int y, int left, int right, int src_color, int dest_color,
Common::Array<FLOODED_LINE> &scratchMem) {
int c;
FLOODED_LINE *p;
bool ret = false;
while (left <= right) {
c = y;
for (;;) {
p = FLOOD_LINE(c);
if ((left >= p->lpos) && (left <= p->rpos)) {
left = p->rpos + 2;
break;
}
c = p->next;
if (!c) {
left = flooder(bmp, left, y, src_color, dest_color, scratchMem);
ret = true;
break;
}
}
}
return ret;
}
void floodfill(BITMAP *bmp, int x, int y, int color) {
int src_color;
int c;
bool done;
FLOODED_LINE *p;
Common::Array<FLOODED_LINE> scratchMem;
/* make sure we have a valid starting point */
if ((x < bmp->cl) || (x >= bmp->cr) || (y < bmp->ct) || (y >= bmp->cb))
return;
/* what color to replace? */
src_color = getpixel(bmp, x, y);
if (src_color == color) {
return;
}
/* set up the list of flooded segments */
scratchMem.resize(bmp->cb);
p = FLOOD_LINE(0);
for (c = 0; c < (int)scratchMem.size(); c++) {
p[c].flags = 0;
p[c].lpos = INT16_MAX;
p[c].rpos = INT16_MIN;
p[c].y = y;
p[c].next = 0;
}
/* start up the flood algorithm */
flooder(bmp, x, y, src_color, color, scratchMem);
/* continue as long as there are some segments still to test */
do {
done = true;
/* for each line on the screen */
for (c = 0; c < (int)scratchMem.size(); c++) {
p = FLOOD_LINE(c);
/* check below the segment? */
if (p->flags & FLOOD_TODO_BELOW) {
p->flags &= ~FLOOD_TODO_BELOW;
if (check_flood_line(bmp, p->y + 1, p->lpos, p->rpos, src_color, color, scratchMem)) {
done = false;
p = FLOOD_LINE(c);
}
}
/* check above the segment? */
if (p->flags & FLOOD_TODO_ABOVE) {
p->flags &= ~FLOOD_TODO_ABOVE;
if (check_flood_line(bmp, p->y - 1, p->lpos, p->rpos, src_color, color, scratchMem)) {
done = false;
/* special case shortcut for going backwards */
if ((c < bmp->cb) && (c > 0))
c -= 2;
}
}
}
} while (!done);
}
} // namespace AGS3

View File

@@ -0,0 +1,36 @@
/* 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/>.
*
*/
#ifndef AGS_LIB_ALLEGRO_FLOOD_H
#define AGS_LIB_ALLEGRO_FLOOD_H
#include "graphics/managed_surface.h"
#include "ags/lib/allegro/base.h"
namespace AGS3 {
class BITMAP;
extern void floodfill(BITMAP *bmp, int x, int y, int color);
} // namespace AGS3
#endif

View File

@@ -0,0 +1,99 @@
/* 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/>.
*
*/
#include "ags/lib/allegro/fmaths.h"
namespace AGS3 {
fixed fixsqrt(fixed x) {
if (x > 0)
return ftofix(sqrt(fixtof(x)));
if (x < 0)
*allegro_errno = EDOM;
return 0;
}
fixed fixhypot(fixed x, fixed y) {
return ftofix(hypot(fixtof(x), fixtof(y)));
}
fixed fixatan(fixed x) {
int a, b, c; /* for binary search */
fixed d; /* difference value for search */
if (x >= 0) { /* search the first part of tan table */
a = 0;
b = 127;
} else { /* search the second half instead */
a = 128;
b = 255;
}
do {
c = (a + b) >> 1;
d = x - _tan_tbl[c];
if (d > 0)
a = c + 1;
else if (d < 0)
b = c - 1;
} while ((a <= b) && (d));
if (x >= 0)
return ((long)c) << 15;
return (-0x00800000L + (((long)c) << 15));
}
fixed fixatan2(fixed y, fixed x) {
fixed r;
if (x == 0) {
if (y == 0) {
*allegro_errno = EDOM;
return 0L;
} else
return ((y < 0) ? -0x00400000L : 0x00400000L);
}
*allegro_errno = 0;
r = fixdiv(y, x);
if (*allegro_errno) {
*allegro_errno = 0;
return ((y < 0) ? -0x00400000L : 0x00400000L);
}
r = fixatan(r);
if (x >= 0)
return r;
if (y >= 0)
return 0x00800000L + r;
return r - 0x00800000L;
}
} // namespace AGS3

View File

@@ -0,0 +1,40 @@
/* 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/>.
*
*/
#ifndef AGS_LIB_ALLEGRO_FMATHS_H
#define AGS_LIB_ALLEGRO_FMATHS_H
#include "ags/lib/allegro/fixed.h"
namespace AGS3 {
AL_FUNC(fixed, fixsqrt, (fixed x));
AL_FUNC(fixed, fixhypot, (fixed x, fixed y));
AL_FUNC(fixed, fixatan, (fixed x));
AL_FUNC(fixed, fixatan2, (fixed y, fixed x));
AL_ARRAY(const fixed, _cos_tbl);
AL_ARRAY(const fixed, _tan_tbl);
AL_ARRAY(const fixed, _acos_tbl);
} // namespace AGS3
#endif

View File

@@ -0,0 +1,390 @@
/* 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/>.
*
*/
#include "ags/lib/allegro/gfx.h"
#include "ags/lib/allegro/color.h"
#include "ags/lib/allegro/flood.h"
#include "ags/lib/allegro/rotate.h"
#include "ags/ags.h"
#include "ags/globals.h"
#include "common/textconsole.h"
#include "common/util.h"
#include "graphics/screen.h"
namespace AGS3 {
int color_conversion;
/*-------------------------------------------------------------------*/
void set_color_conversion(int mode) {
color_conversion = mode;
}
int get_color_conversion() {
return color_conversion;
}
int set_gfx_mode(int card, int w, int h, int depth) {
// Graphics shutdown can be ignored
if (card != -1) {
assert(card == SCUMMVM_ID);
::AGS::g_vm->setGraphicsMode(w, h, depth);
}
return 0;
}
void set_clip_rect(BITMAP *bitmap, int x1, int y1, int x2, int y2) {
// The rect passed to the function in inclusive-inclusive, but
// internally the clipping rect in BITMAP is inclusive-exclusive.
bitmap->cl = CLIP(x1, 0, (int)bitmap->w - 1);
bitmap->ct = CLIP(y1, 0, (int)bitmap->h - 1);
bitmap->cr = CLIP(x2 + 1, 0, (int)bitmap->w);
bitmap->cb = CLIP(y2 + 1, 0, (int)bitmap->h);
}
void get_clip_rect(BITMAP *bitmap, int *x1, int *y1, int *x2, int *y2) {
if (x1)
*x1 = bitmap->cl;
if (y1)
*y1 = bitmap->ct;
if (x2)
*x2 = bitmap->cr - 1;
if (y2)
*y2 = bitmap->cb - 1;
}
void acquire_bitmap(BITMAP *bitmap) {
// No implementation needed
}
void release_bitmap(BITMAP *bitmap) {
// No implementation needed
}
void clear_to_color(BITMAP *bitmap, int color) {
Graphics::ManagedSurface &surf = **bitmap;
surf.clear(color);
}
int bitmap_color_depth(BITMAP *bmp) {
Graphics::ManagedSurface &surf = **bmp;
return (surf.format.bytesPerPixel == 1) ? 8 : surf.format.bpp();
}
int bitmap_mask_color(BITMAP *bmp) {
// For paletted sprites this is 0.
// For other color depths this is bright pink (RGB 255, 0, 255).
// The alpha chanel should be 0.
//if (bmp-format.bytesPerPixel == 1)
// return 0;
//return bmp->format.AGRBToColor(0, 255, 0, 255);
return bmp->getTransparentColor();
}
void blit(const BITMAP *src, BITMAP *dest, int src_x, int src_y, int dst_x, int dst_y, int width, int height) {
dest->draw(src, Common::Rect(src_x, src_y, src_x + width, src_y + height),
dst_x, dst_y, false, false, false, -1);
}
void stretch_blit(const BITMAP *src, BITMAP *dest,
int source_x, int source_y, int source_width, int source_height,
int dest_x, int dest_y, int dest_width, int dest_height) {
dest->stretchDraw(src,
Common::Rect(source_x, source_y, source_x + source_width, source_y + source_height),
Common::Rect(dest_x, dest_y, dest_x + dest_width, dest_y + dest_height),
false, -1);
}
void masked_blit(const BITMAP *src, BITMAP *dest, int src_x, int src_y, int dst_x, int dst_y, int width, int height) {
assert(src->format == dest->format);
dest->draw(src, Common::Rect(src_x, src_y, src_x + width, src_y + height),
dst_x, dst_y, false, false, true, -1);
}
void masked_stretch_blit(const BITMAP *src, BITMAP *dest,
int source_x, int source_y, int source_width, int source_height,
int dest_x, int dest_y, int dest_width, int dest_height) {
dest->stretchDraw(src,
Common::Rect(source_x, source_y, source_x + source_width, source_y + source_height),
Common::Rect(dest_x, dest_y, dest_x + dest_width, dest_y + dest_height),
true, -1);
}
void draw_sprite(BITMAP *bmp, const BITMAP *sprite, int x, int y) {
bmp->draw(sprite, Common::Rect(0, 0, sprite->w, sprite->h),
x, y, false, false, true, -1);
}
void stretch_sprite(BITMAP *bmp, const BITMAP *sprite, int x, int y, int w, int h) {
bmp->stretchDraw(sprite, Common::Rect(0, 0, sprite->w, sprite->h),
Common::Rect(x, y, x + w, y + h),
true, -1);
}
void draw_trans_sprite(BITMAP *bmp, const BITMAP *sprite, int x, int y) {
bmp->draw(sprite, Common::Rect(0, 0, sprite->w, sprite->h),
x, y, false, false, true, _G(trans_blend_alpha));
}
void draw_lit_sprite(BITMAP *bmp, const BITMAP *sprite, int x, int y, int color) {
bmp->draw(sprite, Common::Rect(0, 0, sprite->w, sprite->h),
x, y, false, false, true, color,
_G(trans_blend_red), _G(trans_blend_green), _G(trans_blend_blue));
}
void draw_sprite_h_flip(BITMAP *bmp, const BITMAP *sprite, int x, int y) {
bmp->draw(sprite, Common::Rect(0, 0, sprite->w, sprite->h),
x, y, true, false, true, -1);
}
void draw_sprite_v_flip(BITMAP *bmp, const BITMAP *sprite, int x, int y) {
bmp->draw(sprite, Common::Rect(0, 0, sprite->w, sprite->h),
x, y, false, true, true, -1);
}
void draw_sprite_vh_flip(BITMAP *bmp, const BITMAP *sprite, int x, int y) {
bmp->draw(sprite, Common::Rect(0, 0, sprite->w, sprite->h),
x, y, true, true, true, -1);
}
void rotate_sprite(BITMAP *bmp, const BITMAP *sprite, int x, int y, fixed angle) {
pivot_scaled_sprite(bmp, sprite, (x<<16) + (sprite->w * 0x10000) / 2, (y<<16) + (sprite->h * 0x10000) / 2, sprite->w << 15, sprite->h << 15, angle, 0x10000);
}
void pivot_sprite(BITMAP *bmp, const BITMAP *sprite, int x, int y, int cx, int cy, fixed angle) {
pivot_scaled_sprite(bmp, sprite, x<<16, y<<16, cx<<16, cy<<16, angle, 0x10000);
}
bool is_screen_bitmap(BITMAP *bmp) {
return dynamic_cast<Graphics::Screen *>(bmp) != nullptr;
}
bool is_video_bitmap(BITMAP *bmp) {
return dynamic_cast<Graphics::Screen *>(bmp) != nullptr;
}
bool is_planar_bitmap(BITMAP *bmp) {
return false;
}
bool is_linear_bitmap(BITMAP *bmp) {
return true;
}
bool is_same_bitmap(BITMAP *bmp1, BITMAP *bmp2) {
if ((bmp1 == nullptr) || (bmp2 == nullptr))
return false;
if (bmp1 == bmp2)
return true;
// TODO: allegro also returns true if one bmp is a sub of the other,
// i.e. they share the same id
// This (if needed?) would require a different implementation
return false;
}
void bmp_select(BITMAP *bmp) {
// No implementation needed
}
byte *bmp_write_line(BITMAP *bmp, int line) {
return bmp->line[line];
}
void bmp_write8(byte *addr, int color) {
*addr = color;
}
void bmp_write15(byte *addr, int color) {
*((uint16 *)addr) = color;
}
void bmp_write16(byte *addr, int color) {
*((uint16 *)addr) = color;
}
void bmp_write24(byte *addr, int color) {
*addr = (color & 0xff);
*(addr + 1) = ((color >> 8) & 0xff);
*(addr + 2) = ((color >> 16) & 0xff);
}
void bmp_write32(byte *addr, int color) {
*((uint32 *)addr) = color;
}
void memory_putpixel(BITMAP *bmp, int x, int y, int color) {
putpixel(bmp, x, y, color);
}
void putpixel(BITMAP *bmp, int x, int y, int color) {
Graphics::ManagedSurface &surf = **bmp;
if (x < 0 || x >= surf.w || y < 0 || y >= surf.h)
return;
void *p = surf.getBasePtr(x, y);
switch (surf.format.bytesPerPixel) {
case 1:
*((uint8 *)p) = color;
break;
case 2:
*((uint16 *)p) = color;
break;
case 4:
*((uint32 *)p) = color;
break;
default:
break;
}
}
void _putpixel(BITMAP *bmp, int x, int y, int color) {
Graphics::ManagedSurface &surf = **bmp;
if (x < 0 || x >= surf.w || y < 0 || y >= surf.h)
return;
void *p = surf.getBasePtr(x, y);
*((uint8 *)p) = color;
}
void _putpixel15(BITMAP *bmp, int x, int y, int color) {
error("Unsupported bpp");
}
void _putpixel16(BITMAP *bmp, int x, int y, int color) {
Graphics::ManagedSurface &surf = **bmp;
if (x < 0 || x >= surf.w || y < 0 || y >= surf.h)
return;
void *p = surf.getBasePtr(x, y);
*((uint16 *)p) = color;
}
void _putpixel24(BITMAP *bmp, int x, int y, int color) {
error("Unsupported bpp");
}
void _putpixel32(BITMAP *bmp, int x, int y, int color) {
Graphics::ManagedSurface &surf = **bmp;
if (x < 0 || x >= surf.w || y < 0 || y >= surf.h)
return;
void *p = surf.getBasePtr(x, y);
*((uint32 *)p) = color;
}
int getpixel(const BITMAP *bmp, int x, int y) {
Graphics::ManagedSurface &surf = **bmp;
// Allegro returns -1 if the pixel lies outside the bitmap
if (x < 0 || y < 0 || x >= surf.w || y >= surf.h)
return -1;
void *p = surf.getBasePtr(x, y);
switch (surf.format.bytesPerPixel) {
case 1:
return *((uint8 *)p);
case 2:
return *((uint16 *)p);
case 4:
return *((uint32 *)p);
default:
break;
}
error("Unsupported bpp");
}
int _getpixel(const BITMAP *bmp, int x, int y) {
Graphics::ManagedSurface &surf = **bmp;
if (x < 0 || y < 0 || x >= surf.w || y >= surf.h)
return -1;
void *p = surf.getBasePtr(x, y);
return *((uint8 *)p);
}
int _getpixel15(const BITMAP *bmp, int x, int y) {
error("Unsupported bpp");
}
int _getpixel16(const BITMAP *bmp, int x, int y) {
Graphics::ManagedSurface &surf = **bmp;
if (x < 0 || y < 0 || x >= surf.w || y >= surf.h)
return -1;
void *p = surf.getBasePtr(x, y);
return *((uint16 *)p);
}
int _getpixel24(const BITMAP *bmp, int x, int y) {
error("Unsupported bpp");
}
int _getpixel32(const BITMAP *bmp, int x, int y) {
Graphics::ManagedSurface &surf = **bmp;
if (x < 0 || y < 0 || x >= surf.w || y >= surf.h)
return -1;
void *p = surf.getBasePtr(x, y);
return *((uint32 *)p);
}
void line(BITMAP *bmp, int x1, int y1, int x2, int y2, int color) {
Graphics::ManagedSurface &surf = **bmp;
surf.drawLine(x1, y1, x2, y2, color);
}
void rect(BITMAP *bmp, int x1, int y1, int x2, int y2, int color) {
Graphics::ManagedSurface &surf = **bmp;
if (x1 > x2)
SWAP(x1, x2);
if (y1 > y2)
SWAP(y1, y2);
surf.frameRect(Common::Rect(x1, y1, x2 + 1, y2 + 1), color);
}
void rectfill(BITMAP *bmp, int x1, int y1, int x2, int y2, int color) {
Graphics::ManagedSurface &surf = **bmp;
if (x1 > x2)
SWAP(x1, x2);
if (y1 > y2)
SWAP(y1, y2);
surf.fillRect(Common::Rect(x1, y1, x2 + 1, y2 + 1), color);
}
void triangle(BITMAP *bmp, int x1, int y1, int x2, int y2, int x3, int y3, int color) {
Graphics::ManagedSurface &surf = **bmp;
surf.drawLine(x1, y1, x2, y2, color);
surf.drawLine(x2, y2, x3, y3, color);
surf.drawLine(x3, y3, x1, y1, color);
}
void circlefill(BITMAP *bmp, int x, int y, int radius, int color) {
bmp->circlefill(x, y, radius, color);
}
void clear_bitmap(BITMAP *bmp) {
bmp->clear();
}
} // namespace AGS3

View File

@@ -0,0 +1,240 @@
/* 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/>.
*
*/
#ifndef AGS_LIB_ALLEGRO_GRAPHICS_H
#define AGS_LIB_ALLEGRO_GRAPHICS_H
#include "graphics/managed_surface.h"
#include "ags/lib/allegro/base.h"
#include "ags/lib/allegro/fixed.h"
#include "ags/lib/allegro/surface.h"
#include "common/array.h"
namespace AGS3 {
#define GFX_TEXT -1
#define GFX_AUTODETECT 0
#define GFX_AUTODETECT_FULLSCREEN 1
#define GFX_AUTODETECT_WINDOWED 2
#define GFX_SAFE AL_ID('S','A','F','E')
#define GFX_NONE AL_ID('N','O','N','E')
/* Bitfield for relaying graphics driver type information */
#define GFX_TYPE_UNKNOWN 0
#define GFX_TYPE_WINDOWED 1
#define GFX_TYPE_FULLSCREEN 2
#define GFX_TYPE_DEFINITE 4
#define GFX_TYPE_MAGIC 8
/* drawing modes for draw_sprite_ex() */
#define DRAW_SPRITE_NORMAL 0
#define DRAW_SPRITE_LIT 1
#define DRAW_SPRITE_TRANS 2
/* flipping modes for draw_sprite_ex() */
#define DRAW_SPRITE_NO_FLIP 0x0
#define DRAW_SPRITE_H_FLIP 0x1
#define DRAW_SPRITE_V_FLIP 0x2
#define DRAW_SPRITE_VH_FLIP 0x3
/* Blender mode defines, for the gfx_driver->set_blender_mode() function */
#define blender_mode_none 0
#define blender_mode_trans 1
#define blender_mode_add 2
#define blender_mode_burn 3
#define blender_mode_color 4
#define blender_mode_difference 5
#define blender_mode_dissolve 6
#define blender_mode_dodge 7
#define blender_mode_hue 8
#define blender_mode_invert 9
#define blender_mode_luminance 10
#define blender_mode_multiply 11
#define blender_mode_saturation 12
#define blender_mode_screen 13
#define blender_mode_alpha 14
#define SCREEN_W (gfx_driver ? gfx_driver->w : 0)
#define SCREEN_H (gfx_driver ? gfx_driver->h : 0)
#define VIRTUAL_W (screen ? screen->w : 0)
#define VIRTUAL_H (screen ? screen->h : 0)
#define COLORCONV_NONE 0
#define COLORCONV_8_TO_15 1
#define COLORCONV_8_TO_16 2
#define COLORCONV_8_TO_24 4
#define COLORCONV_8_TO_32 8
#define COLORCONV_15_TO_8 0x10
#define COLORCONV_15_TO_16 0x20
#define COLORCONV_15_TO_24 0x40
#define COLORCONV_15_TO_32 0x80
#define COLORCONV_16_TO_8 0x100
#define COLORCONV_16_TO_15 0x200
#define COLORCONV_16_TO_24 0x400
#define COLORCONV_16_TO_32 0x800
#define COLORCONV_24_TO_8 0x1000
#define COLORCONV_24_TO_15 0x2000
#define COLORCONV_24_TO_16 0x4000
#define COLORCONV_24_TO_32 0x8000
#define COLORCONV_32_TO_8 0x10000
#define COLORCONV_32_TO_15 0x20000
#define COLORCONV_32_TO_16 0x40000
#define COLORCONV_32_TO_24 0x80000
#define COLORCONV_32A_TO_8 0x100000
#define COLORCONV_32A_TO_15 0x200000
#define COLORCONV_32A_TO_16 0x400000
#define COLORCONV_32A_TO_24 0x800000
#define COLORCONV_DITHER_PAL 0x1000000
#define COLORCONV_DITHER_HI 0x2000000
#define COLORCONV_KEEP_TRANS 0x4000000
#define COLORCONV_DITHER (COLORCONV_DITHER_PAL | \
COLORCONV_DITHER_HI)
#define COLORCONV_EXPAND_256 (COLORCONV_8_TO_15 | \
COLORCONV_8_TO_16 | \
COLORCONV_8_TO_24 | \
COLORCONV_8_TO_32)
#define COLORCONV_REDUCE_TO_256 (COLORCONV_15_TO_8 | \
COLORCONV_16_TO_8 | \
COLORCONV_24_TO_8 | \
COLORCONV_32_TO_8 | \
COLORCONV_32A_TO_8)
#define COLORCONV_EXPAND_15_TO_16 COLORCONV_15_TO_16
#define COLORCONV_REDUCE_16_TO_15 COLORCONV_16_TO_15
#define COLORCONV_EXPAND_HI_TO_TRUE (COLORCONV_15_TO_24 | \
COLORCONV_15_TO_32 | \
COLORCONV_16_TO_24 | \
COLORCONV_16_TO_32)
#define COLORCONV_REDUCE_TRUE_TO_HI (COLORCONV_24_TO_15 | \
COLORCONV_24_TO_16 | \
COLORCONV_32_TO_15 | \
COLORCONV_32_TO_16)
#define COLORCONV_24_EQUALS_32 (COLORCONV_24_TO_32 | \
COLORCONV_32_TO_24)
#define COLORCONV_TOTAL (COLORCONV_EXPAND_256 | \
COLORCONV_REDUCE_TO_256 | \
COLORCONV_EXPAND_15_TO_16 | \
COLORCONV_REDUCE_16_TO_15 | \
COLORCONV_EXPAND_HI_TO_TRUE | \
COLORCONV_REDUCE_TRUE_TO_HI | \
COLORCONV_24_EQUALS_32 | \
COLORCONV_32A_TO_15 | \
COLORCONV_32A_TO_16 | \
COLORCONV_32A_TO_24)
#define COLORCONV_PARTIAL (COLORCONV_EXPAND_15_TO_16 | \
COLORCONV_REDUCE_16_TO_15 | \
COLORCONV_24_EQUALS_32)
#define COLORCONV_MOST (COLORCONV_EXPAND_15_TO_16 | \
COLORCONV_REDUCE_16_TO_15 | \
COLORCONV_EXPAND_HI_TO_TRUE | \
COLORCONV_REDUCE_TRUE_TO_HI | \
COLORCONV_24_EQUALS_32)
#define COLORCONV_KEEP_ALPHA (COLORCONV_TOTAL \
& ~(COLORCONV_32A_TO_8 | \
COLORCONV_32A_TO_15 | \
COLORCONV_32A_TO_16 | \
COLORCONV_32A_TO_24))
AL_FUNC(void, set_color_conversion, (int mode));
AL_FUNC(int, get_color_conversion, ());
AL_FUNC(int, set_gfx_mode, (int card, int w, int h, int depth));
AL_FUNC(void, set_clip_rect, (BITMAP *bitmap, int x1, int y1, int x2, int y2));
AL_FUNC(void, get_clip_rect, (BITMAP *bitmap, int *x1, int *y1, int *x2, int *y2));
AL_FUNC(void, clear_bitmap, (BITMAP *bitmap));
AL_FUNC(void, acquire_bitmap, (BITMAP *bitmap));
AL_FUNC(void, release_bitmap, (BITMAP *bitmap));
AL_FUNC(void, draw_sprite, (BITMAP *bmp, const BITMAP *sprite, int x, int y));
AL_FUNC(void, stretch_sprite, (BITMAP *bmp, const BITMAP *sprite, int x, int y, int w, int h));
extern void clear_to_color(BITMAP *bitmap, int color);
extern int bitmap_color_depth(BITMAP *bmp);
extern int bitmap_mask_color(BITMAP *bmp);
extern void add_palette_if_needed(Graphics::ManagedSurface &surf);
extern void blit(const BITMAP *src, BITMAP *dest, int src_x, int src_y, int dst_x, int dst_y, int width, int height);
extern void masked_blit(const BITMAP *src, BITMAP *dest, int src_x, int src_y, int dst_x, int dst_y, int width, int height);
extern void stretch_blit(const BITMAP *src, BITMAP *dest, int source_x, int source_y, int source_width, int source_height,
int dest_x, int dest_y, int dest_width, int dest_height);
extern void masked_stretch_blit(const BITMAP *src, BITMAP *dest, int source_x, int source_y, int source_width, int source_height,
int dest_x, int dest_y, int dest_width, int dest_height);
extern void draw_trans_sprite(BITMAP *bmp, const BITMAP *sprite, int x, int y);
extern void draw_lit_sprite(BITMAP *bmp, const BITMAP *sprite, int x, int y, int color);
extern void draw_sprite_h_flip(BITMAP *bmp, const BITMAP *sprite, int x, int y);
extern void draw_sprite_v_flip(BITMAP *bmp, const BITMAP *sprite, int x, int y);
extern void draw_sprite_vh_flip(BITMAP *bmp, const BITMAP *sprite, int x, int y);
extern void rotate_sprite(BITMAP *bmp, const BITMAP *sprite, int x, int y, fixed angle);
extern void pivot_sprite(BITMAP *bmp, const BITMAP *sprite, int x, int y, int cx, int cy, fixed angle);
extern bool is_screen_bitmap(BITMAP *bmp);
extern bool is_video_bitmap(BITMAP *bmp);
extern bool is_linear_bitmap(BITMAP *bmp);
extern bool is_same_bitmap(BITMAP *bmp1, BITMAP *bmp2);
extern bool is_planar_bitmap(BITMAP *bmp);
extern void bmp_select(BITMAP *bmp);
extern byte *bmp_write_line(BITMAP *bmp, int line);
extern void bmp_write8(byte *addr, int color);
extern void bmp_write15(byte *addr, int color);
extern void bmp_write16(byte *addr, int color);
extern void bmp_write24(byte *addr, int color);
extern void bmp_write32(byte *addr, int color);
extern void memory_putpixel(BITMAP *bmp, int x, int y, int color);
extern void putpixel(BITMAP *bmp, int x, int y, int color);
extern void _putpixel(BITMAP *bmp, int x, int y, int color);
extern void _putpixel15(BITMAP *bmp, int x, int y, int color);
extern void _putpixel16(BITMAP *bmp, int x, int y, int color);
extern void _putpixel24(BITMAP *bmp, int x, int y, int color);
extern void _putpixel32(BITMAP *bmp, int x, int y, int color);
extern int getpixel(const BITMAP *bmp, int x, int y);
extern int _getpixel(const BITMAP *bmp, int x, int y);
extern int _getpixel15(const BITMAP *bmp, int x, int y);
extern int _getpixel16(const BITMAP *bmp, int x, int y);
extern int _getpixel24(const BITMAP *bmp, int x, int y);
extern int _getpixel32(const BITMAP *bmp, int x, int y);
extern void line(BITMAP *bmp, int x1, int y_1, int x2, int y2, int color);
extern void rect(BITMAP *bmp, int x1, int y_1, int x2, int y2, int color);
extern void rectfill(BITMAP *bmp, int x1, int y_1, int x2, int y2, int color);
extern void triangle(BITMAP *bmp, int x1, int y_1, int x2, int y2, int x3, int y3, int color);
extern void circlefill(BITMAP *bmp, int x, int y, int radius, int color);
} // namespace AGS3
#endif

View File

@@ -0,0 +1,48 @@
/* 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/>.
*
*/
#include "ags/lib/allegro/gfx.h"
#include "ags/lib/allegro/color.h"
namespace AGS3 {
/* lookup table for scaling 5 bit colors up to 8 bits */
const int _rgb_scale_5[32] = {
0, 8, 16, 24, 33, 41, 49, 57,
66, 74, 82, 90, 99, 107, 115, 123,
132, 140, 148, 156, 165, 173, 181, 189,
198, 206, 214, 222, 231, 239, 247, 255
};
/* lookup table for scaling 6 bit colors up to 8 bits */
const int _rgb_scale_6[64] = {
0, 4, 8, 12, 16, 20, 24, 28,
32, 36, 40, 44, 48, 52, 56, 60,
65, 69, 73, 77, 81, 85, 89, 93,
97, 101, 105, 109, 113, 117, 121, 125,
130, 134, 138, 142, 146, 150, 154, 158,
162, 166, 170, 174, 178, 182, 186, 190,
195, 199, 203, 207, 211, 215, 219, 223,
227, 231, 235, 239, 243, 247, 251, 255
};
} // namespace AGS3

View File

@@ -0,0 +1,277 @@
/* 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/>.
*
*/
#ifndef AGS_LIB_ALLEGRO_MATH_H
#define AGS_LIB_ALLEGRO_MATH_H
#include "ags/lib/allegro/error.h"
#include "ags/lib/allegro/fixed.h"
#include "ags/globals.h"
namespace AGS3 {
const fixed _cos_tbl[512] = {
/* precalculated fixed point (16.16) cosines for a full circle (0-255) */
65536L, 65531L, 65516L, 65492L, 65457L, 65413L, 65358L, 65294L,
65220L, 65137L, 65043L, 64940L, 64827L, 64704L, 64571L, 64429L,
64277L, 64115L, 63944L, 63763L, 63572L, 63372L, 63162L, 62943L,
62714L, 62476L, 62228L, 61971L, 61705L, 61429L, 61145L, 60851L,
60547L, 60235L, 59914L, 59583L, 59244L, 58896L, 58538L, 58172L,
57798L, 57414L, 57022L, 56621L, 56212L, 55794L, 55368L, 54934L,
54491L, 54040L, 53581L, 53114L, 52639L, 52156L, 51665L, 51166L,
50660L, 50146L, 49624L, 49095L, 48559L, 48015L, 47464L, 46906L,
46341L, 45769L, 45190L, 44604L, 44011L, 43412L, 42806L, 42194L,
41576L, 40951L, 40320L, 39683L, 39040L, 38391L, 37736L, 37076L,
36410L, 35738L, 35062L, 34380L, 33692L, 33000L, 32303L, 31600L,
30893L, 30182L, 29466L, 28745L, 28020L, 27291L, 26558L, 25821L,
25080L, 24335L, 23586L, 22834L, 22078L, 21320L, 20557L, 19792L,
19024L, 18253L, 17479L, 16703L, 15924L, 15143L, 14359L, 13573L,
12785L, 11996L, 11204L, 10411L, 9616L, 8820L, 8022L, 7224L,
6424L, 5623L, 4821L, 4019L, 3216L, 2412L, 1608L, 804L,
0L, -804L, -1608L, -2412L, -3216L, -4019L, -4821L, -5623L,
-6424L, -7224L, -8022L, -8820L, -9616L, -10411L, -11204L, -11996L,
-12785L, -13573L, -14359L, -15143L, -15924L, -16703L, -17479L, -18253L,
-19024L, -19792L, -20557L, -21320L, -22078L, -22834L, -23586L, -24335L,
-25080L, -25821L, -26558L, -27291L, -28020L, -28745L, -29466L, -30182L,
-30893L, -31600L, -32303L, -33000L, -33692L, -34380L, -35062L, -35738L,
-36410L, -37076L, -37736L, -38391L, -39040L, -39683L, -40320L, -40951L,
-41576L, -42194L, -42806L, -43412L, -44011L, -44604L, -45190L, -45769L,
-46341L, -46906L, -47464L, -48015L, -48559L, -49095L, -49624L, -50146L,
-50660L, -51166L, -51665L, -52156L, -52639L, -53114L, -53581L, -54040L,
-54491L, -54934L, -55368L, -55794L, -56212L, -56621L, -57022L, -57414L,
-57798L, -58172L, -58538L, -58896L, -59244L, -59583L, -59914L, -60235L,
-60547L, -60851L, -61145L, -61429L, -61705L, -61971L, -62228L, -62476L,
-62714L, -62943L, -63162L, -63372L, -63572L, -63763L, -63944L, -64115L,
-64277L, -64429L, -64571L, -64704L, -64827L, -64940L, -65043L, -65137L,
-65220L, -65294L, -65358L, -65413L, -65457L, -65492L, -65516L, -65531L,
-65536L, -65531L, -65516L, -65492L, -65457L, -65413L, -65358L, -65294L,
-65220L, -65137L, -65043L, -64940L, -64827L, -64704L, -64571L, -64429L,
-64277L, -64115L, -63944L, -63763L, -63572L, -63372L, -63162L, -62943L,
-62714L, -62476L, -62228L, -61971L, -61705L, -61429L, -61145L, -60851L,
-60547L, -60235L, -59914L, -59583L, -59244L, -58896L, -58538L, -58172L,
-57798L, -57414L, -57022L, -56621L, -56212L, -55794L, -55368L, -54934L,
-54491L, -54040L, -53581L, -53114L, -52639L, -52156L, -51665L, -51166L,
-50660L, -50146L, -49624L, -49095L, -48559L, -48015L, -47464L, -46906L,
-46341L, -45769L, -45190L, -44604L, -44011L, -43412L, -42806L, -42194L,
-41576L, -40951L, -40320L, -39683L, -39040L, -38391L, -37736L, -37076L,
-36410L, -35738L, -35062L, -34380L, -33692L, -33000L, -32303L, -31600L,
-30893L, -30182L, -29466L, -28745L, -28020L, -27291L, -26558L, -25821L,
-25080L, -24335L, -23586L, -22834L, -22078L, -21320L, -20557L, -19792L,
-19024L, -18253L, -17479L, -16703L, -15924L, -15143L, -14359L, -13573L,
-12785L, -11996L, -11204L, -10411L, -9616L, -8820L, -8022L, -7224L,
-6424L, -5623L, -4821L, -4019L, -3216L, -2412L, -1608L, -804L,
0L, 804L, 1608L, 2412L, 3216L, 4019L, 4821L, 5623L,
6424L, 7224L, 8022L, 8820L, 9616L, 10411L, 11204L, 11996L,
12785L, 13573L, 14359L, 15143L, 15924L, 16703L, 17479L, 18253L,
19024L, 19792L, 20557L, 21320L, 22078L, 22834L, 23586L, 24335L,
25080L, 25821L, 26558L, 27291L, 28020L, 28745L, 29466L, 30182L,
30893L, 31600L, 32303L, 33000L, 33692L, 34380L, 35062L, 35738L,
36410L, 37076L, 37736L, 38391L, 39040L, 39683L, 40320L, 40951L,
41576L, 42194L, 42806L, 43412L, 44011L, 44604L, 45190L, 45769L,
46341L, 46906L, 47464L, 48015L, 48559L, 49095L, 49624L, 50146L,
50660L, 51166L, 51665L, 52156L, 52639L, 53114L, 53581L, 54040L,
54491L, 54934L, 55368L, 55794L, 56212L, 56621L, 57022L, 57414L,
57798L, 58172L, 58538L, 58896L, 59244L, 59583L, 59914L, 60235L,
60547L, 60851L, 61145L, 61429L, 61705L, 61971L, 62228L, 62476L,
62714L, 62943L, 63162L, 63372L, 63572L, 63763L, 63944L, 64115L,
64277L, 64429L, 64571L, 64704L, 64827L, 64940L, 65043L, 65137L,
65220L, 65294L, 65358L, 65413L, 65457L, 65492L, 65516L, 65531L
};
const fixed _tan_tbl[256] = {
/* precalculated fixed point (16.16) tangents for a half circle (0-127) */
0L, 804L, 1609L, 2414L, 3220L, 4026L, 4834L, 5644L,
6455L, 7268L, 8083L, 8901L, 9721L, 10545L, 11372L, 12202L,
13036L, 13874L, 14717L, 15564L, 16416L, 17273L, 18136L, 19005L,
19880L, 20762L, 21650L, 22546L, 23449L, 24360L, 25280L, 26208L,
27146L, 28093L, 29050L, 30018L, 30996L, 31986L, 32988L, 34002L,
35030L, 36071L, 37126L, 38196L, 39281L, 40382L, 41500L, 42636L,
43790L, 44963L, 46156L, 47369L, 48605L, 49863L, 51145L, 52451L,
53784L, 55144L, 56532L, 57950L, 59398L, 60880L, 62395L, 63947L,
65536L, 67165L, 68835L, 70548L, 72308L, 74116L, 75974L, 77887L,
79856L, 81885L, 83977L, 86135L, 88365L, 90670L, 93054L, 95523L,
98082L, 100736L, 103493L, 106358L, 109340L, 112447L, 115687L, 119071L,
122609L, 126314L, 130198L, 134276L, 138564L, 143081L, 147847L, 152884L,
158218L, 163878L, 169896L, 176309L, 183161L, 190499L, 198380L, 206870L,
216043L, 225990L, 236817L, 248648L, 261634L, 275959L, 291845L, 309568L,
329472L, 351993L, 377693L, 407305L, 441808L, 482534L, 531352L, 590958L,
665398L, 761030L, 888450L, 1066730L, 1334016L, 1779314L, 2669641L, 5340086L,
-2147483647L, -5340086L, -2669641L, -1779314L, -1334016L, -1066730L, -888450L, -761030L,
-665398L, -590958L, -531352L, -482534L, -441808L, -407305L, -377693L, -351993L,
-329472L, -309568L, -291845L, -275959L, -261634L, -248648L, -236817L, -225990L,
-216043L, -206870L, -198380L, -190499L, -183161L, -176309L, -169896L, -163878L,
-158218L, -152884L, -147847L, -143081L, -138564L, -134276L, -130198L, -126314L,
-122609L, -119071L, -115687L, -112447L, -109340L, -106358L, -103493L, -100736L,
-98082L, -95523L, -93054L, -90670L, -88365L, -86135L, -83977L, -81885L,
-79856L, -77887L, -75974L, -74116L, -72308L, -70548L, -68835L, -67165L,
-65536L, -63947L, -62395L, -60880L, -59398L, -57950L, -56532L, -55144L,
-53784L, -52451L, -51145L, -49863L, -48605L, -47369L, -46156L, -44963L,
-43790L, -42636L, -41500L, -40382L, -39281L, -38196L, -37126L, -36071L,
-35030L, -34002L, -32988L, -31986L, -30996L, -30018L, -29050L, -28093L,
-27146L, -26208L, -25280L, -24360L, -23449L, -22546L, -21650L, -20762L,
-19880L, -19005L, -18136L, -17273L, -16416L, -15564L, -14717L, -13874L,
-13036L, -12202L, -11372L, -10545L, -9721L, -8901L, -8083L, -7268L,
-6455L, -5644L, -4834L, -4026L, -3220L, -2414L, -1609L, -804L
};
const fixed _acos_tbl[513] = {
/* precalculated fixed point (16.16) inverse cosines (-1 to 1) */
0x800000L, 0x7C65C7L, 0x7AE75AL, 0x79C19EL, 0x78C9BEL, 0x77EF25L, 0x772953L, 0x76733AL,
0x75C991L, 0x752A10L, 0x74930CL, 0x740345L, 0x7379C1L, 0x72F5BAL, 0x72768FL, 0x71FBBCL,
0x7184D3L, 0x711174L, 0x70A152L, 0x703426L, 0x6FC9B5L, 0x6F61C9L, 0x6EFC36L, 0x6E98D1L,
0x6E3777L, 0x6DD805L, 0x6D7A5EL, 0x6D1E68L, 0x6CC40BL, 0x6C6B2FL, 0x6C13C1L, 0x6BBDAFL,
0x6B68E6L, 0x6B1558L, 0x6AC2F5L, 0x6A71B1L, 0x6A217EL, 0x69D251L, 0x698420L, 0x6936DFL,
0x68EA85L, 0x689F0AL, 0x685465L, 0x680A8DL, 0x67C17DL, 0x67792CL, 0x673194L, 0x66EAAFL,
0x66A476L, 0x665EE5L, 0x6619F5L, 0x65D5A2L, 0x6591E7L, 0x654EBFL, 0x650C26L, 0x64CA18L,
0x648890L, 0x64478CL, 0x640706L, 0x63C6FCL, 0x63876BL, 0x63484FL, 0x6309A5L, 0x62CB6AL,
0x628D9CL, 0x625037L, 0x621339L, 0x61D69FL, 0x619A68L, 0x615E90L, 0x612316L, 0x60E7F7L,
0x60AD31L, 0x6072C3L, 0x6038A9L, 0x5FFEE3L, 0x5FC56EL, 0x5F8C49L, 0x5F5372L, 0x5F1AE7L,
0x5EE2A7L, 0x5EAAB0L, 0x5E7301L, 0x5E3B98L, 0x5E0473L, 0x5DCD92L, 0x5D96F3L, 0x5D6095L,
0x5D2A76L, 0x5CF496L, 0x5CBEF2L, 0x5C898BL, 0x5C545EL, 0x5C1F6BL, 0x5BEAB0L, 0x5BB62DL,
0x5B81E1L, 0x5B4DCAL, 0x5B19E7L, 0x5AE638L, 0x5AB2BCL, 0x5A7F72L, 0x5A4C59L, 0x5A1970L,
0x59E6B6L, 0x59B42AL, 0x5981CCL, 0x594F9BL, 0x591D96L, 0x58EBBDL, 0x58BA0EL, 0x588889L,
0x58572DL, 0x5825FAL, 0x57F4EEL, 0x57C40AL, 0x57934DL, 0x5762B5L, 0x573243L, 0x5701F5L,
0x56D1CCL, 0x56A1C6L, 0x5671E4L, 0x564224L, 0x561285L, 0x55E309L, 0x55B3ADL, 0x558471L,
0x555555L, 0x552659L, 0x54F77BL, 0x54C8BCL, 0x549A1BL, 0x546B98L, 0x543D31L, 0x540EE7L,
0x53E0B9L, 0x53B2A7L, 0x5384B0L, 0x5356D4L, 0x532912L, 0x52FB6BL, 0x52CDDDL, 0x52A068L,
0x52730CL, 0x5245C9L, 0x52189EL, 0x51EB8BL, 0x51BE8FL, 0x5191AAL, 0x5164DCL, 0x513825L,
0x510B83L, 0x50DEF7L, 0x50B280L, 0x50861FL, 0x5059D2L, 0x502D99L, 0x500175L, 0x4FD564L,
0x4FA967L, 0x4F7D7DL, 0x4F51A6L, 0x4F25E2L, 0x4EFA30L, 0x4ECE90L, 0x4EA301L, 0x4E7784L,
0x4E4C19L, 0x4E20BEL, 0x4DF574L, 0x4DCA3AL, 0x4D9F10L, 0x4D73F6L, 0x4D48ECL, 0x4D1DF1L,
0x4CF305L, 0x4CC829L, 0x4C9D5AL, 0x4C729AL, 0x4C47E9L, 0x4C1D45L, 0x4BF2AEL, 0x4BC826L,
0x4B9DAAL, 0x4B733BL, 0x4B48D9L, 0x4B1E84L, 0x4AF43BL, 0x4AC9FEL, 0x4A9FCDL, 0x4A75A7L,
0x4A4B8DL, 0x4A217EL, 0x49F77AL, 0x49CD81L, 0x49A393L, 0x4979AFL, 0x494FD5L, 0x492605L,
0x48FC3FL, 0x48D282L, 0x48A8CFL, 0x487F25L, 0x485584L, 0x482BECL, 0x48025DL, 0x47D8D6L,
0x47AF57L, 0x4785E0L, 0x475C72L, 0x47330AL, 0x4709ABL, 0x46E052L, 0x46B701L, 0x468DB7L,
0x466474L, 0x463B37L, 0x461201L, 0x45E8D0L, 0x45BFA6L, 0x459682L, 0x456D64L, 0x45444BL,
0x451B37L, 0x44F229L, 0x44C920L, 0x44A01CL, 0x44771CL, 0x444E21L, 0x44252AL, 0x43FC38L,
0x43D349L, 0x43AA5FL, 0x438178L, 0x435894L, 0x432FB4L, 0x4306D8L, 0x42DDFEL, 0x42B527L,
0x428C53L, 0x426381L, 0x423AB2L, 0x4211E5L, 0x41E91AL, 0x41C051L, 0x41978AL, 0x416EC5L,
0x414601L, 0x411D3EL, 0x40F47CL, 0x40CBBBL, 0x40A2FBL, 0x407A3CL, 0x40517DL, 0x4028BEL,
0x400000L, 0x3FD742L, 0x3FAE83L, 0x3F85C4L, 0x3F5D05L, 0x3F3445L, 0x3F0B84L, 0x3EE2C2L,
0x3EB9FFL, 0x3E913BL, 0x3E6876L, 0x3E3FAFL, 0x3E16E6L, 0x3DEE1BL, 0x3DC54EL, 0x3D9C7FL,
0x3D73ADL, 0x3D4AD9L, 0x3D2202L, 0x3CF928L, 0x3CD04CL, 0x3CA76CL, 0x3C7E88L, 0x3C55A1L,
0x3C2CB7L, 0x3C03C8L, 0x3BDAD6L, 0x3BB1DFL, 0x3B88E4L, 0x3B5FE4L, 0x3B36E0L, 0x3B0DD7L,
0x3AE4C9L, 0x3ABBB5L, 0x3A929CL, 0x3A697EL, 0x3A405AL, 0x3A1730L, 0x39EDFFL, 0x39C4C9L,
0x399B8CL, 0x397249L, 0x3948FFL, 0x391FAEL, 0x38F655L, 0x38CCF6L, 0x38A38EL, 0x387A20L,
0x3850A9L, 0x38272AL, 0x37FDA3L, 0x37D414L, 0x37AA7CL, 0x3780DBL, 0x375731L, 0x372D7EL,
0x3703C1L, 0x36D9FBL, 0x36B02BL, 0x368651L, 0x365C6DL, 0x36327FL, 0x360886L, 0x35DE82L,
0x35B473L, 0x358A59L, 0x356033L, 0x353602L, 0x350BC5L, 0x34E17CL, 0x34B727L, 0x348CC5L,
0x346256L, 0x3437DAL, 0x340D52L, 0x33E2BBL, 0x33B817L, 0x338D66L, 0x3362A6L, 0x3337D7L,
0x330CFBL, 0x32E20FL, 0x32B714L, 0x328C0AL, 0x3260F0L, 0x3235C6L, 0x320A8CL, 0x31DF42L,
0x31B3E7L, 0x31887CL, 0x315CFFL, 0x313170L, 0x3105D0L, 0x30DA1EL, 0x30AE5AL, 0x308283L,
0x305699L, 0x302A9CL, 0x2FFE8BL, 0x2FD267L, 0x2FA62EL, 0x2F79E1L, 0x2F4D80L, 0x2F2109L,
0x2EF47DL, 0x2EC7DBL, 0x2E9B24L, 0x2E6E56L, 0x2E4171L, 0x2E1475L, 0x2DE762L, 0x2DBA37L,
0x2D8CF4L, 0x2D5F98L, 0x2D3223L, 0x2D0495L, 0x2CD6EEL, 0x2CA92CL, 0x2C7B50L, 0x2C4D59L,
0x2C1F47L, 0x2BF119L, 0x2BC2CFL, 0x2B9468L, 0x2B65E5L, 0x2B3744L, 0x2B0885L, 0x2AD9A7L,
0x2AAAABL, 0x2A7B8FL, 0x2A4C53L, 0x2A1CF7L, 0x29ED7BL, 0x29BDDCL, 0x298E1CL, 0x295E3AL,
0x292E34L, 0x28FE0BL, 0x28CDBDL, 0x289D4BL, 0x286CB3L, 0x283BF6L, 0x280B12L, 0x27DA06L,
0x27A8D3L, 0x277777L, 0x2745F2L, 0x271443L, 0x26E26AL, 0x26B065L, 0x267E34L, 0x264BD6L,
0x26194AL, 0x25E690L, 0x25B3A7L, 0x25808EL, 0x254D44L, 0x2519C8L, 0x24E619L, 0x24B236L,
0x247E1FL, 0x2449D3L, 0x241550L, 0x23E095L, 0x23ABA2L, 0x237675L, 0x23410EL, 0x230B6AL,
0x22D58AL, 0x229F6BL, 0x22690DL, 0x22326EL, 0x21FB8DL, 0x21C468L, 0x218CFFL, 0x215550L,
0x211D59L, 0x20E519L, 0x20AC8EL, 0x2073B7L, 0x203A92L, 0x20011DL, 0x1FC757L, 0x1F8D3DL,
0x1F52CFL, 0x1F1809L, 0x1EDCEAL, 0x1EA170L, 0x1E6598L, 0x1E2961L, 0x1DECC7L, 0x1DAFC9L,
0x1D7264L, 0x1D3496L, 0x1CF65BL, 0x1CB7B1L, 0x1C7895L, 0x1C3904L, 0x1BF8FAL, 0x1BB874L,
0x1B7770L, 0x1B35E8L, 0x1AF3DAL, 0x1AB141L, 0x1A6E19L, 0x1A2A5EL, 0x19E60BL, 0x19A11BL,
0x195B8AL, 0x191551L, 0x18CE6CL, 0x1886D4L, 0x183E83L, 0x17F573L, 0x17AB9BL, 0x1760F6L,
0x17157BL, 0x16C921L, 0x167BE0L, 0x162DAFL, 0x15DE82L, 0x158E4FL, 0x153D0BL, 0x14EAA8L,
0x14971AL, 0x144251L, 0x13EC3FL, 0x1394D1L, 0x133BF5L, 0x12E198L, 0x1285A2L, 0x1227FBL,
0x11C889L, 0x11672FL, 0x1103CAL, 0x109E37L, 0x10364BL, 0xFCBDAL, 0xF5EAEL, 0xEEE8CL,
0xE7B2DL, 0xE0444L, 0xD8971L, 0xD0A46L, 0xC863FL, 0xBFCBBL, 0xB6CF4L, 0xAD5F0L,
0xA366FL, 0x98CC6L, 0x8D6ADL, 0x810DBL, 0x73642L, 0x63E62L, 0x518A6L, 0x39A39L,
0x0L
};
/* fixatan:
* Fixed point inverse tangent. Does a binary search on the tan table.
*/
fixed fixatan(fixed x) {
int a, b, c; /* for binary search */
fixed d; /* difference value for search */
if (x >= 0) { /* search the first part of tan table */
a = 0;
b = 127;
} else { /* search the second half instead */
a = 128;
b = 255;
}
do {
c = (a + b) >> 1;
d = x - _tan_tbl[c];
if (d > 0)
a = c + 1;
else if (d < 0)
b = c - 1;
} while ((a <= b) && (d));
if (x >= 0)
return ((long)c) << 15;
return (-0x00800000L + (((long)c) << 15));
}
/* fixatan2:
* Like the libc atan2, but for fixed point numbers.
*/
fixed fixatan2(fixed y, fixed x) {
fixed r;
if (x == 0) {
if (y == 0) {
*_G(allegro_errno) = AL_EDOM;
return 0L;
} else
return ((y < 0) ? -0x00400000L : 0x00400000L);
}
*_G(allegro_errno) = AL_NOERROR;
r = fixdiv(y, x);
if (*_G(allegro_errno)) {
*_G(allegro_errno) = AL_NOERROR;
return ((y < 0) ? -0x00400000L : 0x00400000L);
}
r = fixatan(r);
if (x >= 0)
return r;
if (y >= 0)
return 0x00800000L + r;
return r - 0x00800000L;
}
} // namespace AGS3
#endif

View File

@@ -0,0 +1,374 @@
#include "ags/lib/allegro/rotate.h"
#include "ags/lib/allegro/gfx.h"
#include "common/scummsys.h"
namespace AGS3 {
/* rotate_scale_coordinates:
* Calculates the coordinates for the rotated, scaled and flipped sprite,
* and passes them on to the given function.
*/
void rotate_scale_coordinates(fixed w, fixed h,
fixed x, fixed y, fixed cx, fixed cy,
fixed angle,
fixed scale_x, fixed scale_y,
fixed xs[4], fixed ys[4])
{
// Setting angle to the range -180...180 degrees makes sin & cos more numerically stable.
// (Yes, this does have an effect for big angles!)
// Note that using "real" sin() and cos() gives much better precision than fixsin() and fixcos().
angle = angle & 0xffffff;
if (angle >= 0x800000)
angle -= 0x1000000;
double angle_radian = angle * (M_PI / (double)0x800000);
double sin_angle = sin(angle_radian);
double cos_angle = cos(angle_radian);
fixed fix_cos, fix_sin;
if (cos_angle >= 0)
fix_cos = (int)(cos_angle * 0x10000 + 0.5);
else
fix_cos = (int)(cos_angle * 0x10000 - 0.5);
if (sin_angle >= 0)
fix_sin = (int)(sin_angle * 0x10000 + 0.5);
else
fix_sin = (int)(sin_angle * 0x10000 - 0.5);
/* Decide what order to take corners in. */
int tl = 0, tr = 1, bl = 3, br = 2;
/* Calculate new coordinates of all corners. */
w = fixmul(w, scale_x);
h = fixmul(h, scale_y);
cx = fixmul(cx, scale_x);
cy = fixmul(cy, scale_y);
fixed xofs = x - fixmul(cx, fix_cos) + fixmul(cy, fix_sin);
fixed yofs = y - fixmul(cx, fix_sin) - fixmul(cy, fix_cos);
xs[tl] = xofs;
ys[tl] = yofs;
xs[tr] = xofs + fixmul(w, fix_cos);
ys[tr] = yofs + fixmul(w, fix_sin);
xs[bl] = xofs - fixmul(h, fix_sin);
ys[bl] = yofs + fixmul(h, fix_cos);
xs[br] = xs[tr] + xs[bl] - xs[tl];
ys[br] = ys[tr] + ys[bl] - ys[tl];
}
/* parallelogram_map:
* Worker routine for drawing rotated and/or scaled and/or flipped sprites:
* It actually maps the sprite to any parallelogram-shaped area of the
* bitmap. The top left corner is mapped to (xs[0], ys[0]), the top right to
* (xs[1], ys[1]), the bottom right to x (xs[2], ys[2]), and the bottom left
* to (xs[3], ys[3]). The corners are assumed to form a perfect
* parallelogram, i.e. xs[0]+xs[2] = xs[1]+xs[3]. The corners are given in
* fixed point format, so xs[] and ys[] are coordinates of the outer corners
* of corner pixels in clockwise order beginning with top left.
* All coordinates begin with 0 in top left corner of pixel (0, 0). So a
* rotation by 0 degrees of a sprite to the top left of a bitmap can be
* specified with coordinates (0, 0) for the top left pixel in source
* bitmap. With the default scanline drawer, a pixel in the destination
* bitmap is drawn if and only if its center is covered by any pixel in the
* sprite. The color of this covering sprite pixel is used to draw.
*/
void parallelogram_map(BITMAP *bmp, const BITMAP *spr, fixed xs[4], fixed ys[4]) {
// Get index of topmost point.
int top_index = 0;
if (ys[1] < ys[0])
top_index = 1;
if (ys[2] < ys[top_index])
top_index = 2;
if (ys[3] < ys[top_index])
top_index = 3;
// Get direction of points: clockwise or anti-clockwise.
int right_index = (double)(xs[(top_index+1) & 3] - xs[top_index]) *
(double)(ys[(top_index-1) & 3] - ys[top_index]) >
(double)(xs[(top_index-1) & 3] - xs[top_index]) *
(double)(ys[(top_index+1) & 3] - ys[top_index]) ? 1 : -1;
// Get coordinates of the corners.
// Coordinates in bmp and sprite ordered as top-right-bottom-left.
fixed corner_bmp_x[4], corner_bmp_y[4];
fixed corner_spr_x[4], corner_spr_y[4];
int index = top_index;
for (int i = 0; i < 4; i++) {
corner_bmp_x[i] = xs[index];
corner_bmp_y[i] = ys[index];
if (index < 2)
corner_spr_y[i] = 0;
else
// Need `- 1' since otherwise it would be outside sprite.
corner_spr_y[i] = (spr->h << 16) - 1;
if ((index == 0) || (index == 3))
corner_spr_x[i] = 0;
else
corner_spr_x[i] = (spr->w << 16) - 1;
index = (index + right_index) & 3;
}
// Get scanline starts, ends and deltas, and clipping coordinates.
#define top_bmp_y corner_bmp_y[0]
#define right_bmp_y corner_bmp_y[1]
#define bottom_bmp_y corner_bmp_y[2]
#define left_bmp_y corner_bmp_y[3]
#define top_bmp_x corner_bmp_x[0]
#define right_bmp_x corner_bmp_x[1]
#define bottom_bmp_x corner_bmp_x[2]
#define left_bmp_x corner_bmp_x[3]
#define top_spr_y corner_spr_y[0]
#define right_spr_y corner_spr_y[1]
#define bottom_spr_y corner_spr_y[2]
#define left_spr_y corner_spr_y[3]
#define top_spr_x corner_spr_x[0]
#define right_spr_x corner_spr_x[1]
#define bottom_spr_x corner_spr_x[2]
#define left_spr_x corner_spr_x[3]
// Calculate left and right clipping.
fixed clip_left, clip_right;
if (bmp->clip) {
clip_left = bmp->cl << 16;
clip_right = (bmp->cr << 16) - 1;
} else {
clip_left = 0;
clip_right = (bmp->w << 16) - 1;
}
// Stop if we're totally outside.
if ((left_bmp_x > clip_right) && (top_bmp_x > clip_right) && (bottom_bmp_x > clip_right))
return;
if ((right_bmp_x < clip_left) && (top_bmp_x < clip_left) && (bottom_bmp_x < clip_left))
return;
// Bottom clipping.
int clip_bottom_i = (bottom_bmp_y + 0x8000) >> 16;
if (bmp->clip) {
if (clip_bottom_i > bmp->cb)
clip_bottom_i = bmp->cb;
}
// Calculate y coordinate of first scanline.
int bmp_y_i = (top_bmp_y + 0x8000) >> 16;
if (bmp->clip) {
if (bmp_y_i < bmp->ct)
bmp_y_i = bmp->ct;
}
// Sprite is above or below bottom clipping area.
if (bmp_y_i >= clip_bottom_i)
return;
// Vertical gap between top corner and centre of topmost scanline.
fixed extra_scanline_fraction = (bmp_y_i << 16) + 0x8000 - top_bmp_y;
// Calculate x coordinate of beginning of scanline in bmp.
fixed l_bmp_dx = fixdiv(left_bmp_x - top_bmp_x, left_bmp_y - top_bmp_y);
fixed l_bmp_x = top_bmp_x + fixmul(extra_scanline_fraction, l_bmp_dx);
// Calculate x coordinate of beginning of scanline in spr.
// note: all these are rounded down which is probably a Good Thing (tm)
fixed l_spr_dx = fixdiv(left_spr_x - top_spr_x, left_bmp_y - top_bmp_y);
fixed l_spr_x = top_spr_x + fixmul(extra_scanline_fraction, l_spr_dx);
// Calculate y coordinate of beginning of scanline in spr.
fixed l_spr_dy = fixdiv(left_spr_y - top_spr_y, left_bmp_y - top_bmp_y);
fixed l_spr_y = top_spr_y + fixmul(extra_scanline_fraction, l_spr_dy);
// Calculate left loop bound.
int l_bmp_y_bottom_i = (left_bmp_y + 0x8000) >> 16;
if (l_bmp_y_bottom_i > clip_bottom_i)
l_bmp_y_bottom_i = clip_bottom_i;
// Calculate x coordinate of end of scanline in bmp.
fixed r_bmp_dx = fixdiv(right_bmp_x - top_bmp_x, right_bmp_y - top_bmp_y);
fixed r_bmp_x = top_bmp_x + fixmul(extra_scanline_fraction, r_bmp_dx);
// Calculate right loop bound.
int r_bmp_y_bottom_i = (right_bmp_y + 0x8000) >> 16;
// Get dx and dy, the offsets to add to the source coordinates as we move
// one pixel rightwards along a scanline. This formula can be derived by
// considering the 2x2 matrix that transforms the sprite to the
// parallelogram.
// We'd better use double to get this as exact as possible, since any
// errors will be accumulated along the scanline.
fixed spr_dx = (fixed)((ys[3] - ys[0]) * 65536.0 * (65536.0 * spr->w) /
((xs[1] - xs[0]) * (double)(ys[3] - ys[0]) - (xs[3] - xs[0]) * (double)(ys[1] - ys[0])));
fixed spr_dy = (fixed)((ys[1] - ys[0]) * 65536.0 * (65536.0 * spr->h) /
((xs[3] - xs[0]) * (double)(ys[1] - ys[0]) - (xs[1] - xs[0]) * (double)(ys[3] - ys[0])));
bool sameFormat = (spr->format == bmp->format);
uint32 transColor = 0, alphaMask = 0xff;
if (spr->format.bytesPerPixel != 1) {
transColor = spr->format.ARGBToColor(0, 255, 0, 255);
alphaMask = spr->format.ARGBToColor(255, 0, 0, 0);
alphaMask = ~alphaMask;
}
// Loop through scanlines.
while (1) {
// Has beginning of scanline passed a corner?
if (bmp_y_i >= l_bmp_y_bottom_i) {
// Are we done?
if (bmp_y_i >= clip_bottom_i)
break;
// Vertical gap between left corner and centre of scanline.
extra_scanline_fraction = (bmp_y_i << 16) + 0x8000 - left_bmp_y;
// Update x coordinate of beginning of scanline in bmp.
l_bmp_dx = fixdiv(bottom_bmp_x - left_bmp_x, bottom_bmp_y - left_bmp_y);
l_bmp_x = left_bmp_x + fixmul(extra_scanline_fraction, l_bmp_dx);
// Update x coordinate of beginning of scanline in spr.
l_spr_dx = fixdiv(bottom_spr_x - left_spr_x, bottom_bmp_y - left_bmp_y);
l_spr_x = left_spr_x + fixmul(extra_scanline_fraction, l_spr_dx);
// Update y coordinate of beginning of scanline in spr.
l_spr_dy = fixdiv(bottom_spr_y - left_spr_y, bottom_bmp_y - left_bmp_y);
l_spr_y = left_spr_y + fixmul(extra_scanline_fraction, l_spr_dy);
// Update loop bound.
l_bmp_y_bottom_i = (bottom_bmp_y + 0x8000) >> 16;
if (l_bmp_y_bottom_i > clip_bottom_i)
l_bmp_y_bottom_i = clip_bottom_i;
}
// Has end of scanline passed a corner?
if (bmp_y_i >= r_bmp_y_bottom_i) {
// Vertical gap between right corner and centre of scanline.
extra_scanline_fraction = (bmp_y_i << 16) + 0x8000 - right_bmp_y;
// Update x coordinate of end of scanline in bmp.
r_bmp_dx = fixdiv(bottom_bmp_x - right_bmp_x, bottom_bmp_y - right_bmp_y);
r_bmp_x = right_bmp_x + fixmul(extra_scanline_fraction, r_bmp_dx);
// Update loop bound: We aren't supposed to use this any more, so
// just set it to some big enough value.
r_bmp_y_bottom_i = clip_bottom_i;
}
// Make left bmp coordinate be an integer and clip it.
fixed l_bmp_x_rounded;
l_bmp_x_rounded = (l_bmp_x + 0x8000) & ~0xffff;
if (l_bmp_x_rounded < clip_left)
l_bmp_x_rounded = clip_left;
// ... and move starting point in sprite accordingly.
fixed l_spr_x_rounded = l_spr_x + fixmul(l_bmp_x_rounded + 0x7fff - l_bmp_x, spr_dx);
fixed l_spr_y_rounded = l_spr_y + fixmul(l_bmp_x_rounded + 0x7fff - l_bmp_x, spr_dy);
// Make right bmp coordinate be an integer and clip it.
fixed r_bmp_x_rounded = (r_bmp_x - 0x8000) & ~0xffff;
if (r_bmp_x_rounded > clip_right)
r_bmp_x_rounded = clip_right;
// Draw!
if (l_bmp_x_rounded <= r_bmp_x_rounded) {
/* The bodies of these ifs are only reached extremely seldom,
it's an ugly hack to avoid reading outside the sprite when
the rounding errors are accumulated the wrong way. It would
be nicer if we could ensure that this never happens by making
all multiplications and divisions be rounded up or down at
the correct places.
I did try another approach: recalculate the edges of the
scanline from scratch each scanline rather than incrementally.
Drawing a sprite with that routine took about 25% longer time
though.
*/
if ((unsigned)(l_spr_x_rounded >> 16) >= (unsigned)spr->w) {
if (((l_spr_x_rounded < 0) && (spr_dx <= 0)) || ((l_spr_x_rounded > 0) && (spr_dx >= 0))) {
// This can happen.
goto skip_draw;
} else {
// I don't think this can happen, but I can't prove it.
do {
l_spr_x_rounded += spr_dx;
l_bmp_x_rounded += 65536;
if (l_bmp_x_rounded > r_bmp_x_rounded)
goto skip_draw;
} while ((unsigned)(l_spr_x_rounded >> 16) >= (unsigned)spr->w);
}
}
int right_edge_test = l_spr_x_rounded + ((r_bmp_x_rounded - l_bmp_x_rounded) >> 16) * spr_dx;
if ((unsigned)(right_edge_test >> 16) >= (unsigned)spr->w) {
if (((right_edge_test < 0) && (spr_dx <= 0)) || ((right_edge_test > 0) && (spr_dx >= 0))) {
// This can happen.
do {
r_bmp_x_rounded -= 65536;
right_edge_test -= spr_dx;
if (l_bmp_x_rounded > r_bmp_x_rounded)
goto skip_draw;
} while ((unsigned)(right_edge_test >> 16) >= (unsigned)spr->w);
} else {
// I don't think this can happen, but I can't prove it.
goto skip_draw;
}
}
if ((unsigned)(l_spr_y_rounded >> 16) >= (unsigned)spr->h) {
if (((l_spr_y_rounded < 0) && (spr_dy <= 0)) || ((l_spr_y_rounded > 0) && (spr_dy >= 0))) {
// This can happen.
goto skip_draw;
} else {
// I don't think this can happen, but I can't prove it.
do {
l_spr_y_rounded += spr_dy;
l_bmp_x_rounded += 65536;
if (l_bmp_x_rounded > r_bmp_x_rounded)
goto skip_draw;
} while (((unsigned)l_spr_y_rounded >> 16) >= (unsigned)spr->h);
}
}
right_edge_test = l_spr_y_rounded + ((r_bmp_x_rounded - l_bmp_x_rounded) >> 16) * spr_dy;
if ((unsigned)(right_edge_test >> 16) >= (unsigned)spr->h) {
if (((right_edge_test < 0) && (spr_dy <= 0)) || ((right_edge_test > 0) && (spr_dy >= 0))) {
// This can happen.
do {
r_bmp_x_rounded -= 65536;
right_edge_test -= spr_dy;
if (l_bmp_x_rounded > r_bmp_x_rounded)
goto skip_draw;
} while ((unsigned)(right_edge_test >> 16) >= (unsigned)spr->h);
} else {
// I don't think this can happen, but I can't prove it.
goto skip_draw;
}
}
// draw scanline
int r_bmp_x_i = (r_bmp_x_rounded >> 16);
int l_bmp_x_i = (l_bmp_x_rounded >> 16);
for (; l_bmp_x_i <= r_bmp_x_i; ++l_bmp_x_i) {
uint32 c = (uint32)getpixel(spr, l_spr_x_rounded >> 16, l_spr_y_rounded >> 16);
if ((c & alphaMask) != transColor) {
if (!sameFormat) {
uint8 a, r, g, b;
spr->format.colorToARGB(c, a, r, g, b);
c = bmp->format.ARGBToColor(a, r, g, b);
}
putpixel(bmp, l_bmp_x_i, bmp_y_i, c);
}
l_spr_x_rounded += spr_dx;
l_spr_y_rounded += spr_dy;
}
}
// I'm not going to apoligize for this label and its gotos.
// to get rid of it would just make the code look worse.
skip_draw:
// Jump to next scanline.
bmp_y_i++;
// Update beginning of scanline.
l_bmp_x += l_bmp_dx;
l_spr_x += l_spr_dx;
l_spr_y += l_spr_dy;
// Update end of scanline.
r_bmp_x += r_bmp_dx;
}
}
void pivot_scaled_sprite(BITMAP *bmp, const BITMAP *sprite, fixed x, fixed y, fixed cx, fixed cy, fixed angle, fixed scale) {
fixed xs[4], ys[4];
rotate_scale_coordinates(sprite->w << 16, sprite->h << 16,
x, y, cx, cy, angle, scale, scale, xs, ys);
parallelogram_map(bmp, sprite, xs, ys);
}
} // namespace AGS3

View File

@@ -0,0 +1,35 @@
/* 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/>.
*
*/
#ifndef AGS_LIB_ALLEGRO_ROTATE_H
#define AGS_LIB_ALLEGRO_ROTATE_H
#include "ags/lib/allegro/surface.h"
#include "ags/lib/allegro/fixed.h"
namespace AGS3 {
extern void pivot_scaled_sprite(BITMAP *bmp, const BITMAP *sprite, fixed x, fixed y, fixed cx, fixed cy, fixed angle, fixed scale);
} // namespace AGS3
#endif

View File

@@ -0,0 +1,398 @@
/* 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/>.
*
*/
#include "ags/lib/allegro/gfx.h"
#include "ags/lib/allegro/color.h"
#include "ags/lib/allegro/flood.h"
#include "ags/ags.h"
#include "ags/globals.h"
#include "common/textconsole.h"
#include "graphics/screen.h"
namespace AGS3 {
BITMAP::BITMAP(Graphics::ManagedSurface *owner) : _owner(owner),
w(owner->w), h(owner->h), pitch(owner->pitch), format(owner->format),
clip(true), ct(0), cl(0), cr(owner->w), cb(owner->h) {
line.resize(h);
for (int y = 0; y < h; ++y)
line[y] = (byte *)_owner->getBasePtr(0, y);
}
int BITMAP::getpixel(int x, int y) const {
if (x < 0 || y < 0 || x >= w || y >= h)
return -1;
const byte *pixel = (const byte *)getBasePtr(x, y);
if (format.bytesPerPixel == 1)
return *pixel;
else if (format.bytesPerPixel == 2)
return *(const uint16 *)pixel;
else
return *(const uint32 *)pixel;
}
void BITMAP::makeOpaque() {
if (format.aBits() == 0)
return;
assert(format.bytesPerPixel == 4);
uint32 alphaMask = format.ARGBToColor(0xff, 0, 0, 0);
unsigned char *pixels = getPixels();
for (int y = 0 ; y < h ; ++y, pixels += pitch) {
uint32 *data = (uint32 *)pixels;
for (int x = 0 ; x < w ; ++x, ++data)
(*data) |= alphaMask;
}
}
void BITMAP::circlefill(int x, int y, int radius, int color) {
int cx = 0;
int cy = radius;
int df = 1 - radius;
int d_e = 3;
int d_se = -2 * radius + 5;
do {
_owner->hLine(x - cy, y - cx, x + cy, color);
if (cx)
_owner->hLine(x - cy, y + cx, x + cy, color);
if (df < 0) {
df += d_e;
d_e += 2;
d_se += 2;
} else {
if (cx != cy) {
_owner->hLine(x - cx, y - cy, x + cx, color);
if (cy)
_owner->hLine(x - cx, y + cy, x + cx, color);
}
df += d_se;
d_e += 2;
d_se += 4;
cy--;
}
cx++;
} while (cx <= cy);
}
void BITMAP::floodfill(int x, int y, int color) {
AGS3::floodfill(this, x, y, color);
}
#define VGA_COLOR_TRANS(x) ((x) * 255 / 63)
BITMAP::DrawInnerArgs::DrawInnerArgs(BITMAP *_dstBitmap, const BITMAP *srcBitmap,
const Common::Rect &srcRect, const Common::Rect &_dstRect, bool _skipTrans,
int _srcAlpha, bool _horizFlip, bool _vertFlip, int _tintRed,
int _tintGreen, int _tintBlue, bool doScale) : skipTrans(_skipTrans),
srcAlpha(_srcAlpha), horizFlip(_horizFlip), vertFlip(_vertFlip),
tintRed(_tintRed), tintGreen(_tintGreen), tintBlue(_tintBlue),
src(**srcBitmap), shouldDraw(false), dstBitmap(*_dstBitmap),
useTint(_tintRed >= 0 && _tintGreen >= 0 && _tintBlue >= 0),
blenderMode(_G(_blender_mode)), dstRect(_dstRect) {
// Allegro disables draw when the clipping rect has negative width/height.
// Common::Rect instead asserts, which we don't want.
if (dstBitmap.cr <= dstBitmap.cl || dstBitmap.cb <= dstBitmap.ct)
return;
// Figure out the dest area that will be updated
srcArea = srcRect;
srcArea.clip(Common::Rect(0, 0, srcBitmap->w, srcBitmap->h));
if (srcArea.isEmpty())
return;
if (!doScale) {
// Ensure the src rect is constrained to the source bitmap
dstRect.setWidth(srcArea.width());
dstRect.setHeight(srcArea.height());
}
Common::Rect destRect = dstRect.findIntersectingRect(
Common::Rect(dstBitmap.cl, dstBitmap.ct, dstBitmap.cr, dstBitmap.cb));
if (destRect.isEmpty())
// Area is entirely outside the clipping area, so nothing to draw
return;
// Get source and dest surface. Note that for the destination we create
// a temporary sub-surface based on the allowed clipping area
Graphics::ManagedSurface &dest = *dstBitmap._owner;
destArea = dest.getSubArea(destRect);
// Define scaling and other stuff used by the drawing loops
scaleX = SCALE_THRESHOLD * srcRect.width() / dstRect.width();
scaleY = SCALE_THRESHOLD * srcRect.height() / dstRect.height();
sameFormat = (src.format == dstBitmap.format);
if (src.format.bytesPerPixel == 1 && dstBitmap.format.bytesPerPixel != 1) {
for (int i = 0; i < PAL_SIZE; ++i) {
palette[i].r = VGA_COLOR_TRANS(_G(current_palette)[i].r);
palette[i].g = VGA_COLOR_TRANS(_G(current_palette)[i].g);
palette[i].b = VGA_COLOR_TRANS(_G(current_palette)[i].b);
}
}
transColor = 0, alphaMask = 0xff;
if (skipTrans && src.format.bytesPerPixel != 1) {
transColor = src.format.ARGBToColor(0, 255, 0, 255);
alphaMask = src.format.ARGBToColor(255, 0, 0, 0);
alphaMask = ~alphaMask;
}
xStart = (dstRect.left < destRect.left) ? dstRect.left - destRect.left : 0;
yStart = (dstRect.top < destRect.top) ? dstRect.top - destRect.top : 0;
shouldDraw = true;
}
void BITMAP::draw(const BITMAP *srcBitmap, const Common::Rect &srcRect,
int dstX, int dstY, bool horizFlip, bool vertFlip,
bool skipTrans, int srcAlpha, int tintRed, int tintGreen,
int tintBlue) {
// A restricted number of 8bit games (e.g. Snow Problem) contain (leftover?) 32bit resources.
// We can ignore these to prevent conversion on load (and triggering the assertion)
if (format.bytesPerPixel == 1 && srcBitmap->format.bytesPerPixel != 1) {
warning("Attempt to draw >1BPP surface onto 1BPP surface, ignoring");
return;
}
assert(format.bytesPerPixel == 2 || format.bytesPerPixel == 4 ||
(format.bytesPerPixel == 1 && srcBitmap->format.bytesPerPixel == 1));
Graphics::ManagedSurface flipped;
if (horizFlip || vertFlip) {
// Horizontal flipping produces errors in the optimized paths, while vertical
// may result in crashes. For now, we pre-flip to a temporary surface
Graphics::ManagedSurface cropped(const_cast<BITMAP *>(srcBitmap)->getSurface(), srcRect);
flipped.copyFrom(cropped);
if (horizFlip) {
flipped.surfacePtr()->flipHorizontal(flipped.getBounds());
}
if (vertFlip) {
flipped.surfacePtr()->flipVertical(flipped.getBounds());
}
}
BITMAP temp(&flipped);
auto args = DrawInnerArgs(this, (horizFlip || vertFlip) ? &temp : srcBitmap, (horizFlip || vertFlip) ? flipped.getBounds() : srcRect, Common::Rect(dstX, dstY, dstX + 1, dstY + 1), skipTrans, srcAlpha, false, false, tintRed, tintGreen, tintBlue, false);
if (!args.shouldDraw) return;
if (!args.sameFormat && args.src.format.bytesPerPixel == 1) {
if (format.bytesPerPixel == 4)
drawInnerGeneric<4, 1, false>(args);
else
drawInnerGeneric<2, 1, false>(args);
return;
}
#ifdef SCUMMVM_NEON
if (_G(simd_flags) & AGS3::Globals::SIMD_NEON) {
drawNEON<false>(args);
return;
}
#endif
#ifdef SCUMMVM_AVX2
if (_G(simd_flags) & AGS3::Globals::SIMD_AVX2) {
drawAVX2<false>(args);
return;
}
#endif
#ifdef SCUMMVM_SSE2
if (_G(simd_flags) & AGS3::Globals::SIMD_SSE2) {
drawSSE2<false>(args);
return;
}
#endif
drawGeneric<false>(args);
}
void BITMAP::stretchDraw(const BITMAP *srcBitmap, const Common::Rect &srcRect,
const Common::Rect &dstRect, bool skipTrans, int srcAlpha) {
assert(format.bytesPerPixel == 2 || format.bytesPerPixel == 4 ||
(format.bytesPerPixel == 1 && srcBitmap->format.bytesPerPixel == 1));
auto args = DrawInnerArgs(this, srcBitmap, srcRect, dstRect, skipTrans, srcAlpha, false, false, -1, -1, -1, true);
if (!args.shouldDraw) return;
if (!args.sameFormat && args.src.format.bytesPerPixel == 1) {
if (format.bytesPerPixel == 4)
drawInnerGeneric<4, 1, true>(args);
else
drawInnerGeneric<2, 1, true>(args);
return;
}
// Stretching at the same time as blitting produces errors when
// using the optimized paths; for now, we pre-stretch to a temporary surface
Graphics::ManagedSurface cropped(const_cast<BITMAP *>(srcBitmap)->getSurface(), srcRect);
// We need to use Surface::scale, since ManagedSurface _always_ respects the source alpha, and thus skips transparent pixels
Graphics::ManagedSurface *stretched = cropped.scale(dstRect.width(), dstRect.height());
BITMAP temp(stretched);
auto optimizedArgs = DrawInnerArgs(this, &temp, stretched->getBounds(), dstRect, skipTrans, srcAlpha, false, false, -1, -1, -1, false);
#ifdef SCUMMVM_NEON
if (_G(simd_flags) & AGS3::Globals::SIMD_NEON) {
drawNEON<false>(optimizedArgs);
} else
#endif
#ifdef SCUMMVM_AVX2
if (_G(simd_flags) & AGS3::Globals::SIMD_AVX2) {
drawAVX2<false>(optimizedArgs);
} else
#endif
#ifdef SCUMMVM_SSE2
if (_G(simd_flags) & AGS3::Globals::SIMD_SSE2) {
drawSSE2<false>(optimizedArgs);
} else
#endif
{
drawGeneric<true>(optimizedArgs);
}
delete stretched;
}
void BITMAP::blendPixel(uint8 aSrc, uint8 rSrc, uint8 gSrc, uint8 bSrc, uint8 &aDest, uint8 &rDest, uint8 &gDest, uint8 &bDest, uint32 alpha, bool useTint, byte *destVal) const {
switch (_G(_blender_mode)) {
case kSourceAlphaBlender:
if (!useTint) format.colorToARGB(getColor(destVal, format.bytesPerPixel), aDest, rDest, gDest, bDest);
blendSourceAlpha(aSrc, rSrc, gSrc, bSrc, aDest, rDest, gDest, bDest, alpha);
break;
case kArgbToArgbBlender:
if (!useTint) format.colorToARGB(getColor(destVal, format.bytesPerPixel), aDest, rDest, gDest, bDest);
blendArgbToArgb(aSrc, rSrc, gSrc, bSrc, aDest, rDest, gDest, bDest, alpha);
break;
case kArgbToRgbBlender:
if (!useTint) format.colorToARGB(getColor(destVal, format.bytesPerPixel), aDest, rDest, gDest, bDest);
blendArgbToRgb(aSrc, rSrc, gSrc, bSrc, aDest, rDest, gDest, bDest, alpha);
break;
case kRgbToArgbBlender:
if (!useTint) format.colorToARGB(getColor(destVal, format.bytesPerPixel), aDest, rDest, gDest, bDest);
blendRgbToArgb(aSrc, rSrc, gSrc, bSrc, aDest, rDest, gDest, bDest, alpha);
break;
case kRgbToRgbBlender:
if (!useTint) format.colorToARGB(getColor(destVal, format.bytesPerPixel), aDest, rDest, gDest, bDest);
blendRgbToRgb(aSrc, rSrc, gSrc, bSrc, aDest, rDest, gDest, bDest, alpha);
break;
case kAlphaPreservedBlenderMode:
if (!useTint) format.colorToARGB(getColor(destVal, format.bytesPerPixel), aDest, rDest, gDest, bDest);
blendPreserveAlpha(aSrc, rSrc, gSrc, bSrc, aDest, rDest, gDest, bDest, alpha);
break;
case kOpaqueBlenderMode:
blendOpaque(aSrc, rSrc, gSrc, bSrc, aDest, rDest, gDest, bDest, alpha);
break;
case kAdditiveBlenderMode:
if (!useTint) format.colorToARGB(getColor(destVal, format.bytesPerPixel), aDest, rDest, gDest, bDest);
blendAdditiveAlpha(aSrc, rSrc, gSrc, bSrc, aDest, rDest, gDest, bDest, alpha);
break;
case kTintBlenderMode:
blendTintSprite(aSrc, rSrc, gSrc, bSrc, aDest, rDest, gDest, bDest, alpha, false);
break;
case kTintLightBlenderMode:
blendTintSprite(aSrc, rSrc, gSrc, bSrc, aDest, rDest, gDest, bDest, alpha, true);
break;
}
}
void BITMAP::blendTintSprite(uint8 aSrc, uint8 rSrc, uint8 gSrc, uint8 bSrc, uint8 &aDest, uint8 &rDest, uint8 &gDest, uint8 &bDest, uint32 alpha, bool light) const {
// Used from draw_lit_sprite after set_blender_mode(kTintBlenderMode or kTintLightBlenderMode)
// Original blender function: _myblender_color32 and _myblender_color32_light
float xh, xs, xv;
float yh, ys, yv;
int r, g, b;
rgb_to_hsv(rSrc, gSrc, bSrc, &xh, &xs, &xv);
rgb_to_hsv(rDest, gDest, bDest, &yh, &ys, &yv);
if (light) {
// adjust luminance
// (I think the writer meant value, since they are using hsV)
yv -= (1.0 - ((float)alpha / 250.0));
if (yv < 0.0)
yv = 0.0;
}
hsv_to_rgb(xh, xs, yv, &r, &g, &b);
rDest = static_cast<uint8>(r & 0xff);
gDest = static_cast<uint8>(g & 0xff);
bDest = static_cast<uint8>(b & 0xff);
// Preserve value in aDest
}
/*-------------------------------------------------------------------*/
/**
* Dervied screen surface
*/
class Screen : public Graphics::Screen, public BITMAP {
public:
Screen() : Graphics::Screen(), BITMAP(this) {}
Screen(int width, int height) : Graphics::Screen(width, height), BITMAP(this) {}
Screen(int width, int height, const Graphics::PixelFormat &pixelFormat) :
Graphics::Screen(width, height, pixelFormat), BITMAP(this) {}
~Screen() override {}
};
/*-------------------------------------------------------------------*/
BITMAP *create_bitmap(int width, int height) {
return create_bitmap_ex(get_color_depth(), width, height);
}
BITMAP *create_bitmap_ex(int color_depth, int width, int height) {
Graphics::PixelFormat format;
switch (color_depth) {
case 8:
format = Graphics::PixelFormat::createFormatCLUT8();
break;
case 16:
format = Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
break;
case 32:
format = Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24);
break;
default:
error("Invalid color depth");
}
width = MAX(width, 0);
height = MAX(height, 0);
BITMAP *bitmap = new Surface(width, height, format);
return bitmap;
}
BITMAP *create_sub_bitmap(BITMAP *parent, int x, int y, int width, int height) {
Graphics::ManagedSurface &surf = **parent;
return new Surface(surf, Common::Rect(x, y, x + width, y + height));
}
BITMAP *create_video_bitmap(int width, int height) {
return new Screen(width, height);
}
BITMAP *create_system_bitmap(int width, int height) {
return create_bitmap(width, height);
}
void destroy_bitmap(BITMAP *bitmap) {
delete bitmap;
}
} // namespace AGS3

View File

@@ -0,0 +1,356 @@
/* 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/>.
*
*/
#ifndef AGS_LIB_ALLEGRO_SURFACE_H
#define AGS_LIB_ALLEGRO_SURFACE_H
#include "graphics/managed_surface.h"
#include "ags/lib/allegro/base.h"
#include "ags/lib/allegro/color.h"
#include "common/array.h"
namespace AGS3 {
class BITMAP {
private:
Graphics::ManagedSurface *_owner;
public:
int16 &w, &h;
int32 &pitch;
Graphics::PixelFormat &format;
bool clip;
int ct, cb, cl, cr;
Common::Array<byte *> line;
public:
BITMAP(Graphics::ManagedSurface *owner);
virtual ~BITMAP() {
}
Graphics::ManagedSurface &operator*() const {
return *_owner;
}
Graphics::ManagedSurface &getSurface() {
return *_owner;
}
const Graphics::ManagedSurface &getSurface() const {
return *_owner;
}
unsigned char *getPixels() const {
return (unsigned char *)_owner->getPixels();
}
unsigned char *getBasePtr(uint16 x, uint16 y) const {
return (unsigned char *)_owner->getBasePtr(x, y);
}
uint getTransparentColor() const {
// See allegro bitmap_mask_color
// For paletted sprites this is 0.
// For other color depths this is bright pink (RGB 255, 0, 255) with alpha set to 0.
if (format.bytesPerPixel == 1)
return 0;
return format.ARGBToColor(0, 255, 0, 255);
}
inline const Common::Point getOffsetFromOwner() const {
return _owner->getOffsetFromOwner();
}
int getpixel(int x, int y) const;
void clear() {
_owner->clear();
}
void makeOpaque();
/**
* Draws a solid filled in circle
*/
void circlefill(int x, int y, int radius, int color);
/**
* Fills an enclosed area starting at a given point
*/
void floodfill(int x, int y, int color);
/**
* Draw a horizontal line
*/
void hLine(int x, int y, int x2, uint32 color) {
_owner->hLine(x, y, x2, color);
}
/**
* Draw a vertical line.
*/
void vLine(int x, int y, int y2, uint32 color) {
_owner->vLine(x, y, y2, color);
}
/**
* Draws the passed surface onto this one
*/
void draw(const BITMAP *srcBitmap, const Common::Rect &srcRect,
int dstX, int dstY, bool horizFlip, bool vertFlip,
bool skipTrans, int srcAlpha, int tintRed = -1, int tintGreen = -1,
int tintBlue = -1);
/**
* Stretches and draws the passed surface onto this one
*/
void stretchDraw(const BITMAP *srcBitmap, const Common::Rect &srcRect,
const Common::Rect &destRect, bool skipTrans, int srcAlpha);
inline bool isSubBitmap() const {
return _owner->disposeAfterUse() == DisposeAfterUse::NO;
}
private:
// True color blender functions
// In Allegro all the blender functions are of the form
// unsigned int blender_func(unsigned long x, unsigned long y, unsigned long n)
// when x is the sprite color, y the destination color, and n an alpha value
void blendPixel(uint8 aSrc, uint8 rSrc, uint8 gSrc, uint8 bSrc, uint8 &aDest, uint8 &rDest, uint8 &gDest, uint8 &bDest, uint32 alpha, bool useTint, byte *destVal) const;
inline void rgbBlend(uint8 rSrc, uint8 gSrc, uint8 bSrc, uint8 &rDest, uint8 &gDest, uint8 &bDest, uint32 alpha) const {
// Note: the original's handling varies slightly for R & B vs G.
// We need to exactly replicate it to ensure Lamplight City's
// calendar puzzle works correctly
if (alpha)
alpha++;
uint32 x = ((uint32)rSrc << 16) | ((uint32)gSrc << 8) | (uint32)bSrc;
uint32 y = ((uint32)rDest << 16) | ((uint32)gDest << 8) | (uint32)bDest;
uint32 res = ((x & 0xFF00FF) - (y & 0xFF00FF)) * alpha / 256 + y;
y &= 0xFF00;
x &= 0xFF00;
uint32 g = (x - y) * alpha / 256 + y;
rDest = (res >> 16) & 0xff;
gDest = (g >> 8) & 0xff;
bDest = res & 0xff;
}
inline void argbBlend(uint32 aSrc, uint8 rSrc, uint8 gSrc, uint8 bSrc, uint8 &aDest, uint8 &rDest, uint8 &gDest, uint8 &bDest) const {
// Original logic has uint32 src and dst colors as ARGB8888
// ++src_alpha;
// uint32 dst_alpha = geta32(dst);
// if (dst_alpha)
// ++dst_alpha;
// uint32 dst_g = (dst & 0x00FF00) * dst_alpha / 256;
// dst = (dst & 0xFF00FF) * dst_alpha / 256;
// dst_g = (((src & 0x00FF00) - (dst_g & 0x00FF00)) * src_alpha / 256 + dst_g) & 0x00FF00;
// dst = (((src & 0xFF00FF) - (dst & 0xFF00FF)) * src_alpha / 256 + dst) & 0xFF00FF;
// dst_alpha = 256 - (256 - src_alpha) * (256 - dst_alpha) / 256;
// src_alpha = /* 256 * 256 == */ 0x10000 / dst_alpha;
// dst_g = (dst_g * src_alpha / 256) & 0x00FF00;
// dst = (dst * src_alpha / 256) & 0xFF00FF;
// return dst | dst_g | (--dst_alpha << 24);
double sAlpha = (double)(aSrc & 0xff) / 255.0;
double dAlpha = (double)aDest / 255.0;
dAlpha *= (1.0 - sAlpha);
rDest = static_cast<uint8>((rSrc * sAlpha + rDest * dAlpha) / (sAlpha + dAlpha));
gDest = static_cast<uint8>((gSrc * sAlpha + gDest * dAlpha) / (sAlpha + dAlpha));
bDest = static_cast<uint8>((bSrc * sAlpha + bDest * dAlpha) / (sAlpha + dAlpha));
aDest = static_cast<uint8>(255. * (sAlpha + dAlpha));
}
// kRgbToRgbBlender
inline void blendRgbToRgb(uint8 aSrc, uint8 rSrc, uint8 gSrc, uint8 bSrc, uint8 &aDest, uint8 &rDest, uint8 &gDest, uint8 &bDest, uint32 alpha) const {
// Default mode for set_trans_blender
rgbBlend(rSrc, gSrc, bSrc, rDest, gDest, bDest, alpha);
// Original doesn't set alpha (so it is 0), but the function is not meant to be used
// on bitmap with transparency. Should we set alpha to 0xff?
aDest = 0;
}
// kAlphaPreservedBlenderMode
inline void blendPreserveAlpha(uint8 aSrc, uint8 rSrc, uint8 gSrc, uint8 bSrc, uint8 &aDest, uint8 &rDest, uint8 &gDest, uint8 &bDest, uint32 alpha) const {
// Original blender function: _myblender_alpha_trans24
// Like blendRgbToRgb, but result as the same alpha as destColor
rgbBlend(rSrc, gSrc, bSrc, rDest, gDest, bDest, alpha);
// Preserve value in aDest
}
// kArgbToArgbBlender
inline void blendArgbToArgb(uint8 aSrc, uint8 rSrc, uint8 gSrc, uint8 bSrc, uint8 &aDest, uint8 &rDest, uint8 &gDest, uint8 &bDest, uint32 alpha) const {
// Original blender functions: _argb2argb_blender
if (alpha == 0)
alpha = aSrc;
else
alpha = aSrc * ((alpha & 0xff) + 1) / 256;
if (alpha != 0)
argbBlend(alpha, rSrc, gSrc, bSrc, aDest, rDest, gDest, bDest);
}
// kRgbToArgbBlender
inline void blendRgbToArgb(uint8 aSrc, uint8 rSrc, uint8 gSrc, uint8 bSrc, uint8 &aDest, uint8 &rDest, uint8 &gDest, uint8 &bDest, uint32 alpha) const {
// Original blender function: _rgb2argb_blenders
if (alpha == 0 || alpha == 0xff) {
aDest = 0xff;
rDest = rSrc;
gDest = gSrc;
bDest = bSrc;
} else
argbBlend(alpha, rSrc, gSrc, bSrc, aDest, rDest, gDest, bDest);
}
// kArgbToRgbBlender
inline void blendArgbToRgb(uint8 aSrc, uint8 rSrc, uint8 gSrc, uint8 bSrc, uint8 &aDest, uint8 &rDest, uint8 &gDest, uint8 &bDest, uint32 alpha) const {
// Original blender function: _argb2rgb_blender
if (alpha == 0)
alpha = aSrc;
else
alpha = aSrc * ((alpha & 0xff) + 1) / 256;
rgbBlend(rSrc, gSrc, bSrc, rDest, gDest, bDest, alpha);
// Original doesn't set alpha (so it is 0), but the function is not meant to be used
// on bitmap with transparency. Should we set alpha to 0xff?
aDest = 0;
}
// kOpaqueBlenderMode
inline void blendOpaque(uint8 aSrc, uint8 rSrc, uint8 gSrc, uint8 bSrc, uint8 &aDest, uint8 &rDest, uint8 &gDest, uint8 &bDest, uint32 alpha) const {
// Original blender function: _opaque_alpha_blender
aDest = 0xff;
rDest = rSrc;
gDest = gSrc;
bDest = bSrc;
}
// kSourceAlphaBlender
inline void blendSourceAlpha(uint8 aSrc, uint8 rSrc, uint8 gSrc, uint8 bSrc, uint8 &aDest, uint8 &rDest, uint8 &gDest, uint8 &bDest, uint32 alpha) const {
// Used after set_alpha_blender
// Uses alpha from source. Result is fully opaque
rgbBlend(rSrc, gSrc, bSrc, rDest, gDest, bDest, aSrc);
// Original doesn't set alpha (so it is 0), but the function is not meant to be used
// on bitmap with transparency. Should we set alpha to 0xff?
aDest = 0;
}
// kAdditiveBlenderMode
inline void blendAdditiveAlpha(uint8 aSrc, uint8 rSrc, uint8 gSrc, uint8 bSrc, uint8 &aDest, uint8 &rDest, uint8 &gDest, uint8 &bDest, uint32 alpha) const {
// Original blender function: _additive_alpha_copysrc_blender
rDest = rSrc;
gDest = gSrc;
bDest = bSrc;
uint32 a = (uint32)aSrc + (uint32)aDest;
if (a > 0xff)
aDest = 0xff;
else
aDest = static_cast<uint8>(a);
}
// kTintBlenderMode and kTintLightBlenderMode
void blendTintSprite(uint8 aSrc, uint8 rSrc, uint8 gSrc, uint8 bSrc, uint8 &aDest, uint8 &rDest, uint8 &gDest, uint8 &bDest, uint32 alpha, bool light) const;
friend class DrawInnerImpl_AVX2;
friend class DrawInnerImpl_SSE2;
friend class DrawInnerImpl_NEON;
constexpr static int SCALE_THRESHOLD_BITS = 8;
constexpr static int SCALE_THRESHOLD = 1 << SCALE_THRESHOLD_BITS;
struct DrawInnerArgs {
const bool useTint, horizFlip, vertFlip, skipTrans;
bool sameFormat, shouldDraw;
int xStart, yStart, srcAlpha, tintRed, tintGreen, tintBlue, scaleX, scaleY;
uint32 transColor, alphaMask;
PALETTE palette;
BlenderMode blenderMode;
Common::Rect dstRect, srcArea;
BITMAP &dstBitmap;
const ::Graphics::ManagedSurface &src;
::Graphics::Surface destArea;
DrawInnerArgs(BITMAP *dstBitmap, const BITMAP *srcBitmap,
const Common::Rect &srcRect, const Common::Rect &dstRect,
bool skipTrans, int srcAlpha, bool horizFlip,
bool vertFlip, int tintRed, int tintGreen, int tintBlue,
bool doScale);
};
template<bool Scale>
void drawGeneric(DrawInnerArgs &args);
#ifdef SCUMMVM_NEON
template<bool Scale>
void drawNEON(DrawInnerArgs &args);
#endif
#ifdef SCUMMVM_SSE2
template<bool Scale>
void drawSSE2(DrawInnerArgs &args);
#endif
#ifdef SCUMMVM_AVX2
template<bool Scale>
void drawAVX2(DrawInnerArgs &args);
#endif
template<int DestBytesPerPixel, int SrcBytesPerPixel, bool Scale>
void drawInnerGeneric(DrawInnerArgs &args);
inline uint32 getColor(const byte *data, byte bpp) const {
switch (bpp) {
case 1:
return *data;
case 2:
return *(const uint16 *)data;
case 4:
return *(const uint32 *)data;
default:
error("Unsupported format in BITMAP::getColor");
}
}
};
/**
* Derived surface class
*/
class Surface : public Graphics::ManagedSurface, public BITMAP {
public:
Surface(int width, int height, const Graphics::PixelFormat &pixelFormat) :
Graphics::ManagedSurface(width, height, pixelFormat), BITMAP(this) {
// Allegro uses 255, 0, 255 RGB as the transparent color
if (pixelFormat.bytesPerPixel == 2 || pixelFormat.bytesPerPixel == 4)
setTransparentColor(pixelFormat.RGBToColor(255, 0, 255));
}
Surface(Graphics::ManagedSurface &surf, const Common::Rect &bounds) :
Graphics::ManagedSurface(surf, bounds), BITMAP(this) {
// Allegro uses 255, 0, 255 RGB as the transparent color
if (surf.format.bytesPerPixel == 2 || surf.format.bytesPerPixel == 4)
setTransparentColor(surf.format.RGBToColor(255, 0, 255));
}
~Surface() override {
}
};
BITMAP *create_bitmap(int width, int height);
BITMAP *create_bitmap_ex(int color_depth, int width, int height);
BITMAP *create_sub_bitmap(BITMAP *parent, int x, int y, int width, int height);
BITMAP *create_video_bitmap(int width, int height);
BITMAP *create_system_bitmap(int width, int height);
void destroy_bitmap(BITMAP *bitmap);
} // namespace AGS3
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,212 @@
/* 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/>.
*
*/
#include "ags/lib/allegro/color.h"
#include "ags/lib/allegro/surface.h"
#include "ags/globals.h"
namespace AGS3 {
template<int DestBytesPerPixel, int SrcBytesPerPixel, bool Scale>
void BITMAP::drawInnerGeneric(DrawInnerArgs &args) {
const int xDir = args.horizFlip ? -1 : 1;
byte rSrc, gSrc, bSrc, aSrc;
byte rDest = 0, gDest = 0, bDest = 0, aDest = 0;
// Instead of skipping pixels outside our boundary here, we just clip
// our area instead.
int xCtrStart = 0, xCtrBppStart = 0, xCtrWidth = args.dstRect.width();
if (args.xStart + xCtrWidth > args.destArea.w) { // Clip the right
xCtrWidth = args.destArea.w - args.xStart;
}
if (args.xStart < 0) { // Clip the left
xCtrStart = -args.xStart;
xCtrBppStart = xCtrStart * SrcBytesPerPixel;
args.xStart = 0;
}
int destY = args.yStart, yCtr = 0, srcYCtr = 0, scaleYCtr = 0, yCtrHeight = args.dstRect.height();
if (args.yStart < 0) { // Clip the top
yCtr = -args.yStart;
destY = 0;
if (Scale) {
scaleYCtr = yCtr * args.scaleY;
srcYCtr = scaleYCtr / BITMAP::SCALE_THRESHOLD;
}
}
if (args.yStart + yCtrHeight > args.destArea.h) { // Clip the bottom
yCtrHeight = args.destArea.h - args.yStart;
}
byte *destP = (byte *)args.destArea.getBasePtr(0, destY);
const byte *srcP = (const byte *)args.src.getBasePtr(
args.horizFlip ? args.srcArea.right - 1 : args.srcArea.left,
args.vertFlip ? args.srcArea.bottom - 1 - yCtr :
args.srcArea.top + yCtr);
for (; yCtr < yCtrHeight; ++destY, ++yCtr, scaleYCtr += args.scaleY) {
if (Scale) {
int newSrcYCtr = scaleYCtr / BITMAP::SCALE_THRESHOLD;
if (srcYCtr != newSrcYCtr) {
int diffSrcYCtr = newSrcYCtr - srcYCtr;
srcP += args.src.pitch * diffSrcYCtr;
srcYCtr = newSrcYCtr;
}
}
// Loop through the pixels of the row
for (int destX = args.xStart, xCtr = xCtrStart, xCtrBpp = xCtrBppStart, scaleXCtr = xCtr * args.scaleX; xCtr < xCtrWidth; ++destX, ++xCtr, xCtrBpp += SrcBytesPerPixel, scaleXCtr += args.scaleX) {
const byte *srcVal = srcP + xDir * xCtrBpp;
if (Scale) {
srcVal = srcP + (scaleXCtr / BITMAP::SCALE_THRESHOLD) * SrcBytesPerPixel;
}
uint32 srcCol = getColor(srcVal, SrcBytesPerPixel);
// Check if this is a transparent color we should skip
if (args.skipTrans && ((srcCol & args.alphaMask) == args.transColor))
continue;
byte *destVal = (byte *)&destP[destX * DestBytesPerPixel];
// When blitting to the same format we can just copy the color
if (DestBytesPerPixel == 1) {
*destVal = srcCol;
continue;
} else if ((DestBytesPerPixel == SrcBytesPerPixel) && args.srcAlpha == -1) {
if (DestBytesPerPixel == 4)
*(uint32 *)destVal = srcCol;
else
*(uint16 *)destVal = srcCol;
continue;
}
// We need the rgb values to do blending and/or convert between formats
if (SrcBytesPerPixel == 1) {
const RGB &rgb = args.palette[srcCol];
aSrc = 0xff;
rSrc = rgb.r;
gSrc = rgb.g;
bSrc = rgb.b;
} else {
if (SrcBytesPerPixel == 4) {
aSrc = srcCol >> 24;
rSrc = (srcCol >> 16) & 0xff;
gSrc = (srcCol >> 8) & 0xff;
bSrc = srcCol & 0xff;
} else { // SrcBytesPerPixel == 2
aSrc = 0xff;
rSrc = (srcCol >> 11) & 0x1f;
rSrc = (rSrc << 3) | (rSrc >> 2);
gSrc = (srcCol >> 5) & 0x3f;
gSrc = (gSrc << 2) | (gSrc >> 4);
bSrc = srcCol & 0x1f;
bSrc = (bSrc << 3) | (bSrc >> 2);
}
//src.format.colorToARGB(srcCol, aSrc, rSrc, gSrc, bSrc);
}
if (args.srcAlpha == -1) {
// This means we don't use blending.
aDest = aSrc;
rDest = rSrc;
gDest = gSrc;
bDest = bSrc;
} else {
if (args.useTint) {
rDest = rSrc;
gDest = gSrc;
bDest = bSrc;
aDest = aSrc;
rSrc = args.tintRed;
gSrc = args.tintGreen;
bSrc = args.tintBlue;
aSrc = args.srcAlpha;
} else {
uint32 destCol = getColor(destVal, DestBytesPerPixel);
if (DestBytesPerPixel == 1) {
const RGB &rgb = args.palette[destCol];
aDest = 0xff;
rDest = rgb.r;
gDest = rgb.g;
bDest = rgb.b;
} else {
if (DestBytesPerPixel == 4) {
aDest = destCol >> 24;
rDest = (destCol >> 16) & 0xff;
gDest = (destCol >> 8) & 0xff;
bDest = destCol & 0xff;
} else { // DestBytesPerPixel == 2
aDest = 0xff;
rDest = (destCol >> 11) & 0x1f;
rDest = (rDest << 3) | (rDest >> 2);
gDest = (destCol >> 5) & 0x3f;
gDest = (gDest << 2) | (gDest >> 4);
bDest = destCol & 0x1f;
bDest = (bDest << 3) | (bDest >> 2);
}
//src.format.colorToARGB(srcCol, aSrc, rSrc, gSrc, bSrc);
}
}
blendPixel(aSrc, rSrc, gSrc, bSrc, aDest, rDest, gDest, bDest, args.srcAlpha, args.useTint, destVal);
}
uint32 pixel;// = format.ARGBToColor(aDest, rDest, gDest, bDest);
if (DestBytesPerPixel == 4) {
pixel = (aDest << 24) | (rDest << 16) | (gDest << 8) | (bDest);
*(uint32 *)destVal = pixel;
}
else {
pixel = ((rDest >> 3) << 11) | ((gDest >> 2) << 5) | (bDest >> 3);
*(uint16 *)destVal = pixel;
}
}
destP += args.destArea.pitch;
if (!Scale) srcP += args.vertFlip ? -args.src.pitch : args.src.pitch;
}
}
template<bool Scale>
void BITMAP::drawGeneric(DrawInnerArgs &args) {
if (args.sameFormat) {
switch (format.bytesPerPixel) {
case 1: drawInnerGeneric<1, 1, Scale>(args); break;
case 2: drawInnerGeneric<2, 2, Scale>(args); break;
case 4: drawInnerGeneric<4, 4, Scale>(args); break;
}
} else if (format.bytesPerPixel == 4 && args.src.format.bytesPerPixel == 2) {
drawInnerGeneric<4, 2, Scale>(args);
} else if (format.bytesPerPixel == 2 && args.src.format.bytesPerPixel == 4) {
drawInnerGeneric<2, 4, Scale>(args);
}
}
template void BITMAP::drawGeneric<false>(DrawInnerArgs &);
template void BITMAP::drawGeneric<true>(DrawInnerArgs &);
template void BITMAP::drawInnerGeneric<4, 4, false>(DrawInnerArgs &);
template void BITMAP::drawInnerGeneric<4, 4, true>(DrawInnerArgs &);
template void BITMAP::drawInnerGeneric<4, 2, false>(DrawInnerArgs &);
template void BITMAP::drawInnerGeneric<4, 2, true>(DrawInnerArgs &);
template void BITMAP::drawInnerGeneric<2, 4, false>(DrawInnerArgs &);
template void BITMAP::drawInnerGeneric<2, 4, true>(DrawInnerArgs &);
template void BITMAP::drawInnerGeneric<4, 1, false>(DrawInnerArgs &);
template void BITMAP::drawInnerGeneric<4, 1, true>(DrawInnerArgs &);
template void BITMAP::drawInnerGeneric<2, 1, false>(DrawInnerArgs &);
template void BITMAP::drawInnerGeneric<2, 1, true>(DrawInnerArgs &);
} // end of namespace AGS3

View File

@@ -0,0 +1,989 @@
/* 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/>.
*
*/
#include "ags/ags.h"
// Without this ifdef the iOS backend breaks, please do not remove
#ifdef SCUMMVM_NEON
#include "ags/globals.h"
#include "ags/lib/allegro/color.h"
#include "ags/lib/allegro/flood.h"
#include "ags/lib/allegro/gfx.h"
#include "common/textconsole.h"
#include "graphics/screen.h"
#include <arm_neon.h>
#if !defined(__aarch64__) && !defined(__ARM_NEON)
#if defined(__clang__)
#pragma clang attribute push (__attribute__((target("neon"))), apply_to=function)
#elif defined(__GNUC__)
#pragma GCC push_options
#pragma GCC target("fpu=neon")
#endif
#endif // !defined(__aarch64__) && !defined(__ARM_NEON)
namespace AGS3 {
class DrawInnerImpl_NEON {
static inline uint32x4_t simd2BppTo4Bpp(uint16x4_t pixels) {
uint32x4_t x = vmovl_u16(pixels);
// c is the extracted 5/6 bit color from the image
uint32x4_t c = vshrq_n_u32(x, 11);
// We convert it back to normal by shifting it thrice over, naturally, and then using the 2 most
// sinificant bits in the original color for the least significant bits in the new one
uint32x4_t r = vshlq_n_u32(vorrq_u32(vshlq_n_u32(c, 3), vshrq_n_u32(c, 2)), 16);
c = vshrq_n_u32(vandq_u32(x, vmovq_n_u32(0x07e0)), 5);
uint32x4_t g = vshlq_n_u32(vorrq_u32(vshlq_n_u32(c, 2), vshrq_n_u32(c, 4)), 8);
c = vandq_u32(x, vmovq_n_u32(0x001f));
uint32x4_t b = vorrq_u32(vshlq_n_u32(c, 3), vshrq_n_u32(c, 2));
// By default 2bpp to 4bpp makes the alpha channel 255
return vorrq_u32(vorrq_u32(vorrq_u32(r, g), b), vmovq_n_u32(0xff000000));
}
static inline uint16x4_t simd4BppTo2Bpp(uint32x4_t pixels) {
// x is the final 16 bit rgb pixel
uint32x4_t x = vshrq_n_u32(vandq_u32(pixels, vmovq_n_u32(0x000000ff)), 3);
x = vorrq_u32(x, vshlq_n_u32(vshrq_n_u32(vandq_u32(pixels, vmovq_n_u32(0x0000ff00)), 8+2), 5));
x = vorrq_u32(x, vshlq_n_u32(vshrq_n_u32(vandq_u32(pixels, vmovq_n_u32(0x00ff0000)), 16+3), 11));
return vmovn_u32(x);
}
static inline uint16x8_t rgbBlendSIMD2Bpp(uint16x8_t srcCols, uint16x8_t destCols, uint16x8_t alphas) {
// Here we add 1 to alphas if its 0. This is what the original blender function did
alphas = vaddq_u16(alphas, vandq_u16(vceqq_u16(alphas, vmovq_n_u16(0)), vmovq_n_u16(1)));
// Split the components into rgb
uint16x8_t srcComps[] = {
vandq_u16(srcCols, vmovq_n_u16(0x1f)), // B
vandq_u16(vshrq_n_u16(srcCols, 5), vmovq_n_u16(0x3f)), // G
vshrq_n_u16(srcCols, 11), // R
}, destComps[] = {
vandq_u16(destCols, vmovq_n_u16(0x1f)), // B
vandq_u16(vshrq_n_u16(destCols, 5), vmovq_n_u16(0x3f)), // G
vshrq_n_u16(destCols, 11), // R
};
// At some point I made it so that it would put them into their 8bit depth format
// to keep the function as 1-1 with the original, but it didn't seem to help much
//srcComps[0] = vorrq_u16(vshlq_n_u16(srcComps[0], 3), vshrq_n_u16(srcComps[0], 2));
//srcComps[1] = vorrq_u16(vshlq_n_u16(srcComps[1], 2), vshrq_n_u16(srcComps[1], 4));
//srcComps[2] = vorrq_u16(vshlq_n_u16(srcComps[2], 3), vshrq_n_u16(srcComps[2], 2));
//destComps[0] = vorrq_u16(vshlq_n_u16(destComps[0], 3), vshrq_n_u16(destComps[0], 2));
//destComps[1] = vorrq_u16(vshlq_n_u16(destComps[1], 2), vshrq_n_u16(destComps[1], 4));
//destComps[2] = vorrq_u16(vshlq_n_u16(destComps[2], 3), vshrq_n_u16(destComps[2], 2));
// Calculate the differences between the colors
uint16x8_t diffs[] = {
vsubq_u16(srcComps[0], destComps[0]), // B
vsubq_u16(srcComps[1], destComps[1]), // G
vsubq_u16(srcComps[2], destComps[2]), // R
};
// Multiply by alpha and shift depth bits to the right
// pretty much the same as (int)(((float)component / 255.0f) * ((float)alpha / 255.0f) * 255.0f)
alphas = vshrq_n_u16(alphas, 2);
diffs[1] = vshrq_n_u16(vmulq_u16(diffs[1], alphas), 6);
alphas = vshrq_n_u16(alphas, 1);
diffs[0] = vshrq_n_u16(vmulq_u16(diffs[0], alphas), 5);
diffs[2] = vshrq_n_u16(vmulq_u16(diffs[2], alphas), 5);
// Originally, I converted it back to normal here from the 8bpp form, but don't need to do that anymore
//diffs[0] = vandq_u16(vshrq_n_u16(vaddq_u16(diffs[0], destComps[0]), 3), vmovq_n_u16(0x1f));
//diffs[1] = vandq_u16(vshrq_n_u16(vaddq_u16(diffs[1], destComps[1]), 2), vmovq_n_u16(0x3f));
//diffs[2] = vandq_u16(vshrq_n_u16(vaddq_u16(diffs[2], destComps[2]), 3), vmovq_n_u16(0x1f));
// Here we add the difference between the 2 colors times alpha onto the destination
diffs[0] = vandq_u16(vaddq_u16(diffs[0], destComps[0]), vmovq_n_u16(0x1f));
diffs[1] = vandq_u16(vaddq_u16(diffs[1], destComps[1]), vmovq_n_u16(0x3f));
diffs[2] = vandq_u16(vaddq_u16(diffs[2], destComps[2]), vmovq_n_u16(0x1f));
// We compile all the colors into diffs[0] as a 16 bit rgb pixel
diffs[0] = vorrq_u16(diffs[0], vshlq_n_u16(diffs[1], 5));
return vorrq_u16(diffs[0], vshlq_n_u16(diffs[2], 11));
}
// preserveAlpha:
// false => set destCols's alpha to 0
// true => keep destCols's alpha
static inline uint32x4_t rgbBlendSIMD(uint32x4_t srcCols, uint32x4_t destCols, uint32x4_t alphas, bool preserveAlpha) {
// Here we add 1 to alphas if its 0. This is what the original blender function did
alphas = vaddq_u32(alphas, vandq_u32(vcgtq_u32(alphas, vmovq_n_u32(0)), vmovq_n_u32(1)));
// Get the alpha from the destination
uint32x4_t alpha = vandq_u32(destCols, vmovq_n_u32(0xff000000));
// Get red and blue components
uint32x4_t srcColsCopy = srcCols;
srcColsCopy = vandq_u32(srcColsCopy, vmovq_n_u32(0xff00ff));
uint32x4_t destColsCopy = destCols;
destColsCopy = vandq_u32(destColsCopy, vmovq_n_u32(0xff00ff));
// compute the difference, then multiply by alpha and divide by 255
srcColsCopy = vsubq_u32(srcColsCopy, destColsCopy);
srcColsCopy = vmulq_u32(srcColsCopy, alphas);
srcColsCopy = vshrq_n_u32(srcColsCopy, 8);
srcColsCopy = vaddq_u32(srcColsCopy, destCols); // Add the new red/blue to the old ones
// do the same for the green component
srcCols = vandq_u32(srcCols, vmovq_n_u32(0xff00));
destCols = vandq_u32(destCols, vmovq_n_u32(0xff00));
srcCols = vsubq_u32(srcCols, destCols);
srcCols = vmulq_u32(srcCols, alphas);
srcCols = vshrq_n_u32(srcCols, 8);
srcCols = vaddq_u32(srcCols, destCols); // Add the new green to the old green
// keep values in 8bit range and glue red/blue and green together
srcColsCopy = vandq_u32(srcColsCopy, vmovq_n_u32(0xff00ff));
srcCols = vandq_u32(srcCols, vmovq_n_u32(0xff00));
srcCols = vorrq_u32(srcCols, srcColsCopy);
// Remember that alpha is not alphas, but rather the alpha of destCols
if (preserveAlpha) {
srcCols = vandq_u32(srcCols, vmovq_n_u32(0x00ffffff));
srcCols = vorrq_u32(srcCols, alpha);
}
return srcCols;
}
// uses the alpha from srcCols and destCols
static inline uint32x4_t argbBlendSIMD(uint32x4_t srcCols, uint32x4_t destCols) {
float32x4_t srcA = vcvtq_f32_u32(vshrq_n_u32(srcCols, 24));
srcA = vmulq_n_f32(srcA, 1.0f / 255.0f);
float32x4_t srcR = vcvtq_f32_u32(vandq_u32(vshrq_n_u32(srcCols, 16), vmovq_n_u32(0xff)));
float32x4_t srcG = vcvtq_f32_u32(vandq_u32(vshrq_n_u32(srcCols, 8), vmovq_n_u32(0xff)));
float32x4_t srcB = vcvtq_f32_u32(vandq_u32(srcCols, vmovq_n_u32(0xff)));
float32x4_t destA = vcvtq_f32_u32(vshrq_n_u32(destCols, 24));
destA = vmulq_n_f32(destA, 1.0f / 255.0f);
float32x4_t destR = vcvtq_f32_u32(vandq_u32(vshrq_n_u32(destCols, 16), vmovq_n_u32(0xff)));
float32x4_t destG = vcvtq_f32_u32(vandq_u32(vshrq_n_u32(destCols, 8), vmovq_n_u32(0xff)));
float32x4_t destB = vcvtq_f32_u32(vandq_u32(destCols, vmovq_n_u32(0xff)));
// the destination alpha gets multiplied by 255 - source alpha
destA = vmulq_f32(destA, vsubq_f32(vmovq_n_f32(1.0f), srcA));
// ((src * sAlpha) + (dest * dAlpha)) / (sAlpha + dAlpha)
float32x4_t combA = vaddq_f32(srcA, destA);
float32x4_t combArcp = vrecpeq_f32(combA);
destR = vmulq_f32(vaddq_f32(vmulq_f32(srcR, srcA), vmulq_f32(destR, destA)), combArcp);
destG = vmulq_f32(vaddq_f32(vmulq_f32(srcG, srcA), vmulq_f32(destG, destA)), combArcp);
destB = vmulq_f32(vaddq_f32(vmulq_f32(srcB, srcA), vmulq_f32(destB, destA)), combArcp);
combA = vmulq_n_f32(combA, 255.0);
// Now put it back together
return vorrq_u32(vshlq_n_u32(vcvtq_u32_f32(combA), 24),
vorrq_u32(vshlq_n_u32(vcvtq_u32_f32(destR), 16),
vorrq_u32(vshlq_n_u32(vcvtq_u32_f32(destG), 8),
vcvtq_u32_f32(destB))));
}
static inline uint32x4_t blendTintSpriteSIMD(uint32x4_t srcCols, uint32x4_t destCols, uint32x4_t alphas, bool light) {
// This function is NOT 1 to 1 with the original... It just approximates it
// It gets the value of the HSV of the dest color
// Then it gets the HSV of the srcCols
// how the values are transformed
// from 1 uint32x4_t srcCols with each lane being ARGB uint32
// srcCols[0] = A | R | G | B
// srcCols[1] = A | R | G | B
// srcCols[2] = A | R | G | B
// srcCols[3] = A | R | G | B
// ->
// to 4 float32x4_t's each being a separate channel with each lane
// corresponding to their respective srcCols lane
// dda = { A[0], A[1], A[2], A[3] }
// ddr = { R[0], R[1], R[2], R[3] }
// ddg = { G[0], G[1], G[2], G[3] }
// ddb = { B[0], B[1], B[2], B[3] }
// do the transformation (we don't actually need alpha at all)
float32x4_t ddr, ddg, ddb;
ddr = vmulq_n_f32(vcvtq_f32_u32(vandq_u32(vshrq_n_u32(destCols, 16), vmovq_n_u32(0xff))), 1.0 / 255.0);
ddg = vmulq_n_f32(vcvtq_f32_u32(vandq_u32(vshrq_n_u32(destCols, 8), vmovq_n_u32(0xff))), 1.0 / 255.0);
ddb = vmulq_n_f32(vcvtq_f32_u32(vandq_u32(destCols, vmovq_n_u32(0xff))), 1.0 / 255.0);
float32x4_t ssr, ssg, ssb;
ssr = vmulq_n_f32(vcvtq_f32_u32(vandq_u32(vshrq_n_u32(srcCols, 16), vmovq_n_u32(0xff))), 1.0 / 255.0);
ssg = vmulq_n_f32(vcvtq_f32_u32(vandq_u32(vshrq_n_u32(srcCols, 8), vmovq_n_u32(0xff))), 1.0 / 255.0);
ssb = vmulq_n_f32(vcvtq_f32_u32(vandq_u32(srcCols, vmovq_n_u32(0xff))), 1.0 / 255.0);
// Get the maxes and mins (needed for HSV->RGB and vice-versa)
float32x4_t dmaxes = vmaxq_f32(ddr, vmaxq_f32(ddg, ddb));
float32x4_t smaxes = vmaxq_f32(ssr, vmaxq_f32(ssg, ssb));
float32x4_t smins = vminq_f32(ssr, vminq_f32(ssg, ssb));
// This is here to stop from dividing by 0
const float32x4_t eplison0 = vmovq_n_f32(0.0000001);
float32x4_t chroma = vmaxq_f32(vsubq_f32(smaxes, smins), eplison0);
// RGB to HSV is a piecewise function, so we compute each part of the function first...
float32x4_t hr, hg, hb, hue, chromaReq;
chromaReq = vrecpeq_f32(chroma);
hr = vmulq_f32(vsubq_f32(ssg, ssb), chromaReq);
float32x4_t hrDiv6 = vmulq_n_f32(hr, 1.0 / 6.0);
hrDiv6 = vsubq_f32(hrDiv6, vcvtq_f32_u32(vandq_u32(vcltq_f32(hrDiv6, vmovq_n_f32(0.0)), vmovq_n_u32(1))));
hr = vsubq_f32(hr, vmulq_n_f32(vcvtq_f32_s32(vcvtq_s32_f32(hrDiv6)), 6.0));
hg = vaddq_f32(vmulq_f32(vsubq_f32(ssb, ssr), chromaReq), vmovq_n_f32(2.0));
hb = vaddq_f32(vmulq_f32(vsubq_f32(ssr, ssg), chromaReq), vmovq_n_f32(4.0));
// And then compute which one will be used based on criteria
float32x4_t hrfactors = vcvtq_f32_u32(vandq_u32(vandq_u32(vceqq_f32(ssr, smaxes), vmvnq_u32(vceqq_f32(ssr, ssb))), vmovq_n_u32(1)));
float32x4_t hgfactors = vcvtq_f32_u32(vandq_u32(vandq_u32(vceqq_f32(ssg, smaxes), vmvnq_u32(vceqq_f32(ssg, ssr))), vmovq_n_u32(1)));
float32x4_t hbfactors = vcvtq_f32_u32(vandq_u32(vandq_u32(vceqq_f32(ssb, smaxes), vmvnq_u32(vceqq_f32(ssb, ssg))), vmovq_n_u32(1)));
hue = vmulq_f32(hr, hrfactors);
hue = vaddq_f32(hue, vmulq_f32(hg, hgfactors));
hue = vaddq_f32(hue, vmulq_f32(hb, hbfactors));
// Mess with the light like the original function
float32x4_t val = dmaxes;
if (light) {
val = vsubq_f32(val, vsubq_f32(vmovq_n_f32(1.0), vmulq_n_f32(vcvtq_f32_u32(alphas), 1.0 / 250.0)));
val = vmaxq_f32(val, vmovq_n_f32(0.0));
}
// then it stitches the HSV back together
// the hue and saturation come from the source (tint) color, and the value comes from
// the destination (real source) color
chroma = vmulq_f32(val, vmulq_f32(vsubq_f32(smaxes, smins), vrecpeq_f32(vaddq_f32(smaxes, eplison0))));
float32x4_t hprime_mod2 = vmulq_n_f32(hue, 1.0 / 2.0);
hprime_mod2 = vmulq_n_f32(vsubq_f32(hprime_mod2, vcvtq_f32_s32(vcvtq_s32_f32(hprime_mod2))), 2.0);
float32x4_t x = vmulq_f32(chroma, vsubq_f32(vmovq_n_f32(1.0), vabsq_f32(vsubq_f32(hprime_mod2, vmovq_n_f32(1.0)))));
uint32x4_t hprime_rounded = vcvtq_u32_f32(hue);
uint32x4_t x_int = vcvtq_u32_f32(vmulq_n_f32(x, 255.0));
uint32x4_t c_int = vcvtq_u32_f32(vmulq_n_f32(chroma, 255.0));
// Again HSV->RGB is also a piecewise function
uint32x4_t val0 = vorrq_u32(vshlq_n_u32(x_int, 8), vshlq_n_u32(c_int, 16));
val0 = vandq_u32(val0, vorrq_u32(vceqq_u32(hprime_rounded, vmovq_n_u32(0)), vceqq_u32(hprime_rounded, vmovq_n_u32(6))));
uint32x4_t val1 = vorrq_u32(vshlq_n_u32(c_int, 8), vshlq_n_u32(x_int, 16));
val1 = vandq_u32(val1, vceqq_u32(hprime_rounded, vmovq_n_u32(1)));
uint32x4_t val2 = vorrq_u32(vshlq_n_u32(c_int, 8), x_int);
val2 = vandq_u32(val2, vceqq_u32(hprime_rounded, vmovq_n_u32(2)));
uint32x4_t val3 = vorrq_u32(vshlq_n_u32(x_int, 8), c_int);
val3 = vandq_u32(val3, vceqq_u32(hprime_rounded, vmovq_n_u32(3)));
uint32x4_t val4 = vorrq_u32(vshlq_n_u32(x_int, 16), c_int);
val4 = vandq_u32(val4, vceqq_u32(hprime_rounded, vmovq_n_u32(4)));
uint32x4_t val5 = vorrq_u32(vshlq_n_u32(c_int, 16), x_int);
val5 = vandq_u32(val5, vceqq_u32(hprime_rounded, vmovq_n_u32(5)));
// or the values together
uint32x4_t final = vorrq_u32(val0, vorrq_u32(val1, vorrq_u32(val2, vorrq_u32(val3, vorrq_u32(val4, val5)))));
// add the minimums back in
uint32x4_t val_add = vcvtq_u32_f32(vmulq_n_f32(vsubq_f32(val, chroma), 255.0));
val_add = vorrq_u32(val_add, vorrq_u32(vshlq_n_u32(val_add, 8), vorrq_u32(vshlq_n_u32(val_add, 16), vandq_u32(destCols, vmovq_n_u32(0xff000000)))));
final = vaddq_u32(final, val_add);
return final;
}
static inline uint32x4_t blendPixelSIMD(uint32x4_t srcCols, uint32x4_t destCols, uint32x4_t alphas) {
uint32x4_t srcAlphas, difAlphas, mask, ch1, ch2;
auto setupArgbAlphas = [&]() {
// This acts the same as this in the normal blender functions
// if (alpha == 0)
// alpha = aSrc;
// else
// alpha = aSrc * ((alpha & 0xff) + 1) / 256;
// where alpha is the alpha byte of the srcCols
srcAlphas = vshrq_n_u32(srcCols, 24);
difAlphas = vaddq_u32(vandq_u32(alphas, vmovq_n_u32(0xff)), vmovq_n_u32(1));
difAlphas = vshrq_n_u32(vmulq_u32(srcAlphas, difAlphas), 8);
difAlphas = vshlq_n_u32(difAlphas, 24);
srcAlphas = vshlq_n_u32(srcAlphas, 24);
mask = vceqq_u32(alphas, vmovq_n_u32(0));
srcAlphas = vandq_u32(srcAlphas, mask);
difAlphas = vandq_u32(difAlphas, vmvnq_u32(mask));
srcCols = vandq_u32(srcCols, vmovq_n_u32(0x00ffffff));
srcCols = vorrq_u32(srcCols, vorrq_u32(srcAlphas, difAlphas));
};
switch (_G(_blender_mode)) {
case kSourceAlphaBlender: // see BITMAP member function blendSourceAlpha
alphas = vshrq_n_u32(srcCols, 24);
return rgbBlendSIMD(srcCols, destCols, alphas, false);
case kArgbToArgbBlender: // see BITMAP member function blendArgbToArgb
setupArgbAlphas();
// only blend if alpha isn't 0, otherwise use destCols
mask = vcgtq_u32(vshrq_n_u32(srcCols, 24), vmovq_n_u32(0));
ch1 = vandq_u32(argbBlendSIMD(srcCols, destCols), mask);
ch2 = vandq_u32(destCols, vmvnq_u32(mask));
return vorrq_u32(ch1, ch2);
case kArgbToRgbBlender: // see BITMAP member function blendArgbToRgb
setupArgbAlphas();
return rgbBlendSIMD(srcCols, destCols, vshrq_n_u32(srcCols, 24), false);
case kRgbToArgbBlender: // see BITMAP member function blendRgbToArgb
// if alpha is NOT 0 or 255
ch2 = vandq_u32(srcCols, vmovq_n_u32(0x00ffffff));
ch2 = vorrq_u32(ch2, vshlq_n_u32(alphas, 24));
ch2 = argbBlendSIMD(ch2, destCols);
// if alpha is 0 or 255
ch1 = vorrq_u32(srcCols, vmovq_n_u32(0xff000000));
// mask and or them together
mask = vorrq_u32(vceqq_u32(alphas, vmovq_n_u32(0)), vceqq_u32(alphas, vmovq_n_u32(0xff)));
ch1 = vandq_u32(ch1, mask);
ch2 = vandq_u32(ch2, vmvnq_u32(mask));
return vorrq_u32(ch1, ch2);
case kRgbToRgbBlender: // see BITMAP member function blendRgbToRgb
return rgbBlendSIMD(srcCols, destCols, alphas, false);
case kAlphaPreservedBlenderMode: // see BITMAP member function blendPreserveAlpha
return rgbBlendSIMD(srcCols, destCols, alphas, true);
case kOpaqueBlenderMode: // see BITMAP member function blendOpaque
return vorrq_u32(srcCols, vmovq_n_u32(0xff000000));
case kAdditiveBlenderMode: // see BITMAP member function blendAdditiveAlpha
srcAlphas = vaddq_u32(vshrq_n_u32(srcCols, 24), vshrq_n_u32(destCols, 24));
srcAlphas = vminq_u32(srcAlphas, vmovq_n_u32(0xff));
srcCols = vandq_u32(srcCols, vmovq_n_u32(0x00ffffff));
return vorrq_u32(srcCols, vshlq_n_u32(srcAlphas, 24));
case kTintBlenderMode: // see BITMAP member function blendTintSprite
return blendTintSpriteSIMD(srcCols, destCols, alphas, false);
case kTintLightBlenderMode: // see BITMAP member function blendTintSprite
return blendTintSpriteSIMD(srcCols, destCols, alphas, true);
}
return srcCols;
}
static inline uint16x8_t blendPixelSIMD2Bpp(uint16x8_t srcCols, uint16x8_t destCols, uint16x8_t alphas) {
uint16x8_t mask, ch1, ch2;
switch (_G(_blender_mode)) {
case kSourceAlphaBlender:
case kOpaqueBlenderMode:
case kAdditiveBlenderMode:
return srcCols;
case kArgbToArgbBlender:
case kArgbToRgbBlender:
ch1 = vandq_u16(vmovq_n_u16(0xff), vceqq_u16(alphas, vmovq_n_u16(0)));
ch2 = vandq_u16(alphas, vcgtq_u16(alphas, vmovq_n_u16(0)));
alphas = vorrq_u16(ch1, ch2);
// fall through
case kRgbToRgbBlender:
case kAlphaPreservedBlenderMode:
return rgbBlendSIMD2Bpp(srcCols, destCols, alphas);
case kRgbToArgbBlender:
mask = vorrq_u16(vceqq_u16(alphas, vmovq_n_u16(0)), vceqq_u16(alphas, vmovq_n_u16(255)));
ch1 = vandq_u16(srcCols, mask);
ch2 = vandq_u16(rgbBlendSIMD2Bpp(srcCols, destCols, alphas), vmvnq_u16(mask));
return vorrq_u16(ch1, ch2);
case kTintBlenderMode:
case kTintLightBlenderMode:
uint32x4_t srcColsLo = simd2BppTo4Bpp(vget_low_u16(srcCols));
uint32x4_t srcColsHi = simd2BppTo4Bpp(vget_high_u16(srcCols));
uint32x4_t destColsLo = simd2BppTo4Bpp(vget_low_u16(destCols));
uint32x4_t destColsHi = simd2BppTo4Bpp(vget_high_u16(destCols));
uint32x4_t alphasLo = vmovl_u16(vget_low_u16(alphas));
uint32x4_t alphasHi = vmovl_u16(vget_high_u16(alphas));
uint16x4_t lo = simd4BppTo2Bpp(blendTintSpriteSIMD(srcColsLo, destColsLo, alphasLo, _G(_blender_mode) == kTintLightBlenderMode));
uint16x4_t hi = simd4BppTo2Bpp(blendTintSpriteSIMD(srcColsHi, destColsHi, alphasHi, _G(_blender_mode) == kTintLightBlenderMode));
return vcombine_u16(lo, hi);
}
return srcCols;
}
template<int DestBytesPerPixel, int SrcBytesPerPixel>
static inline void drawPixelSIMD(byte *destPtr, const byte *srcP2, uint32x4_t tint, uint32x4_t alphas, uint32x4_t maskedAlphas, uint32x4_t transColors, int xDir, int xCtrBpp, int srcAlpha, int skipTrans, bool horizFlip, bool useTint, uint32x4_t skipMask) {
uint32x4_t srcCols, destCol;
if (DestBytesPerPixel == 4)
destCol = vld1q_u32((uint32 *)destPtr);
else
destCol = simd2BppTo4Bpp(vld1_u16((uint16 *)destPtr));
if (SrcBytesPerPixel == 4)
srcCols = vld1q_u32((const uint32 *)(srcP2 + xDir * xCtrBpp));
else
srcCols = simd2BppTo4Bpp(vld1_u16((const uint16 *)(srcP2 + xDir * xCtrBpp)));
// we do this here because we need to check if we should skip the pixel before we blend it
uint32x4_t mask1 = skipTrans ? vceqq_u32(vandq_u32(srcCols, maskedAlphas), transColors) : vmovq_n_u32(0);
mask1 = vorrq_u32(mask1, skipMask);
if (srcAlpha != -1) {
// take into account for useTint
if (useTint) {
srcCols = blendPixelSIMD(tint, srcCols, alphas);
} else {
srcCols = blendPixelSIMD(srcCols, destCol, alphas);
}
}
uint32x4_t destCols2 = vandq_u32(destCol, mask1);
uint32x4_t srcCols2 = vandq_u32(srcCols, vmvnq_u32(mask1));
uint32x4_t final = vorrq_u32(destCols2, srcCols2);
if (horizFlip) {
final = vrev64q_u32(final);
final = vcombine_u32(vget_high_u32(final), vget_low_u32(final));
}
if (DestBytesPerPixel == 4) {
vst1q_u32((uint32 *)destPtr, final);
} else {
vst1_u16((uint16 *)destPtr, simd4BppTo2Bpp(final));
}
}
static inline void drawPixelSIMD2Bpp(byte *destPtr, const byte *srcP2, uint16x8_t tint, uint16x8_t alphas, uint16x8_t transColors, int xDir, int xCtrBpp, int srcAlpha, int skipTrans, bool horizFlip, bool useTint, uint16x8_t skipMask) {
uint16x8_t destCol = vld1q_u16((uint16 *)destPtr);
uint16x8_t srcCols = vld1q_u16((const uint16 *)(srcP2 + xDir * xCtrBpp));
uint16x8_t mask1 = skipTrans ? vceqq_u16(srcCols, transColors) : vmovq_n_u16(0);
mask1 = vorrq_u16(mask1, skipMask);
if (srcAlpha != -1) {
// take into account for useTint
if (useTint) {
srcCols = blendPixelSIMD2Bpp(tint, srcCols, alphas);
} else {
srcCols = blendPixelSIMD2Bpp(srcCols, destCol, alphas);
}
}
uint16x8_t destCols2 = vandq_u16(destCol, mask1);
uint16x8_t srcCols2 = vandq_u16(srcCols, vmvnq_u16(mask1));
uint16x8_t final = vorrq_u16(destCols2, srcCols2);
if (horizFlip) {
final = vrev64q_u16(final);
final = vcombine_u16(vget_high_u16(final), vget_low_u16(final));
}
vst1q_u16((uint16 *)destPtr, final);
}
public:
// This template handles 2bpp and 4bpp, the other specializations handle 1bpp and format conversion blits
template<int DestBytesPerPixel, int SrcBytesPerPixel, bool Scale>
static void drawInner4BppWithConv(BITMAP::DrawInnerArgs &args) {
const int xDir = args.horizFlip ? -1 : 1;
byte rSrc, gSrc, bSrc, aSrc;
byte rDest = 0, gDest = 0, bDest = 0, aDest = 0;
uint32x4_t tint = vshlq_n_u32(vdupq_n_u32(args.srcAlpha), 24);
tint = vorrq_u32(tint, vshlq_n_u32(vdupq_n_u32(args.tintRed), 16));
tint = vorrq_u32(tint, vshlq_n_u32(vdupq_n_u32(args.tintGreen), 8));
tint = vorrq_u32(tint, vdupq_n_u32(args.tintBlue));
uint32x4_t maskedAlphas = vmovq_n_u32(args.alphaMask);
uint32x4_t transColors = vmovq_n_u32(args.transColor);
uint32x4_t alphas = vmovq_n_u32(args.srcAlpha);
// This is so that we can calculate what pixels to crop off in a vectorized way
const uint32x4_t addIndexesNormal = {0, 1, 2, 3};
const uint32x4_t addIndexesFlipped = {3, 2, 1, 0};
uint32x4_t addIndexes = args.horizFlip ? addIndexesFlipped : addIndexesNormal;
// This is so that we can calculate in parallel the pixel indexes for scaled drawing
uint32x4_t scaleAdds = {0, (uint32)args.scaleX, (uint32)args.scaleX*2, (uint32)args.scaleX*3};
// Clip the bounds ahead of time (so we don't waste time checking if we are in bounds when
// we are in the inner loop)
int xCtrStart = 0, xCtrBppStart = 0, xCtrWidth = args.dstRect.width();
if (args.xStart + xCtrWidth > args.destArea.w) {
xCtrWidth = args.destArea.w - args.xStart;
}
if (args.xStart < 0) {
xCtrStart = -args.xStart;
xCtrBppStart = xCtrStart * SrcBytesPerPixel;
args.xStart = 0;
}
int destY = args.yStart, srcYCtr = 0, yCtr = 0, scaleYCtr = 0, yCtrHeight = args.dstRect.height();
if (Scale) yCtrHeight = args.dstRect.height();
if (args.yStart < 0) {
yCtr = -args.yStart;
destY = 0;
if (Scale) {
scaleYCtr = yCtr * args.scaleY;
srcYCtr = scaleYCtr / BITMAP::SCALE_THRESHOLD;
}
}
if (args.yStart + yCtrHeight > args.destArea.h) {
yCtrHeight = args.destArea.h - args.yStart;
}
/*if (!Scale && xCtrWidth % 4 != 0) {
--yCtrHeight;
}*/
const int secondToLast = xCtrWidth - 4;
byte *destP = (byte *)args.destArea.getBasePtr(0, destY);
const byte *srcP = (const byte *)args.src.getBasePtr(
args.horizFlip ? args.srcArea.right - 4 : args.srcArea.left,
args.vertFlip ? args.srcArea.bottom - 1 - yCtr : args.srcArea.top + yCtr);
for (; yCtr < yCtrHeight; ++destY, ++yCtr, scaleYCtr += args.scaleY) {
uint32x4_t xCtrWidthSIMD = vdupq_n_u32(xCtrWidth); // This is the width of the row
if (!Scale) {
int xCtr = xCtrStart, xCtrBpp = xCtrBppStart, destX = args.xStart;
for (; xCtr < secondToLast; destX += 4, xCtr += 4, xCtrBpp += SrcBytesPerPixel*4) {
byte *destPtr = &destP[destX * DestBytesPerPixel];
drawPixelSIMD<DestBytesPerPixel, SrcBytesPerPixel>(destPtr, srcP, tint, alphas, maskedAlphas, transColors, xDir, xCtrBpp, args.srcAlpha, args.skipTrans, args.horizFlip, args.useTint, vmovq_n_u32(0));
}
byte *destPtr = &destP[destX * DestBytesPerPixel];
uint32x4_t srcCols = vmovq_n_u32(0);
uint32x4_t destCols = vmovq_n_u32(0);
memcpy(&srcCols, srcP + xDir * xCtrBpp, (xCtrWidth - xCtr) * SrcBytesPerPixel);
memcpy(&destCols, destPtr, (xCtrWidth - xCtr) * DestBytesPerPixel);
// Skip pixels that are beyond the row
// uint32x4_t skipMask = vcgeq_u32(vaddq_u32(vdupq_n_u32(xCtr), addIndexes), xCtrWidthSIMD);
drawPixelSIMD<DestBytesPerPixel, SrcBytesPerPixel>((byte *)&destCols, (byte *)&srcCols, tint, alphas, maskedAlphas, transColors, xDir, 0, args.srcAlpha, args.skipTrans, args.horizFlip, args.useTint, vmovq_n_u32(0));
memcpy(destPtr, &destCols, (xCtrWidth - xCtr) * DestBytesPerPixel);
// Goto next row in source and destination image
destP += args.destArea.pitch;
srcP += args.vertFlip ? -args.src.pitch : args.src.pitch;
} else {
// Here we are scaling the image
int newSrcYCtr = scaleYCtr / BITMAP::SCALE_THRESHOLD;
// Since the source yctr might not update every row of the destination, we have
// to see if we are on a new row...
if (srcYCtr != newSrcYCtr) {
int diffSrcYCtr = newSrcYCtr - srcYCtr; // Have we moved yet
srcP += args.src.pitch * diffSrcYCtr;
srcYCtr = newSrcYCtr;
}
// Now also since we might skip a pixel or 2 or duplicate one to reach the desired
// scaling size, we create a small dummy buffer that we copy the pixels into and then
// call the drawPixelsSIMD function
byte srcBuffer[4*4];
for (int xCtr = xCtrStart, xCtrBpp = xCtrBppStart, destX = args.xStart, scaleXCtr = xCtrStart * args.scaleX; xCtr < xCtrWidth; destX += 4, xCtr += 4, xCtrBpp += SrcBytesPerPixel*4) {
if (yCtr + 1 == yCtrHeight && xCtr + 4 > xCtrWidth) break; // Don't go past the last 4 pixels
uint32x4_t indexes = vdupq_n_u32(scaleXCtr);
// Calculate in parallel the indexes of the pixels
indexes = vmulq_n_u32(vshrq_n_u32(vaddq_u32(indexes, scaleAdds), BITMAP::SCALE_THRESHOLD_BITS), SrcBytesPerPixel);
// Simply memcpy them in. memcpy has no real performance overhead here
memcpy(&srcBuffer[0*(uintptr_t)SrcBytesPerPixel], srcP + vgetq_lane_u32(indexes, 0), SrcBytesPerPixel);
memcpy(&srcBuffer[1*(uintptr_t)SrcBytesPerPixel], srcP + vgetq_lane_u32(indexes, 1), SrcBytesPerPixel);
memcpy(&srcBuffer[2*(uintptr_t)SrcBytesPerPixel], srcP + vgetq_lane_u32(indexes, 2), SrcBytesPerPixel);
memcpy(&srcBuffer[3*(uintptr_t)SrcBytesPerPixel], srcP + vgetq_lane_u32(indexes, 3), SrcBytesPerPixel);
scaleXCtr += args.scaleX*4;
// Now this is pretty much the same as before with non-scaled code, except that we use
// our dummy source buffer instead of the actual source bitmap
byte *destPtr = &destP[destX * (uintptr_t)DestBytesPerPixel];
uint32x4_t skipMask = vcgeq_u32(vaddq_u32(vdupq_n_u32(xCtr), addIndexes), xCtrWidthSIMD);
drawPixelSIMD<DestBytesPerPixel, SrcBytesPerPixel>(destPtr, (const byte *)srcBuffer, tint, alphas, maskedAlphas, transColors, 1, 0, args.srcAlpha, args.skipTrans, args.horizFlip, args.useTint, skipMask);
}
// We calculate every row here except the last (because then we need to
// check for if we fall off the edge of the row)
// The only exception here is scaling drawing this is because:
// 1) if statements are costly, and the less we do the faster this loop is
// 2) with this, the only branch in the normal drawing loop is the width check
// 3) the scaling code will actually draw until the last 4 pixels of the image
// and do the extra if checks because the scaling code is already much slower
// than the normal drawing loop, and the less duplicate code helps here.
if (yCtr + 1 != yCtrHeight) destP += args.destArea.pitch;
}
}
// Get the last x values of the last row
int xCtr = xCtrStart, xCtrBpp = xCtrBppStart, destX = args.xStart;
// We have a picture that is a multiple of 4, so no extra pixels to draw
/*if (xCtrWidth % 4 == 0)*/ return;
// Drawing the last few not scaled pixels here.
// Same as the loop above but now we check if we are going to overflow,
// and thus we don't need to mask out pixels that go over the row.
if (!Scale) {
for (; xCtr + 4 < xCtrWidth; destX += 4, xCtr += 4, xCtrBpp += SrcBytesPerPixel*4) {
byte *destPtr = &destP[(ptrdiff_t)destX * DestBytesPerPixel];
drawPixelSIMD<DestBytesPerPixel, SrcBytesPerPixel>(destPtr, srcP, tint, alphas, maskedAlphas, transColors, xDir, xCtrBpp, args.srcAlpha, args.skipTrans, args.horizFlip, args.useTint, vmovq_n_u32(0));
}
// Because we move in 4 pixel units, and horizFlip moves in 1, we have to move
// 1 pixel past the last pixel we did not blit, meaning going forward 3 pixels.
if (args.horizFlip) srcP += SrcBytesPerPixel * 3;
} else {
// So if we are scaling, set up the xCtr to what it was before (AKA the last 4 or so pixels of the image)
xCtr = xCtrWidth - xCtrWidth % 4;
xCtrBpp = xCtr * SrcBytesPerPixel;
destX = args.xStart+xCtr;
}
// For the last 4 pixels, we just do them in serial, nothing special
for (; xCtr < xCtrWidth; ++destX, ++xCtr, xCtrBpp += SrcBytesPerPixel) {
const byte *srcColPtr = (const byte *)(srcP + xDir * xCtrBpp);
if (Scale) {
srcColPtr = (const byte *)(srcP + (xCtr * args.scaleX) / BITMAP::SCALE_THRESHOLD * SrcBytesPerPixel);
}
byte *destVal = (byte *)&destP[destX * DestBytesPerPixel];
uint32 srcCol = args.dstBitmap.getColor(srcColPtr, SrcBytesPerPixel);
// Check if this is a transparent color we should skip
if (args.skipTrans && ((srcCol & args.alphaMask) == args.transColor))
continue;
args.src.format.colorToARGB(srcCol, aSrc, rSrc, gSrc, bSrc);
if (args.srcAlpha != -1) {
if (args.useTint) {
rDest = rSrc;
gDest = gSrc;
bDest = bSrc;
aDest = aSrc;
rSrc = args.tintRed;
gSrc = args.tintGreen;
bSrc = args.tintBlue;
aSrc = args.srcAlpha;
}
args.dstBitmap.blendPixel(aSrc, rSrc, gSrc, bSrc, aDest, rDest, gDest, bDest, args.srcAlpha, args.useTint, destVal);
srcCol = args.dstBitmap.format.ARGBToColor(aDest, rDest, gDest, bDest);
} else {
srcCol = args.dstBitmap.format.ARGBToColor(aSrc, rSrc, gSrc, bSrc);
}
if (DestBytesPerPixel == 4)
*(uint32 *)destVal = srcCol;
else
*(uint16 *)destVal = srcCol;
}
}
template<bool Scale>
static void drawInner2Bpp(BITMAP::DrawInnerArgs &args) {
const int xDir = args.horizFlip ? -1 : 1;
byte rSrc, gSrc, bSrc, aSrc;
byte rDest = 0, gDest = 0, bDest = 0, aDest = 0;
uint16x8_t tint = vdupq_n_u16(args.src.format.ARGBToColor(args.srcAlpha, args.tintRed, args.tintGreen, args.tintBlue));
uint16x8_t transColors = vdupq_n_u16(args.transColor);
uint16x8_t alphas = vdupq_n_u16(args.srcAlpha);
// This is so that we can calculate what pixels to crop off in a vectorized way
uint16x8_t addIndexesNormal = {0, 1, 2, 3, 4, 5, 6, 7};
uint16x8_t addIndexesFlipped = {7, 6, 5, 4, 3, 2, 1, 0};
uint16x8_t addIndexes = args.horizFlip ? addIndexesFlipped : addIndexesNormal;
// This is so that we can calculate in parallel the pixel indices for scaled drawing
uint32x4_t scaleAdds = {0, (uint32)args.scaleX, (uint32)args.scaleX*2, (uint32)args.scaleX*3};
uint32x4_t scaleAdds2 = {(uint32)args.scaleX*4, (uint32)args.scaleX*5, (uint32)args.scaleX*6, (uint32)args.scaleX*7};
// Clip the bounds ahead of time (so we don't waste time checking if we are in bounds when
// we are in the inner loop)
int xCtrStart = 0, xCtrBppStart = 0, xCtrWidth = args.dstRect.width();
if (args.xStart + xCtrWidth > args.destArea.w) {
xCtrWidth = args.destArea.w - args.xStart;
}
if (args.xStart < 0) {
xCtrStart = -args.xStart;
xCtrBppStart = xCtrStart * 2;
args.xStart = 0;
}
int destY = args.yStart, yCtr = 0, srcYCtr = 0, scaleYCtr = 0, yCtrHeight = args.dstRect.height();
if (Scale) yCtrHeight = args.dstRect.height();
if (args.yStart < 0) {
yCtr = -args.yStart;
destY = 0;
if (Scale) {
scaleYCtr = yCtr * args.scaleY;
srcYCtr = scaleYCtr / BITMAP::SCALE_THRESHOLD;
}
}
if (args.yStart + yCtrHeight > args.destArea.h) {
yCtrHeight = args.destArea.h - args.yStart;
}
/*if (!Scale && xCtrWidth % 8 != 0) {
--yCtrHeight;
}*/
const int secondToLast = xCtrWidth - 8;
byte *destP = (byte *)args.destArea.getBasePtr(0, destY);
const byte *srcP = (const byte *)args.src.getBasePtr(
args.horizFlip ? args.srcArea.right - 8 : args.srcArea.left,
args.vertFlip ? args.srcArea.bottom - 1 - yCtr : args.srcArea.top + yCtr);
for (; yCtr < yCtrHeight; ++destY, ++yCtr, scaleYCtr += args.scaleY) {
uint16x8_t xCtrWidthSIMD = vmovq_n_u16(xCtrWidth); // This is the width of the row
if (!Scale) {
// If we are not scaling the image
int xCtr = xCtrStart, xCtrBpp = xCtrBppStart, destX = args.xStart;
for (; xCtr < secondToLast; destX += 8, xCtr += 8, xCtrBpp += 16) {
byte *destPtr = &destP[destX * 2];
drawPixelSIMD2Bpp(destPtr, srcP, tint, alphas, transColors, xDir, xCtrBpp, args.srcAlpha, args.skipTrans, args.horizFlip, args.useTint, vmovq_n_u16(0));
}
byte *destPtr = &destP[destX * 2];
uint16x8_t srcCols = vmovq_n_u16(0);
uint16x8_t destCols = vmovq_n_u16(0);
const int copySize = (xCtrWidth - xCtr) * 2;
memcpy(&srcCols, srcP + xDir * xCtrBpp, copySize);
memcpy(&destCols, destPtr, copySize);
// Skip pixels that are beyond the row
// uint16x8_t skipMask = vcgeq_u16(vaddq_u16(vdupq_n_u16(xCtr), addIndexes), xCtrWidthSIMD);
drawPixelSIMD2Bpp((byte *)&destCols, (byte *)&srcCols, tint, alphas, transColors, xDir, 0, args.srcAlpha, args.skipTrans, args.horizFlip, args.useTint, vmovq_n_u16(0));
memcpy(destPtr, &destCols, copySize);
// Goto next row in source and destination image
destP += args.destArea.pitch;
srcP += args.vertFlip ? -args.src.pitch : args.src.pitch;
} else {
// Here we are scaling the image
int newSrcYCtr = scaleYCtr / BITMAP::SCALE_THRESHOLD;
// Since the source yctr might not update every row of the destination, we have
// to see if we are on a new row...
if (srcYCtr != newSrcYCtr) {
int diffSrcYCtr = newSrcYCtr - srcYCtr;
srcP += args.src.pitch * diffSrcYCtr;
srcYCtr = newSrcYCtr;
}
// Now also since we might skip a pixel or 2 or duplicate one to reach the desired
// scaling size, we create a small dummy buffer that we copy the pixels into and then
// call the drawPixelsSIMD function
uint16 srcBuffer[8];
for (int xCtr = xCtrStart, xCtrBpp = xCtrBppStart, destX = args.xStart, scaleXCtr = xCtrStart * args.scaleX; xCtr < xCtrWidth; destX += 8, xCtr += 8, xCtrBpp += 16) {
if (yCtr + 1 == yCtrHeight && xCtr + 8 > xCtrWidth) break;
uint32x4_t indexes = vdupq_n_u32(scaleXCtr), indexes2 = vdupq_n_u32(scaleXCtr);
// Calculate in parallel the indices of the pixels
indexes = vmulq_n_u32(vshrq_n_u32(vaddq_u32(indexes, scaleAdds), BITMAP::SCALE_THRESHOLD_BITS), 2);
indexes2 = vmulq_n_u32(vshrq_n_u32(vaddq_u32(indexes2, scaleAdds2), BITMAP::SCALE_THRESHOLD_BITS), 2);
// Simply memcpy them in. memcpy has no real performance overhead here
srcBuffer[0] = *(const uint16 *)(srcP + vgetq_lane_u32(indexes, 0));
srcBuffer[1] = *(const uint16 *)(srcP + vgetq_lane_u32(indexes, 1));
srcBuffer[2] = *(const uint16 *)(srcP + vgetq_lane_u32(indexes, 2));
srcBuffer[3] = *(const uint16 *)(srcP + vgetq_lane_u32(indexes, 3));
srcBuffer[4] = *(const uint16 *)(srcP + vgetq_lane_u32(indexes2, 0));
srcBuffer[5] = *(const uint16 *)(srcP + vgetq_lane_u32(indexes2, 1));
srcBuffer[6] = *(const uint16 *)(srcP + vgetq_lane_u32(indexes2, 2));
srcBuffer[7] = *(const uint16 *)(srcP + vgetq_lane_u32(indexes2, 3));
scaleXCtr += args.scaleX*8;
// Now this is pretty much the same as before with non-scaled code, except that we use
// our dummy source buffer instead of the actual source bitmap
byte *destPtr = &destP[destX * 2];
uint16x8_t skipMask = vcgeq_u16(vaddq_u16(vdupq_n_u16(xCtr), addIndexes), xCtrWidthSIMD);
drawPixelSIMD2Bpp(destPtr, (const byte *)srcBuffer, tint, alphas, transColors, 1, 0, args.srcAlpha, args.skipTrans, args.horizFlip, args.useTint, skipMask);
}
// We calculate every row here except the last (because then we need to
// check for if we fall off the edge of the row)
// The only exception here is scaling drawing this is because:
// 1) if statements are costly, and the less we do the faster this loop is
// 2) with this, the only branch in the normal drawing loop is the width check
// 3) the scaling code will actually draw until the last 4 pixels of the image
// and do the extra if checks because the scaling code is already much slower
// than the normal drawing loop, and the less duplicate code helps here.
if (yCtr + 1 != yCtrHeight) destP += args.destArea.pitch;
}
}
// We have a picture that is a multiple of 8, so no extra pixels to draw
/*if (xCtrWidth % 8 == 0)*/ return;
// Get the last x values of the last row
int xCtr = xCtrStart, xCtrBpp = xCtrBppStart, destX = args.xStart;
// Drawing the last few not scaled pixels here.
// Same as the loop above but now we check if we are going to overflow,
// and thus we don't need to mask out pixels that go over the row.
if (!Scale) {
for (; xCtr + 8 < xCtrWidth; destX += 8, xCtr += 8, xCtrBpp += 16) {
byte *destPtr = &destP[destX * 2];
drawPixelSIMD2Bpp(destPtr, srcP, tint, alphas, transColors, xDir, xCtrBpp, args.srcAlpha, args.skipTrans, args.horizFlip, args.useTint, vmovq_n_u16(0));
}
// Because we move in 8 pixel units, and horizFlip moves in 1, we have to move
// 1 pixel past the last pixel we did not blit, meaning going forward 7 pixels.
if (args.horizFlip) srcP += 2 * 7;
} else {
// So if we are scaling, set up the xCtr to what it was before (AKA the last 8 or so pixels of the image)
xCtr = xCtrWidth - xCtrWidth % 8;
xCtrBpp = xCtr * 2;
destX = args.xStart+xCtr;
}
// For the last 4 pixels, we just do them in serial, nothing special
for (; xCtr < xCtrWidth; ++destX, ++xCtr, xCtrBpp += 2) {
const byte *srcColPtr = (const byte *)(srcP + xDir * xCtrBpp);
if (Scale) {
srcColPtr = (const byte *)(srcP + (xCtr * args.scaleX) / BITMAP::SCALE_THRESHOLD * 2);
}
byte *destVal = (byte *)&destP[destX * 2];
uint32 srcCol = (uint32)(*(const uint16 *)srcColPtr);
// Check if this is a transparent color we should skip
if (args.skipTrans && srcCol == args.transColor)
continue;
args.src.format.colorToARGB(srcCol, aSrc, rSrc, gSrc, bSrc);
if (args.srcAlpha != -1) {
if (args.useTint) {
rDest = rSrc;
gDest = gSrc;
bDest = bSrc;
aDest = aSrc;
rSrc = args.tintRed;
gSrc = args.tintGreen;
bSrc = args.tintBlue;
aSrc = args.srcAlpha;
}/* else {
format.colorToARGB((uint32)(*(uint16 *)destVal), aDest, rDest, gDest, bDest);
}*/
args.dstBitmap.blendPixel(aSrc, rSrc, gSrc, bSrc, aDest, rDest, gDest, bDest, args.srcAlpha, args.useTint, destVal);
srcCol = args.dstBitmap.format.ARGBToColor(aDest, rDest, gDest, bDest);
} else {
srcCol = args.dstBitmap.format.ARGBToColor(aSrc, rSrc, gSrc, bSrc);
}
*(uint16 *)destVal = srcCol;
}
}
template<bool Scale>
static void drawInner1Bpp(BITMAP::DrawInnerArgs &args) {
const int xDir = args.horizFlip ? -1 : 1;
uint8x16_t transColors = vmovq_n_u8(args.transColor);
// This is so that we can calculate in parallel the pixel indices for scaled drawing
uint32x4_t scaleAdds1 = {0, (uint32)args.scaleX, (uint32)args.scaleX*2, (uint32)args.scaleX*3};
uint32x4_t scaleAdds2 = {(uint32)args.scaleX*4, (uint32)args.scaleX*5, (uint32)args.scaleX*6, (uint32)args.scaleX*7};
uint32x4_t scaleAdds3 = {(uint32)args.scaleX*8, (uint32)args.scaleX*9, (uint32)args.scaleX*10, (uint32)args.scaleX*11};
uint32x4_t scaleAdds4 = {(uint32)args.scaleX*12, (uint32)args.scaleX*13, (uint32)args.scaleX*14, (uint32)args.scaleX*15};
// Clip the bounds ahead of time (so we don't waste time checking if we are in bounds when
// we are in the inner loop)
int xCtrStart = 0, xCtrWidth = args.dstRect.width();
if (args.xStart + xCtrWidth > args.destArea.w) {
xCtrWidth = args.destArea.w - args.xStart;
}
if (args.xStart < 0) {
xCtrStart = -args.xStart;
args.xStart = 0;
}
int destY = args.yStart, yCtr = 0, srcYCtr = 0, scaleYCtr = 0, yCtrHeight = args.dstRect.height();
if (Scale) yCtrHeight = args.dstRect.height();
if (args.yStart < 0) {
yCtr = -args.yStart;
destY = 0;
if (Scale) {
scaleYCtr = yCtr * args.scaleY;
srcYCtr = scaleYCtr / BITMAP::SCALE_THRESHOLD;
}
}
if (args.yStart + yCtrHeight > args.destArea.h) {
yCtrHeight = args.destArea.h - args.yStart;
}
byte *destP = (byte *)args.destArea.getBasePtr(0, destY);
const byte *srcP = (const byte *)args.src.getBasePtr(
args.horizFlip ? args.srcArea.right - 16 : args.srcArea.left,
args.vertFlip ? args.srcArea.bottom - 1 - yCtr : args.srcArea.top + yCtr);
for (; yCtr < yCtrHeight; ++destY, ++yCtr, scaleYCtr += args.scaleY) {
if (Scale) {
// So here we update the srcYCtr differently due to this being for
// scaling
int newSrcYCtr = scaleYCtr / BITMAP::SCALE_THRESHOLD;
if (srcYCtr != newSrcYCtr) {
// Since the source yctr might not update every row of the destination, we have
// to see if we are on a new row...
int diffSrcYCtr = newSrcYCtr - srcYCtr;
srcP += args.src.pitch * diffSrcYCtr;
srcYCtr = newSrcYCtr;
}
}
int xCtr = xCtrStart, destX = args.xStart, scaleXCtr = xCtrStart * args.scaleX;
for (; xCtr + 16 < xCtrWidth; destX += 16, xCtr += 16) {
byte *destPtr = &destP[destX];
// Here we don't use the drawPixelSIMD function because 1bpp bitmaps in allegro
// can't have any blending applied to them
uint8x16_t destCols = vld1q_u8(destPtr);
uint8x16_t srcCols = vld1q_u8(srcP + xDir * xCtr);
if (Scale) {
// If we are scaling, we have to set each pixel individually
uint32x4_t indexes1 = vdupq_n_u32(scaleXCtr), indexes2 = vdupq_n_u32(scaleXCtr);
uint32x4_t indexes3 = vdupq_n_u32(scaleXCtr), indexes4 = vdupq_n_u32(scaleXCtr);
indexes1 = vshrq_n_u32(vaddq_u32(indexes1, scaleAdds1), BITMAP::SCALE_THRESHOLD_BITS);
indexes2 = vshrq_n_u32(vaddq_u32(indexes2, scaleAdds2), BITMAP::SCALE_THRESHOLD_BITS);
indexes3 = vshrq_n_u32(vaddq_u32(indexes3, scaleAdds3), BITMAP::SCALE_THRESHOLD_BITS);
indexes4 = vshrq_n_u32(vaddq_u32(indexes4, scaleAdds4), BITMAP::SCALE_THRESHOLD_BITS);
srcCols = vsetq_lane_u8(srcP[vgetq_lane_u32(indexes1, 0)], srcCols, 0);
srcCols = vsetq_lane_u8(srcP[vgetq_lane_u32(indexes1, 1)], srcCols, 1);
srcCols = vsetq_lane_u8(srcP[vgetq_lane_u32(indexes1, 2)], srcCols, 2);
srcCols = vsetq_lane_u8(srcP[vgetq_lane_u32(indexes1, 3)], srcCols, 3);
srcCols = vsetq_lane_u8(srcP[vgetq_lane_u32(indexes2, 0)], srcCols, 4);
srcCols = vsetq_lane_u8(srcP[vgetq_lane_u32(indexes2, 1)], srcCols, 5);
srcCols = vsetq_lane_u8(srcP[vgetq_lane_u32(indexes2, 2)], srcCols, 6);
srcCols = vsetq_lane_u8(srcP[vgetq_lane_u32(indexes2, 3)], srcCols, 7);
srcCols = vsetq_lane_u8(srcP[vgetq_lane_u32(indexes3, 0)], srcCols, 8);
srcCols = vsetq_lane_u8(srcP[vgetq_lane_u32(indexes3, 1)], srcCols, 9);
srcCols = vsetq_lane_u8(srcP[vgetq_lane_u32(indexes3, 2)], srcCols, 10);
srcCols = vsetq_lane_u8(srcP[vgetq_lane_u32(indexes3, 3)], srcCols, 11);
srcCols = vsetq_lane_u8(srcP[vgetq_lane_u32(indexes4, 0)], srcCols, 12);
srcCols = vsetq_lane_u8(srcP[vgetq_lane_u32(indexes4, 1)], srcCols, 13);
srcCols = vsetq_lane_u8(srcP[vgetq_lane_u32(indexes4, 2)], srcCols, 14);
srcCols = vsetq_lane_u8(srcP[vgetq_lane_u32(indexes4, 3)], srcCols, 15);
scaleXCtr += args.scaleX*16;
}
// Mask out transparent pixels
uint8x16_t mask1 = args.skipTrans ? vceqq_u8(srcCols, transColors) : vmovq_n_u8(0);
uint8x16_t final = vorrq_u8(vandq_u8(srcCols, vmvnq_u8(mask1)), vandq_u8(destCols, mask1));
if (args.horizFlip) {
final = vrev64q_u8(final);
final = vcombine_u8(vget_high_u8(final), vget_low_u8(final));
}
vst1q_u8(destPtr, final);
}
// Get the last x values
// Because we move in 16 pixel units, and horizFlip moves in 1, we have to move
// 1 pixel past the last pixel we did not blit, meaning going forward 15 pixels.
if (args.horizFlip) srcP += 15;
for (; xCtr < xCtrWidth; ++destX, ++xCtr, scaleXCtr += args.scaleX) {
const byte *srcCol = (const byte *)(srcP + xDir * xCtr);
if (Scale) {
srcCol = (const byte *)(srcP + scaleXCtr / BITMAP::SCALE_THRESHOLD);
}
// Check if this is a transparent color we should skip
if (args.skipTrans && *srcCol == args.transColor)
continue;
byte *destVal = (byte *)&destP[destX];
*destVal = *srcCol;
}
if (args.horizFlip) srcP -= 15; // Undo what we did up there
destP += args.destArea.pitch; // Go to next row
// Only advance the src row by 1 every time like this if we don't scale
if (!Scale) srcP += args.vertFlip ? -args.src.pitch : args.src.pitch;
}
}
}; // end of class DrawInnerImpl_NEON
template<bool Scale>
void BITMAP::drawNEON(DrawInnerArgs &args) {
if (args.sameFormat) {
switch (format.bytesPerPixel) {
case 1: DrawInnerImpl_NEON::drawInner1Bpp<Scale>(args); break;
case 2: DrawInnerImpl_NEON::drawInner2Bpp<Scale>(args); break;
case 4: DrawInnerImpl_NEON::drawInner4BppWithConv<4, 4, Scale>(args); break;
}
} else if (format.bytesPerPixel == 4 && args.src.format.bytesPerPixel == 2) {
DrawInnerImpl_NEON::drawInner4BppWithConv<4, 2, Scale>(args);
} else if (format.bytesPerPixel == 2 && args.src.format.bytesPerPixel == 4) {
DrawInnerImpl_NEON::drawInner4BppWithConv<2, 4, Scale>(args);
}
}
template void BITMAP::drawNEON<false>(DrawInnerArgs &);
template void BITMAP::drawNEON<true>(DrawInnerArgs &);
} // namespace AGS3
#if !defined(__aarch64__) && !defined(__ARM_NEON)
#if defined(__clang__)
#pragma clang attribute pop
#elif defined(__GNUC__)
#pragma GCC pop_options
#endif
#endif // !defined(__aarch64__) && !defined(__ARM_NEON)
#endif // SCUMMVM_NEON

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,74 @@
/* 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/>.
*
*/
#include "ags/lib/allegro/system.h"
#include "ags/lib/allegro/aintern.h"
#include "ags/globals.h"
#include "common/system.h"
namespace AGS3 {
GFX_MODE_LIST *get_gfx_mode_list(int card) {
GFX_MODE_LIST *list = new GFX_MODE_LIST();
list->num_modes = 1;
list->mode = new GFX_MODE[1];
GFX_MODE &gm = list->mode[0];
gm.width = 320;
gm.height = 200;
gm.bpp = 32;
return list;
}
void destroy_gfx_mode_list(GFX_MODE_LIST *list) {
delete[] list->mode;
delete list;
}
void set_color_depth(int depth) {
_G(_color_depth) = depth;
}
int get_color_depth() {
return _G(_color_depth);
}
int get_desktop_resolution(int32_t *width, int32_t *height) {
// TODO: ScummVM has a hardcoded dummy desktop resolution. See if there's any
// need to change the values, given we're hardcoded for pretend full-screen
if (width)
*width = 640;
if (height)
*height = 480;
return 0;
}
void request_refresh_rate(int rate) {
// No implementation
}
void set_close_button_callback(void(*proc)()) {
// No implementation
}
} // namespace AGS3

View File

@@ -0,0 +1,151 @@
/* 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/>.
*
*/
#ifndef AGS_LIB_ALLEGRO_SYSTEM_H
#define AGS_LIB_ALLEGRO_SYSTEM_H
#include "ags/lib/allegro/base.h"
#include "ags/lib/allegro/color.h"
#include "ags/lib/allegro/gfx.h"
#include "ags/shared/core/types.h"
namespace AGS3 {
#ifndef AL_METHOD
#define AL_METHOD(type, name, args) type (*name) args
#endif
#define SYSTEM_AUTODETECT 0
#define SYSTEM_SCUMMVM AL_ID('S','C','V','M')
#define SYSTEM_NONE AL_ID('N','O','N','E')
#define GFX_SCUMMVM AL_ID('S', 'C', 'V', 'M')
#define SWITCH_NONE 0
#define SWITCH_PAUSE 1
#define SWITCH_AMNESIA 2
#define SWITCH_BACKGROUND 3
#define SWITCH_BACKAMNESIA 4
#define SWITCH_IN 0
#define SWITCH_OUT 1
struct GFX_MODE {
int width, height, bpp;
};
struct GFX_MODE_LIST {
int num_modes; /* number of gfx modes */
GFX_MODE *mode; /* pointer to the actual mode list array */
};
struct SYSTEM_DRIVER {
int id;
const char *name;
const char *desc;
const char *ascii_name;
AL_METHOD(int, init, (void));
AL_METHOD(void, exit, (void));
AL_METHOD(void, get_executable_name, (char *output, int size));
AL_METHOD(int, find_resource, (char *dest, const char *resource, int size));
AL_METHOD(void, set_window_title, (const char *name));
AL_METHOD(int, set_close_button_callback, (AL_METHOD(void, proc, (void))));
AL_METHOD(void, message, (const char *msg));
AL_METHOD(void, assert, (const char *msg));
AL_METHOD(void, save_console_state, (void));
AL_METHOD(void, restore_console_state, (void));
AL_METHOD(BITMAP *, create_bitmap, (int color_depth, int width, int height));
AL_METHOD(void, created_bitmap, (BITMAP *bmp));
AL_METHOD(BITMAP *, create_sub_bitmap, (BITMAP *parent, int x, int y, int width, int height));
AL_METHOD(void, created_sub_bitmap, (BITMAP *bmp, BITMAP *parent));
AL_METHOD(int, destroy_bitmap, (BITMAP *bitmap));
AL_METHOD(void, read_hardware_palette, (void));
AL_METHOD(void, set_palette_range, (const RGB *p, int from, int to, int retracesync));
AL_METHOD(struct GFX_VTABLE *, get_vtable, (int color_depth));
AL_METHOD(int, set_display_switch_mode, (int mode));
AL_METHOD(void, display_switch_lock, (int lock, int foreground));
AL_METHOD(int, desktop_color_depth, (void));
AL_METHOD(int, get_desktop_resolution, (int *width, int *height));
AL_METHOD(void, get_gfx_safe_mode, (int *driver, struct GFX_MODE *mode));
AL_METHOD(void, yield_timeslice, (void));
AL_METHOD(void *, create_mutex, (void));
AL_METHOD(void, destroy_mutex, (void *handle));
AL_METHOD(void, lock_mutex, (void *handle));
AL_METHOD(void, unlock_mutex, (void *handle));
};
/* creates and manages the screen bitmap */
struct GFX_DRIVER {
int id;
AL_CONST char *name;
AL_CONST char *desc;
AL_CONST char *ascii_name;
AL_METHOD(BITMAP *, init, (int w, int h, int v_w, int v_h, int color_depth));
AL_METHOD(void, exit, (BITMAP *b));
AL_METHOD(int, scroll, (int x, int y));
AL_METHOD(void, vsync, (void));
AL_METHOD(void, set_palette, (AL_CONST RGB *p, int from, int to, int retracesync));
AL_METHOD(int, request_scroll, (int x, int y));
AL_METHOD(int, poll_scroll, (void));
AL_METHOD(void, enable_triple_buffer, (void));
AL_METHOD(BITMAP *, create_video_bitmap, (int width, int height));
AL_METHOD(void, destroy_video_bitmap, (BITMAP *bitmap));
AL_METHOD(int, show_video_bitmap, (BITMAP *bitmap));
AL_METHOD(int, request_video_bitmap, (BITMAP *bitmap));
AL_METHOD(BITMAP *, create_system_bitmap, (int width, int height));
AL_METHOD(void, destroy_system_bitmap, (BITMAP *bitmap));
AL_METHOD(int, set_mouse_sprite, (BITMAP *sprite, int xfocus, int yfocus));
AL_METHOD(int, show_mouse, (BITMAP *bmp, int x, int y));
AL_METHOD(void, hide_mouse, (void));
AL_METHOD(void, move_mouse, (int x, int y));
AL_METHOD(void, save_video_state, (void));
AL_METHOD(void, restore_video_state, (void));
AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a));
AL_METHOD(GFX_MODE_LIST *, fetch_mode_list, (void));
int w, h; /* physical (not virtual!) screen size */
int linear; /* true if video memory is linear */
long bank_size; /* bank size, in bytes */
long bank_gran; /* bank granularity, in bytes */
long vid_mem; /* video memory size, in bytes */
long vid_phys_base; /* physical address of video memory */
int windowed; /* true if driver runs windowed */
};
extern void set_color_depth(int depth);
extern int get_color_depth();
extern int get_desktop_resolution(int32_t *width, int32_t *height);
extern void request_refresh_rate(int rate);
extern void set_close_button_callback(void(*proc)());
extern GFX_MODE_LIST *get_gfx_mode_list(int card);
extern void destroy_gfx_mode_list(GFX_MODE_LIST *list);
inline void vsync() {}
inline int set_display_switch_callback(int dir, AL_METHOD(void, cb, (void))) {
return 0;
}
inline int set_display_switch_mode(int v) {
return -1;
}
} // namespace AGS3
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,151 @@
/* 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/>.
*
*/
#ifndef AGS_LIB_ALLEGRO_UNICODE_H
#define AGS_LIB_ALLEGRO_UNICODE_H
#include "ags/lib/allegro/base.h"
namespace AGS3 {
#define U_ASCII AL_ID('A','S','C','8')
#define U_ASCII_CP AL_ID('A','S','C','P')
#define U_UNICODE AL_ID('U','N','I','C')
#define U_UTF8 AL_ID('U','T','F','8')
#define U_CURRENT AL_ID('c','u','r','.')
/* UTF-8 support functions
*/
extern int utf8_getc(const char *s);
extern int utf8_getx(char **s);
extern int utf8_setc(char *s, int c);
extern int utf8_width(const char *s);
extern int utf8_cwidth(int c);
extern int utf8_isok(int c);
/**
* ASCII support functions
*/
extern int ascii_getc(const char *s);
extern int ascii_getx(char **s);
extern int ascii_setc(char *s, int c);
extern int ascii_width(const char *s);
extern int ascii_cwidth(int c);
extern int ascii_isok(int c);
/* ugetc: */
extern int (*ugetc)(const char *s);
/* ugetxc: */
extern int (*ugetx)(char **s);
/* ugetxc: */
extern int (*ugetxc)(const char * const *s);
/* usetc: */
extern int (*usetc)(char *s, int c);
/* uwidth: */
extern int (*uwidth)(const char *s);
/* ucwidth: */
extern int (*ucwidth)(int c);
/* uisok: */
extern int (*uisok)(int c);
/* set_uformat:
* Selects a new text encoding format.
*/
extern void set_uformat(int type);
enum { LC_CTYPE };
extern const char *setlocale(int type, const char *language);
/* get_uformat:
* Returns the current text encoding format.
*/
extern int get_uformat();
extern size_t ustrsize(const char *s);
/* &nicode string length
*/
extern int ustrlen(const char *s);
/* utolower:
* Unicode-aware version of the ANSI tolower() function.
*/
extern int utolower(int c);
/* utoupper:
* Unicode-aware version of the ANSI toupper() function.
*/
extern int utoupper(int c);
/* Unicode string compare
*/
extern int ustrcmp(const char *s1, const char *s2);
/* ustricmp:
* Unicode-aware version of the DJGPP stricmp() function.
*/
extern int ustricmp(const char *s1, const char *s2);
/* ustrncmp:
* Unicode-aware version of the ANSI strncmp() function.
*/
extern int ustrncmp(const char *s1, const char *s2, int n);
/* ustrnicmp:
* Unicode-aware version of the DJGPP strnicmp() function.
*/
extern int ustrnicmp(const char *s1, const char *s2, int n);
/* uoffset:
* Returns the offset in bytes from the start of the string to the
* character at the specified index. If the index is negative, counts
* backward from the end of the string (-1 returns an offset to the
* last character).
*/
extern int uoffset(const char *s, int index);
/* ugetat:
* Returns the character from the specified index within the string.
*/
extern int ugetat(const char *s, int idx);
/* ustrlwr:
* Unicode-aware version of the ANSI strlwr() function.
*/
extern char *ustrlwr(char *s);
/* ustrupr:
* Unicode-aware version of the ANSI strupr() function.
*/
extern char *ustrupr(char *s);
/* ustrstr:
* Unicode-aware version of the ANSI strstr() function.
*/
extern const char *ustrstr(const char *s1, const char *s2);
/* usetat:
* Modifies the character at the specified index within the string,
* handling adjustments for variable width data. Returns how far the
* rest of the string was moved.
*/
int usetat(char *s, int index, int c);
/* ustrsizez:
* Returns the size of the specified string in bytes, including the
* trailing zero.
*/
extern int ustrsizez(const char *s);
extern int need_uconvert(const char *s, int type, int newtype);
extern int uvszprintf(char *buf, int size, const char *format, va_list args);
} // namespace AGS3
#endif

View File

@@ -0,0 +1,155 @@
/* 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/>.
*
*/
/***************************************************************************/
/* */
/* ahangles.c */
/* */
/* A routine used to compute vector angles with limited accuracy */
/* and very high speed (body). */
/* */
/* Copyright 2000-2001, 2002 Catharon Productions Inc. */
/* Author: David Turner */
/* */
/* This file is part of the Catharon Typography Project and shall only */
/* be used, modified, and distributed under the terms of the Catharon */
/* Open Source License that should come with this file under the name */
/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/* Note that this license is compatible with the FreeType license. */
/* */
/***************************************************************************/
#include <ft2build.h>
#include "ags/lib/freetype-2.1.3/autohint/ahangles.h"
namespace AGS3 {
namespace FreeType213 {
/* the following table has been automatically generated with */
/* the `mather.py' Python script */
const AH_Angle ah_arctan[1L << AH_ATAN_BITS] = {
0, 0, 1, 1, 1, 2, 2, 2,
3, 3, 3, 3, 4, 4, 4, 5,
5, 5, 6, 6, 6, 7, 7, 7,
8, 8, 8, 9, 9, 9, 10, 10,
10, 10, 11, 11, 11, 12, 12, 12,
13, 13, 13, 14, 14, 14, 14, 15,
15, 15, 16, 16, 16, 17, 17, 17,
18, 18, 18, 18, 19, 19, 19, 20,
20, 20, 21, 21, 21, 21, 22, 22,
22, 23, 23, 23, 24, 24, 24, 24,
25, 25, 25, 26, 26, 26, 26, 27,
27, 27, 28, 28, 28, 28, 29, 29,
29, 30, 30, 30, 30, 31, 31, 31,
31, 32, 32, 32, 33, 33, 33, 33,
34, 34, 34, 34, 35, 35, 35, 35,
36, 36, 36, 36, 37, 37, 37, 38,
38, 38, 38, 39, 39, 39, 39, 40,
40, 40, 40, 41, 41, 41, 41, 42,
42, 42, 42, 42, 43, 43, 43, 43,
44, 44, 44, 44, 45, 45, 45, 45,
46, 46, 46, 46, 46, 47, 47, 47,
47, 48, 48, 48, 48, 48, 49, 49,
49, 49, 50, 50, 50, 50, 50, 51,
51, 51, 51, 51, 52, 52, 52, 52,
52, 53, 53, 53, 53, 53, 54, 54,
54, 54, 54, 55, 55, 55, 55, 55,
56, 56, 56, 56, 56, 57, 57, 57,
57, 57, 57, 58, 58, 58, 58, 58,
59, 59, 59, 59, 59, 59, 60, 60,
60, 60, 60, 61, 61, 61, 61, 61,
61, 62, 62, 62, 62, 62, 62, 63,
63, 63, 63, 63, 63, 64, 64, 64
};
AH_Angle ah_angle(FT_Vector *v) {
FT_Pos dx, dy;
AH_Angle angle;
dx = v->x;
dy = v->y;
/* check trivial cases */
if (dy == 0) {
angle = 0;
if (dx < 0)
angle = AH_PI;
return angle;
} else if (dx == 0) {
angle = AH_HALF_PI;
if (dy < 0)
angle = -AH_HALF_PI;
return angle;
}
angle = 0;
if (dx < 0) {
dx = -v->x;
dy = -v->y;
angle = AH_PI;
}
if (dy < 0) {
FT_Pos tmp;
tmp = dx;
dx = -dy;
dy = tmp;
angle -= AH_HALF_PI;
}
if (dx == 0 && dy == 0)
return 0;
if (dx == dy)
angle += AH_PI / 4;
else if (dx > dy)
angle += ah_arctan[FT_DivFix(dy, dx) >> (16 - AH_ATAN_BITS)];
else
angle += AH_HALF_PI - ah_arctan[FT_DivFix(dx, dy) >> (16 - AH_ATAN_BITS)];
if (angle > AH_PI)
angle -= AH_2PI;
return angle;
}
AH_Angle ah_angle_diff(AH_Angle angle1, AH_Angle angle2) {
AH_Angle delta;
delta = (angle2 - angle1);
if (delta < 0)
delta += AH_2PI;
if (delta > AH_PI)
delta -= AH_2PI;
return delta;
}
} // End of namespace FreeType213
} // End of namespace AGS3

View File

@@ -0,0 +1,75 @@
/* 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/>.
*
*/
/***************************************************************************/
/* */
/* ahangles.h */
/* */
/* A routine used to compute vector angles with limited accuracy */
/* and very high speed (specification). */
/* */
/* Copyright 2000-2001, 2002 Catharon Productions Inc. */
/* Author: David Turner */
/* */
/* This file is part of the Catharon Typography Project and shall only */
/* be used, modified, and distributed under the terms of the Catharon */
/* Open Source License that should come with this file under the name */
/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/* Note that this license is compatible with the FreeType license. */
/* */
/***************************************************************************/
#ifndef AGS_LIB_FREETYPE_AHANGLES_H
#define AGS_LIB_FREETYPE_AHANGLES_H
#include <ft2build.h>
#include "ags/lib/freetype-2.1.3/autohint/ahtypes.h"
namespace AGS3 {
namespace FreeType213 {
/* PI expressed in ah_angles -- we don't really need an important */
/* precision, so 256 should be enough */
#define AH_PI 256
#define AH_2PI (AH_PI * 2)
#define AH_HALF_PI (AH_PI / 2)
#define AH_2PIMASK (AH_2PI - 1)
/* the number of bits used to express an arc tangent; */
/* see the structure of the lookup table */
#define AH_ATAN_BITS 8
extern const AH_Angle ah_arctan[1L << AH_ATAN_BITS];
AH_Angle ah_angle(FT_Vector *v);
AH_Angle ah_angle_diff(AH_Angle angle1, AH_Angle angle2);
} // End of namespace FreeType213
} // End of namespace AGS3
#endif /* AGS_LIB_FREETYPE_AHANGLES_H */

View File

@@ -0,0 +1,371 @@
/* 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/>.
*
*/
/***************************************************************************/
/* */
/* ahglobal.c */
/* */
/* Routines used to compute global metrics automatically (body). */
/* */
/* Copyright 2000-2001, 2002 Catharon Productions Inc. */
/* Author: David Turner */
/* */
/* This file is part of the Catharon Typography Project and shall only */
/* be used, modified, and distributed under the terms of the Catharon */
/* Open Source License that should come with this file under the name */
/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/* Note that this license is compatible with the FreeType license. */
/* */
/***************************************************************************/
#include <ft2build.h>
#include "ags/lib/freetype-2.1.3/autohint/ahglobal.h"
#include "ags/lib/freetype-2.1.3/autohint/ahglyph.h"
#include "common/debug.h"
#define MAX_TEST_CHARACTERS 12
namespace AGS3 {
namespace FreeType213 {
static const char* blue_chars[AH_BLUE_MAX] = {
"THEZOCQS",
"HEZLOCUS",
"xzroesc",
"xzroesc",
"pqgjy"
};
/* simple insertion sort */
static void sort_values(FT_Int count, FT_Pos *table) {
FT_Int i, j;
FT_Pos swap;
for (i = 1; i < count; i++) {
for (j = i; j > 0; j--) {
if (table[j] > table[j - 1])
break;
swap = table[j];
table[j] = table[j - 1];
table[j - 1] = swap;
}
}
}
static FT_Error ah_hinter_compute_blues(AH_Hinter hinter) {
AH_Blue blue;
AH_Globals globals = &hinter->globals->design;
FT_Pos flats[MAX_TEST_CHARACTERS];
FT_Pos rounds[MAX_TEST_CHARACTERS];
FT_Int num_flats;
FT_Int num_rounds;
FT_Face face;
FT_GlyphSlot glyph;
FT_Error error;
FT_CharMap charmap;
face = hinter->face;
glyph = face->glyph;
/* save current charmap */
charmap = face->charmap;
/* do we have a Unicode charmap in there? */
error = FT_Select_Charmap(face, FT_ENCODING_UNICODE);
if (error)
goto Exit;
/* we compute the blues simply by loading each character from the */
/* 'blue_chars[blues]' string, then compute its top-most and */
/* bottom-most points */
debug(6, "blue zones computation");
debug(6, "------------------------------------------------");
for (blue = AH_BLUE_CAPITAL_TOP; blue < AH_BLUE_MAX; blue++) {
const char *p = blue_chars[blue];
const char *limit = p + MAX_TEST_CHARACTERS;
FT_Pos *blue_ref, *blue_shoot;
debugN(6, "blue %3d: ", blue);
num_flats = 0;
num_rounds = 0;
for (; p < limit; p++) {
FT_UInt glyph_index;
FT_Vector *extremum;
FT_Vector *points;
FT_Vector *point_limit;
FT_Vector *point;
FT_Bool round;
/* exit if we reach the end of the string */
if (!*p)
break;
debugN(6, "`%c'", *p);
/* load the character in the face -- skip unknown or empty ones */
glyph_index = FT_Get_Char_Index(face, (FT_UInt)*p);
if (glyph_index == 0)
continue;
error = FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE);
if (error || glyph->outline.n_points <= 0)
continue;
/* now compute min or max point indices and coordinates */
points = glyph->outline.points;
point_limit = points + glyph->outline.n_points;
point = points;
extremum = point;
point++;
if (AH_IS_TOP_BLUE(blue)) {
for (; point < point_limit; point++)
if (point->y > extremum->y)
extremum = point;
} else {
for (; point < point_limit; point++)
if (point->y < extremum->y)
extremum = point;
}
debugN(6, "%5d", (int)extremum->y);
/* now, check whether the point belongs to a straight or round */
/* segment; we first need to find in which contour the extremum */
/* lies, then see its previous and next points */
{
FT_Int idx = (FT_Int)(extremum - points);
FT_Int n;
FT_Int first, last, prev, next, end;
FT_Pos dist;
last = -1;
first = 0;
for (n = 0; n < glyph->outline.n_contours; n++) {
end = glyph->outline.contours[n];
if (end >= idx) {
last = end;
break;
}
first = end + 1;
}
/* XXX: should never happen! */
if (last < 0)
continue;
/* now look for the previous and next points that are not on the */
/* same Y coordinate. Threshold the `closeness'... */
prev = idx;
next = prev;
do {
if (prev > first)
prev--;
else
prev = last;
dist = points[prev].y - extremum->y;
if (dist < -5 || dist > 5)
break;
} while (prev != idx);
do {
if (next < last)
next++;
else
next = first;
dist = points[next].y - extremum->y;
if (dist < -5 || dist > 5)
break;
} while (next != idx);
/* now, set the `round' flag depending on the segment's kind */
round = FT_BOOL(
FT_CURVE_TAG(glyph->outline.tags[prev]) != FT_CURVE_TAG_ON ||
FT_CURVE_TAG(glyph->outline.tags[next]) != FT_CURVE_TAG_ON);
debugN(6, "%c ", round ? 'r' : 'f');
}
if (round)
rounds[num_rounds++] = extremum->y;
else
flats[num_flats++] = extremum->y;
}
debugN(6, "\n");
/* we have computed the contents of the `rounds' and `flats' tables, */
/* now determine the reference and overshoot position of the blue; */
/* we simply take the median value after a simple short */
sort_values(num_rounds, rounds);
sort_values(num_flats, flats);
blue_ref = globals->blue_refs + blue;
blue_shoot = globals->blue_shoots + blue;
if (num_flats == 0 && num_rounds == 0) {
*blue_ref = -10000;
*blue_shoot = -10000;
} else if (num_flats == 0) {
*blue_ref = *blue_shoot = rounds[num_rounds / 2];
} else if (num_rounds == 0) {
*blue_ref = *blue_shoot = flats[num_flats / 2];
} else {
*blue_ref = flats[num_flats / 2];
*blue_shoot = rounds[num_rounds / 2];
}
/* there are sometimes problems: if the overshoot position of top */
/* zones is under its reference position, or the opposite for bottom */
/* zones. We must thus check everything there and correct the errors */
if (*blue_shoot != *blue_ref) {
FT_Pos ref = *blue_ref;
FT_Pos shoot = *blue_shoot;
FT_Bool over_ref = FT_BOOL(shoot > ref);
if (AH_IS_TOP_BLUE(blue) ^ over_ref)
*blue_shoot = *blue_ref = (shoot + ref) / 2;
}
debug(6, "-- ref = %ld, shoot = %ld", *blue_ref, *blue_shoot);
}
/* reset original face charmap */
FT_Set_Charmap(face, charmap);
error = 0;
Exit:
return error;
}
static FT_Error ah_hinter_compute_widths(AH_Hinter hinter) {
/* scan the array of segments in each direction */
AH_Outline outline = hinter->glyph;
AH_Segment segments;
AH_Segment limit;
AH_Globals globals = &hinter->globals->design;
FT_Pos *widths;
FT_Int dimension;
FT_Int *p_num_widths;
FT_Error error = 0;
FT_Pos edge_distance_threshold = 32000;
globals->num_widths = 0;
globals->num_heights = 0;
/* For now, compute the standard width and height from the `o' */
/* character. I started computing the stem width of the `i' and the */
/* stem height of the "-", but it wasn't too good. Moreover, we now */
/* have a single character that gives us standard width and height. */
{
FT_UInt glyph_index;
glyph_index = FT_Get_Char_Index(hinter->face, 'o');
if (glyph_index == 0)
return 0;
error = FT_Load_Glyph(hinter->face, glyph_index, FT_LOAD_NO_SCALE);
if (error)
goto Exit;
error = ah_outline_load(hinter->glyph, hinter->face);
if (error)
goto Exit;
ah_outline_compute_segments(hinter->glyph);
ah_outline_link_segments(hinter->glyph);
}
segments = outline->horz_segments;
limit = segments + outline->num_hsegments;
widths = globals->heights;
p_num_widths = &globals->num_heights;
for (dimension = 1; dimension >= 0; dimension--) {
AH_Segment seg = segments;
AH_Segment link;
FT_Int num_widths = 0;
for (; seg < limit; seg++) {
link = seg->link;
/* we only consider stem segments there! */
if (link && link->link == seg && link > seg) {
FT_Pos dist;
dist = seg->pos - link->pos;
if (dist < 0)
dist = -dist;
if (num_widths < AH_MAX_WIDTHS)
widths[num_widths++] = dist;
}
}
sort_values(num_widths, widths);
*p_num_widths = num_widths;
/* we will now try to find the smallest width */
if (num_widths > 0 && widths[0] < edge_distance_threshold)
edge_distance_threshold = widths[0];
segments = outline->vert_segments;
limit = segments + outline->num_vsegments;
widths = globals->widths;
p_num_widths = &globals->num_widths;
}
/* Now, compute the edge distance threshold as a fraction of the */
/* smallest width in the font. Set it in `hinter.glyph' too! */
if (edge_distance_threshold == 32000)
edge_distance_threshold = 50;
/* let's try 20% */
hinter->glyph->edge_distance_threshold = edge_distance_threshold / 5;
Exit:
return error;
}
FT_Error ah_hinter_compute_globals(AH_Hinter hinter) {
return ah_hinter_compute_widths(hinter) || ah_hinter_compute_blues(hinter);
}
} // End of namespace FreeType213
} // End of namespace AGS3

View File

@@ -0,0 +1,64 @@
/* 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/>.
*
*/
/***************************************************************************/
/* */
/* ahglobal.h */
/* */
/* Routines used to compute global metrics automatically */
/* (specification). */
/* */
/* Copyright 2000-2001, 2002 Catharon Productions Inc. */
/* Author: David Turner */
/* */
/* This file is part of the Catharon Typography Project and shall only */
/* be used, modified, and distributed under the terms of the Catharon */
/* Open Source License that should come with this file under the name */
/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/* Note that this license is compatible with the FreeType license. */
/* */
/***************************************************************************/
#ifndef AGS_LIB_FREETYPE_AHGLOBAL_H
#define AGS_LIB_FREETYPE_AHGLOBAL_H
#include <ft2build.h>
#include "ags/lib/freetype-2.1.3/autohint/ahtypes.h"
namespace AGS3 {
namespace FreeType213 {
#define AH_IS_TOP_BLUE(b) ((b) == AH_BLUE_CAPITAL_TOP || (b) == AH_BLUE_SMALL_TOP)
/* compute global metrics automatically */
FT_Error ah_hinter_compute_globals(AH_Hinter hinter);
} // End of namespace FreeType213
} // End of namespace AGS3
#endif /* AGS_LIB_FREETYPE_AHGLOBAL_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,84 @@
/* 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/>.
*
*/
/***************************************************************************/
/* */
/* ahglyph.h */
/* */
/* Routines used to load and analyze a given glyph before hinting */
/* (specification). */
/* */
/* Copyright 2000-2001, 2002 Catharon Productions Inc. */
/* Author: David Turner */
/* */
/* This file is part of the Catharon Typography Project and shall only */
/* be used, modified, and distributed under the terms of the Catharon */
/* Open Source License that should come with this file under the name */
/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/* Note that this license is compatible with the FreeType license. */
/* */
/***************************************************************************/
#ifndef AGS_LIB_FREETYPE_AHGLYPH_H
#define AGS_LIB_FREETYPE_AHGLYPH_H
#include <ft2build.h>
#include "ags/lib/freetype-2.1.3/autohint/ahtypes.h"
namespace AGS3 {
namespace FreeType213 {
typedef enum AH_UV_ {
AH_UV_FXY,
AH_UV_FYX,
AH_UV_OXY,
AH_UV_OYX,
AH_UV_OX,
AH_UV_OY,
AH_UV_YX,
AH_UV_XY /* should always be last! */
} AH_UV;
void ah_setup_uv(AH_Outline outline, AH_UV source);
/* AH_OutlineRec functions - they should be typically called in this order */
FT_Error ah_outline_new(FT_Memory memory, AH_Outline *aoutline);
FT_Error ah_outline_load(AH_Outline outline, FT_Face face);
void ah_outline_compute_segments(AH_Outline outline);
void ah_outline_link_segments(AH_Outline outline);
void ah_outline_detect_features(AH_Outline outline);
void ah_outline_compute_blue_edges(AH_Outline outline, AH_Face_Globals globals);
void ah_outline_scale_blue_edges(AH_Outline outline, AH_Face_Globals globals);
void ah_outline_save(AH_Outline outline, AH_Loader loader);
void ah_outline_done(AH_Outline outline);
} // End of namespace FreeType213
} // End of namespace AGS3
#endif /* AGS_LIB_FREETYPE_AHGLYPH_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,78 @@
/* 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/>.
*
*/
/***************************************************************************/
/* */
/* ahhint.h */
/* */
/* Glyph hinter (declaration). */
/* */
/* Copyright 2000-2001, 2002 Catharon Productions Inc. */
/* Author: David Turner */
/* */
/* This file is part of the Catharon Typography Project and shall only */
/* be used, modified, and distributed under the terms of the Catharon */
/* Open Source License that should come with this file under the name */
/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/* Note that this license is compatible with the FreeType license. */
/* */
/***************************************************************************/
#ifndef AGS_LIB_FREETYPE_AHHINT_H
#define AGS_LIB_FREETYPE_AHHINT_H
#include <ft2build.h>
#include "ags/lib/freetype-2.1.3/autohint/ahglobal.h"
namespace AGS3 {
namespace FreeType213 {
#define AH_HINT_DEFAULT 0
#define AH_HINT_NO_ALIGNMENT 1
#define AH_HINT_NO_HORZ_EDGES 0x200000L /* temporary hack */
#define AH_HINT_NO_VERT_EDGES 0x400000L /* temporary hack */
/* create a new empty hinter object */
FT_Error ah_hinter_new(FT_Memory memory, AH_Hinter *ahinter);
/* Load a hinted glyph in the hinter */
FT_Error ah_hinter_load_glyph(AH_Hinter hinter, FT_GlyphSlot slot, FT_Size size, FT_UInt glyph_index, FT_Int32 load_flags);
/* finalize a hinter object */
void ah_hinter_done(AH_Hinter hinter);
void ah_hinter_done_face_globals(AH_Face_Globals globals);
void ah_hinter_get_global_hints(AH_Hinter hinter, FT_Face face, void **global_hints, long *global_len);
void ah_hinter_done_global_hints(AH_Hinter hinter, void *global_hints);
} // End of namespace FreeType213
} // End of namespace AGS3
#endif /* AGS_LIB_FREETYPE_AHHINT_H */

View File

@@ -0,0 +1,68 @@
/* 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/>.
*
*/
/***************************************************************************/
/* */
/* ahloader.h */
/* */
/* Glyph loader for the auto-hinting module (declaration only). */
/* */
/* Copyright 2000-2001, 2002 Catharon Productions Inc. */
/* Author: David Turner */
/* */
/* This file is part of the Catharon Typography Project and shall only */
/* be used, modified, and distributed under the terms of the Catharon */
/* Open Source License that should come with this file under the name */
/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/* Note that this license is compatible with the FreeType license. */
/* */
/***************************************************************************/
#ifndef AGS_LIB_FREETYPE_AHLOADER_H
#define AGS_LIB_FREETYPE_AHLOADER_H
#include <ft2build.h>
#include "ags/lib/freetype-2.1.3/ftgloadr.h"
#include FT_OUTLINE_H
#define AH_Load FT_GlyphLoad
#define AH_Loader FT_GlyphLoader
#define ah_loader_new FT_GlyphLoader_New
#define ah_loader_done FT_GlyphLoader_Done
#define ah_loader_reset FT_GlyphLoader_Reset
#define ah_loader_rewind FT_GlyphLoader_Rewind
#define ah_loader_create_extra FT_GlyphLoader_CreateExtra
#define ah_loader_check_points FT_GlyphLoader_CheckPoints
#define ah_loader_check_subglyphs FT_GlyphLoader_CheckSubGlyphs
#define ah_loader_prepare FT_GlyphLoader_Prepare
#define ah_loader_add FT_GlyphLoader_Add
#define ah_loader_copy_points FT_GlyphLoader_CopyPoints
#endif /* AGS_LIB_FREETYPE_AHLOADER_H */

View File

@@ -0,0 +1,315 @@
/* 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/>.
*
*/
/***************************************************************************/
/* */
/* ahtypes.h */
/* */
/* General types and definitions for the auto-hint module */
/* (specification only). */
/* */
/* Copyright 2000-2001, 2002 Catharon Productions Inc. */
/* Author: David Turner */
/* */
/* This file is part of the Catharon Typography Project and shall only */
/* be used, modified, and distributed under the terms of the Catharon */
/* Open Source License that should come with this file under the name */
/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/* Note that this license is compatible with the FreeType license. */
/* */
/***************************************************************************/
#ifndef AGS_LIB_FREETYPE_AHTYPES_H
#define AGS_LIB_FREETYPE_AHTYPES_H
#include <ft2build.h>
#include FT_TYPES_H
#include "ags/lib/freetype-2.1.3/autohint/ahloader.h"
namespace AGS3 {
namespace FreeType213 {
/**** COMPILE-TIME BUILD OPTIONS ****/
/*************************************************************************/
/* */
/* If this option is defined, only strong interpolation will be used to */
/* place the points between edges. Otherwise, `smooth' points are */
/* detected and later hinted through weak interpolation to correct some */
/* unpleasant artefacts. */
/* */
#undef AH_OPTION_NO_WEAK_INTERPOLATION
/*************************************************************************/
/* */
/* If this option is defined, only weak interpolation will be used to */
/* place the points between edges. Otherwise, `strong' points are */
/* detected and later hinted through strong interpolation to correct */
/* some unpleasant artefacts. */
/* */
#undef AH_OPTION_NO_STRONG_INTERPOLATION
/*************************************************************************/
/* */
/* Undefine this macro if you don't want to hint the metrics. There is */
/* no reason to do this (at least for non-CJK scripts), except for */
/* experimentation. */
/* */
#undef AH_HINT_METRICS
/*************************************************************************/
/* */
/* Define this macro if you do not want to insert extra edges at a */
/* glyph's x and y extremum (if there isn't one already available). */
/* This helps to reduce a number of artefacts and allows hinting of */
/* metrics. */
/* */
#undef AH_OPTION_NO_EXTREMUM_EDGES
/* don't touch for now */
#define AH_MAX_WIDTHS 12
#define AH_MAX_HEIGHTS 12
/**** TYPE DEFINITIONS ****/
/* see agangles.h */
typedef FT_Int AH_Angle;
/* hint flags */
#define AH_FLAG_NONE 0
/* bezier control points flags */
#define AH_FLAG_CONIC 1
#define AH_FLAG_CUBIC 2
#define AH_FLAG_CONTROL ( AH_FLAG_CONIC | AH_FLAG_CUBIC )
/* extrema flags */
#define AH_FLAG_EXTREMA_X 4
#define AH_FLAG_EXTREMA_Y 8
/* roundness */
#define AH_FLAG_ROUND_X 16
#define AH_FLAG_ROUND_Y 32
/* touched */
#define AH_FLAG_TOUCH_X 64
#define AH_FLAG_TOUCH_Y 128
/* weak interpolation */
#define AH_FLAG_WEAK_INTERPOLATION 256
#define AH_FLAG_INFLECTION 512
typedef FT_Int AH_Flags;
/* edge hint flags */
#define AH_EDGE_NORMAL 0
#define AH_EDGE_ROUND 1
#define AH_EDGE_SERIF 2
#define AH_EDGE_DONE 4
typedef FT_Int AH_Edge_Flags;
/* hint directions -- the values are computed so that two vectors are */
/* in opposite directions iff `dir1+dir2 == 0' */
#define AH_DIR_NONE 4
#define AH_DIR_RIGHT 1
#define AH_DIR_LEFT -1
#define AH_DIR_UP 2
#define AH_DIR_DOWN -2
typedef FT_Int AH_Direction;
typedef struct AH_PointRec_ *AH_Point;
typedef struct AH_SegmentRec_ *AH_Segment;
typedef struct AH_EdgeRec_ *AH_Edge;
typedef struct AH_PointRec_ {
AH_Flags flags; /* point flags used by hinter */
FT_Pos ox, oy;
FT_Pos fx, fy;
FT_Pos x, y;
FT_Pos u, v;
AH_Direction in_dir; /* direction of inwards vector */
AH_Direction out_dir; /* direction of outwards vector */
AH_Angle in_angle;
AH_Angle out_angle;
AH_Point next; /* next point in contour */
AH_Point prev; /* previous point in contour */
} AH_PointRec;
typedef struct AH_SegmentRec_ {
AH_Edge_Flags flags;
AH_Direction dir;
AH_Point first; /* first point in edge segment */
AH_Point last; /* last point in edge segment */
AH_Point *contour; /* ptr to first point of segment's contour */
FT_Pos pos; /* position of segment */
FT_Pos min_coord; /* minimum coordinate of segment */
FT_Pos max_coord; /* maximum coordinate of segment */
AH_Edge edge;
AH_Segment edge_next;
AH_Segment link; /* link segment */
AH_Segment serif; /* primary segment for serifs */
FT_Pos num_linked; /* number of linked segments */
FT_Pos score;
} AH_SegmentRec;
typedef struct AH_EdgeRec_ {
AH_Edge_Flags flags;
AH_Direction dir;
AH_Segment first;
AH_Segment last;
FT_Pos fpos;
FT_Pos opos;
FT_Pos pos;
AH_Edge link;
AH_Edge serif;
FT_Int num_linked;
FT_Int score;
FT_Pos *blue_edge;
} AH_EdgeRec;
/* an outline as seen by the hinter */
typedef struct AH_OutlineRec_ {
FT_Memory memory;
AH_Direction vert_major_dir; /* vertical major direction */
AH_Direction horz_major_dir; /* horizontal major direction */
FT_Fixed x_scale;
FT_Fixed y_scale;
FT_Pos edge_distance_threshold;
FT_Int max_points;
FT_Int num_points;
AH_Point points;
FT_Int max_contours;
FT_Int num_contours;
AH_Point *contours;
FT_Int num_hedges;
AH_Edge horz_edges;
FT_Int num_vedges;
AH_Edge vert_edges;
FT_Int num_hsegments;
AH_Segment horz_segments;
FT_Int num_vsegments;
AH_Segment vert_segments;
} AH_OutlineRec, *AH_Outline;
#define AH_BLUE_CAPITAL_TOP 0 /* THEZOCQS */
#define AH_BLUE_CAPITAL_BOTTOM ( AH_BLUE_CAPITAL_TOP + 1 ) /* HEZLOCUS */
#define AH_BLUE_SMALL_TOP ( AH_BLUE_CAPITAL_BOTTOM + 1 ) /* xzroesc */
#define AH_BLUE_SMALL_BOTTOM ( AH_BLUE_SMALL_TOP + 1 ) /* xzroesc */
#define AH_BLUE_SMALL_MINOR ( AH_BLUE_SMALL_BOTTOM + 1 ) /* pqgjy */
#define AH_BLUE_MAX ( AH_BLUE_SMALL_MINOR + 1 )
typedef FT_Int AH_Blue;
#define AH_HINTER_MONOCHROME 1
#define AH_HINTER_OPTIMIZE 2
typedef FT_Int AH_Hinter_Flags;
typedef struct AH_GlobalsRec_ {
FT_Int num_widths;
FT_Int num_heights;
FT_Pos stds[2];
FT_Pos widths[AH_MAX_WIDTHS];
FT_Pos heights[AH_MAX_HEIGHTS];
FT_Pos blue_refs[AH_BLUE_MAX];
FT_Pos blue_shoots[AH_BLUE_MAX];
} AH_GlobalsRec, *AH_Globals;
typedef struct AH_Face_GlobalsRec_ {
FT_Face face;
AH_GlobalsRec design;
AH_GlobalsRec scaled;
FT_Fixed x_scale;
FT_Fixed y_scale;
FT_Bool control_overshoot;
} AH_Face_GlobalsRec, *AH_Face_Globals;
typedef struct AH_HinterRec {
FT_Memory memory;
AH_Hinter_Flags flags;
FT_Int algorithm;
FT_Face face;
AH_Face_Globals globals;
AH_Outline glyph;
AH_Loader loader;
FT_Vector pp1;
FT_Vector pp2;
FT_Bool transformed;
FT_Vector trans_delta;
FT_Matrix trans_matrix;
FT_Bool do_horz_hints; /* disable X hinting */
FT_Bool do_vert_hints; /* disable Y hinting */
FT_Bool do_horz_snapping; /* disable X stem size snapping */
FT_Bool do_vert_snapping; /* disable Y stem size snapping */
} AH_HinterRec, *AH_Hinter;
} // End of namespace FreeType213
} // End of namespace AGS3
#endif /* AGS_LIB_FREETYPE_AHTYPES_H */

View File

@@ -0,0 +1,50 @@
/* 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/>.
*
*/
/***************************************************************************/
/* */
/* fterrors.h */
/* */
/* FreeType error codes */
/* */
/* Copyright 1996-2001, 2002 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
#ifndef AGS_LIB_FREETYPE_FTERRORS_H
#define AGS_LIB_FREETYPE_FTERRORS_H
#define FT_Err_Ok 0x00
#define FT_Err_Invalid_Argument 0x06
#define FT_Err_Unimplemented_Feature 0x07
#define FT_Err_Invalid_Composite 0x15
#define FT_Err_Out_Of_Memory 0x40
#endif /* AGS_LIB_FREETYPE_FTERRORS_H */

View File

@@ -0,0 +1,285 @@
/* 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/>.
*
*/
/***************************************************************************/
/* */
/* ftgloadr.c */
/* */
/* The FreeType glyph loader (body). */
/* */
/* Copyright 2002 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
#include <ft2build.h>
#include "ags/lib/freetype-2.1.3/autohint/ahhint.h"
#include "ags/lib/freetype-2.1.3/ftmemory.h"
namespace AGS3 {
namespace FreeType213 {
/* create a new glyph loader */
FT_Error FT_GlyphLoader_New(FT_Memory memory, FT_GlyphLoader *aloader) {
FT_GlyphLoader loader;
FT_Error error;
if (!FT_NEW(loader)) {
loader->memory = memory;
*aloader = loader;
}
return error;
}
/* rewind the glyph loader - reset counters to 0 */
void FT_GlyphLoader_Rewind(FT_GlyphLoader loader) {
FT_GlyphLoad base = &loader->base;
FT_GlyphLoad current = &loader->current;
base->outline.n_points = 0;
base->outline.n_contours = 0;
base->num_subglyphs = 0;
*current = *base;
}
/* reset the glyph loader, frees all allocated tables */
/* and starts from zero */
void FT_GlyphLoader_Reset(FT_GlyphLoader loader) {
FT_Memory memory = loader->memory;
FT_FREE(loader->base.outline.points);
FT_FREE(loader->base.outline.tags);
FT_FREE(loader->base.outline.contours);
FT_FREE(loader->base.extra_points);
FT_FREE(loader->base.subglyphs);
loader->max_points = 0;
loader->max_contours = 0;
loader->max_subglyphs = 0;
FT_GlyphLoader_Rewind(loader);
}
/* delete a glyph loader */
void FT_GlyphLoader_Done(FT_GlyphLoader loader) {
if (loader) {
FT_Memory memory = loader->memory;
FT_GlyphLoader_Reset(loader);
FT_FREE(loader);
}
}
/* re-adjust the `current' outline fields */
static void FT_GlyphLoader_Adjust_Points(FT_GlyphLoader loader) {
FT_Outline *base = &loader->base.outline;
FT_Outline *current = &loader->current.outline;
current->points = base->points + base->n_points;
current->tags = base->tags + base->n_points;
current->contours = base->contours + base->n_contours;
/* handle extra points table - if any */
if (loader->use_extra)
loader->current.extra_points = loader->base.extra_points + base->n_points;
}
FT_Error FT_GlyphLoader_CreateExtra(FT_GlyphLoader loader) {
FT_Error error;
FT_Memory memory = loader->memory;
if (!FT_NEW_ARRAY(loader->base.extra_points, loader->max_points)) {
loader->use_extra = 1;
FT_GlyphLoader_Adjust_Points(loader);
}
return error;
}
/* re-adjust the `current' subglyphs field */
static void FT_GlyphLoader_Adjust_Subglyphs(FT_GlyphLoader loader) {
FT_GlyphLoad base = &loader->base;
FT_GlyphLoad current = &loader->current;
current->subglyphs = base->subglyphs + base->num_subglyphs;
}
/* Ensure that we can add `n_points' and `n_contours' to our glyph. this */
/* function reallocates its outline tables if necessary. Note that it */
/* DOESN'T change the number of points within the loader! */
/* */
FT_Error FT_GlyphLoader_CheckPoints(FT_GlyphLoader loader, FT_UInt n_points, FT_UInt n_contours) {
FT_Memory memory = loader->memory;
FT_Error error = FT_Err_Ok;
FT_Outline *base = &loader->base.outline;
FT_Outline *current = &loader->current.outline;
FT_Bool adjust = 1;
FT_UInt new_max, old_max;
/* check points & tags */
new_max = base->n_points + current->n_points + n_points;
old_max = loader->max_points;
if (new_max > old_max) {
new_max = (new_max + 7) & -8;
if (FT_RENEW_ARRAY(base->points, old_max, new_max) || FT_RENEW_ARRAY(base->tags, old_max, new_max))
goto Exit;
if (loader->use_extra && FT_RENEW_ARRAY(loader->base.extra_points, old_max, new_max))
goto Exit;
adjust = 1;
loader->max_points = new_max;
}
/* check contours */
old_max = loader->max_contours;
new_max = base->n_contours + current->n_contours + n_contours;
if (new_max > old_max) {
new_max = (new_max + 3) & -4;
if (FT_RENEW_ARRAY(base->contours, old_max, new_max))
goto Exit;
adjust = 1;
loader->max_contours = new_max;
}
if (adjust)
FT_GlyphLoader_Adjust_Points(loader);
Exit:
return error;
}
/* Ensure that we can add `n_subglyphs' to our glyph. this function */
/* reallocates its subglyphs table if necessary. Note that it DOES */
/* NOT change the number of subglyphs within the loader! */
/* */
FT_Error FT_GlyphLoader_CheckSubGlyphs(FT_GlyphLoader loader, FT_UInt n_subs) {
FT_Memory memory = loader->memory;
FT_Error error = FT_Err_Ok;
FT_UInt new_max, old_max;
FT_GlyphLoad base = &loader->base;
FT_GlyphLoad current = &loader->current;
new_max = base->num_subglyphs + current->num_subglyphs + n_subs;
old_max = loader->max_subglyphs;
if (new_max > old_max) {
new_max = (new_max + 1) & -2;
if (FT_RENEW_ARRAY(base->subglyphs, old_max, new_max))
goto Exit;
loader->max_subglyphs = new_max;
FT_GlyphLoader_Adjust_Subglyphs(loader);
}
Exit:
return error;
}
/* prepare loader for the addition of a new glyph on top of the base one */
void FT_GlyphLoader_Prepare(FT_GlyphLoader loader) {
FT_GlyphLoad current = &loader->current;
current->outline.n_points = 0;
current->outline.n_contours = 0;
current->num_subglyphs = 0;
FT_GlyphLoader_Adjust_Points(loader);
FT_GlyphLoader_Adjust_Subglyphs(loader);
}
/* add current glyph to the base image - and prepare for another */
void FT_GlyphLoader_Add(FT_GlyphLoader loader) {
FT_GlyphLoad base = &loader->base;
FT_GlyphLoad current = &loader->current;
FT_UInt n_curr_contours = current->outline.n_contours;
FT_UInt n_base_points = base->outline.n_points;
FT_UInt n;
base->outline.n_points = (short)(base->outline.n_points + current->outline.n_points);
base->outline.n_contours = (short)(base->outline.n_contours + current->outline.n_contours);
base->num_subglyphs += current->num_subglyphs;
/* adjust contours count in newest outline */
for (n = 0; n < n_curr_contours; n++)
current->outline.contours[n] =
(short)(current->outline.contours[n] + n_base_points);
/* prepare for another new glyph image */
FT_GlyphLoader_Prepare(loader);
}
FT_Error FT_GlyphLoader_CopyPoints(FT_GlyphLoader target, FT_GlyphLoader source) {
FT_Error error;
FT_UInt num_points = source->base.outline.n_points;
FT_UInt num_contours = source->base.outline.n_contours;
error = FT_GlyphLoader_CheckPoints(target, num_points, num_contours);
if (!error) {
FT_Outline *out = &target->base.outline;
FT_Outline *in = &source->base.outline;
FT_MEM_COPY(out->points, in->points, num_points * sizeof(FT_Vector));
FT_MEM_COPY(out->tags, in->tags, num_points * sizeof(char));
FT_MEM_COPY(out->contours, in->contours, num_contours * sizeof(short));
/* do we need to copy the extra points? */
if (target->use_extra && source->use_extra)
FT_MEM_COPY(target->base.extra_points, source->base.extra_points, num_points * sizeof(FT_Vector));
out->n_points = (short)num_points;
out->n_contours = (short)num_contours;
FT_GlyphLoader_Adjust_Points(target);
}
return error;
}
} // End of namespace FreeType213
} // End of namespace AGS3

View File

@@ -0,0 +1,137 @@
/* 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/>.
*
*/
/***************************************************************************/
/* */
/* ftgloadr.h */
/* */
/* The FreeType glyph loader (specification). */
/* */
/* Copyright 2002 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
#ifndef AGS_LIB_FREETYPE_FTGLOADR_H
#define AGS_LIB_FREETYPE_FTGLOADR_H
#include "graphics/fonts/freetype.h"
namespace AGS3 {
namespace FreeType213 {
typedef struct FT_GlyphLoaderRec_ *FT_GlyphLoader;
#define FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS 1
#define FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES 2
#define FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID 4
#define FT_SUBGLYPH_FLAG_SCALE 8
#define FT_SUBGLYPH_FLAG_XY_SCALE 0x40
#define FT_SUBGLYPH_FLAG_2X2 0x80
#define FT_SUBGLYPH_FLAG_USE_MY_METRICS 0x200
enum {
FT_GLYPH_OWN_BITMAP = 1
};
typedef struct FT_SubGlyphRec_ {
FT_Int index;
FT_UShort flags;
FT_Int arg1;
FT_Int arg2;
FT_Matrix transform;
} FT_SubGlyphRec;
typedef FT_SubGlyphRec *FT_SubGlyph;
typedef struct FT_GlyphLoadRec_ {
FT_Outline outline; /* outline */
FT_Vector *extra_points; /* extra points table */
FT_UInt num_subglyphs; /* number of subglyphs */
FT_SubGlyph subglyphs; /* subglyphs */
} FT_GlyphLoadRec, *FT_GlyphLoad;
typedef struct FT_GlyphLoaderRec_ {
FT_Memory memory;
FT_UInt max_points;
FT_UInt max_contours;
FT_UInt max_subglyphs;
FT_Bool use_extra;
FT_GlyphLoadRec base;
FT_GlyphLoadRec current;
void* other; /* for possible future extension? */
} FT_GlyphLoaderRec;
/* create new empty glyph loader */
FT_Error FT_GlyphLoader_New(FT_Memory memory, FT_GlyphLoader *aloader);
/* add an extra points table to a glyph loader */
FT_Error FT_GlyphLoader_CreateExtra(FT_GlyphLoader loader);
/* destroy a glyph loader */
void FT_GlyphLoader_Done(FT_GlyphLoader loader);
/* reset a glyph loader (frees everything int it) */
void FT_GlyphLoader_Reset(FT_GlyphLoader loader);
/* rewind a glyph loader */
void FT_GlyphLoader_Rewind(FT_GlyphLoader loader);
/* check that there is enough room to add 'n_points' and 'n_contours' */
/* to the glyph loader */
FT_Error FT_GlyphLoader_CheckPoints(FT_GlyphLoader loader, FT_UInt n_points, FT_UInt n_contours);
/* check that there is enough room to add 'n_subs' sub-glyphs to */
/* a glyph loader */
FT_Error FT_GlyphLoader_CheckSubGlyphs(FT_GlyphLoader loader, FT_UInt n_subs);
/* prepare a glyph loader, i.e. empty the current glyph */
void FT_GlyphLoader_Prepare(FT_GlyphLoader loader);
/* add the current glyph to the base glyph */
void FT_GlyphLoader_Add(FT_GlyphLoader loader);
/* copy points from one glyph loader to another */
FT_Error FT_GlyphLoader_CopyPoints(FT_GlyphLoader target, FT_GlyphLoader source);
} // End of namespace FreeType213
} // End of namespace AGS3
#endif /* AGS_LIB_FREETYPE_FTGLOADR_H */

View File

@@ -0,0 +1,109 @@
/* 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/>.
*
*/
/***************************************************************************/
/* */
/* ftmemory.h */
/* */
/* The FreeType memory management macros (specification). */
/* */
/* Copyright 1996-2001, 2002 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
#ifndef AGS_LIB_FREETYPE_FTMEMORY_H
#define AGS_LIB_FREETYPE_FTMEMORY_H
#include <ft2build.h>
#include FT_TYPES_H
namespace AGS3 {
namespace FreeType213 {
#undef FT_SET_ERROR
#define FT_SET_ERROR(expression) ((error = (expression)) != 0)
FT_Error FT_Alloc(FT_Memory memory, FT_Long size, void **P);
FT_Error FT_Realloc(FT_Memory memory, FT_Long current, FT_Long size, void **P);
void FT_Free(FT_Memory memory, void **P);
#define FT_MEM_SET(dest, byte, count) ft_memset(dest, byte, count)
#define FT_MEM_COPY(dest, source, count) ft_memcpy(dest, source, count)
#define FT_MEM_MOVE(dest, source, count) ft_memmove(dest, source, count)
#define FT_MEM_ZERO(dest, count) FT_MEM_SET(dest, 0, count)
#define FT_ZERO(p) FT_MEM_ZERO(p, sizeof(*(p)))
#define FT_MEM_ALLOC(_pointer_, _size_) FT_Alloc(memory, _size_, (void **)&(_pointer_))
#define FT_MEM_FREE(_pointer_) FT_Free(memory, (void **)&(_pointer_))
#define FT_MEM_REALLOC(_pointer_, _current_, _size_) FT_Realloc(memory, _current_, _size_, (void **)&(_pointer_))
/*************************************************************************/
/* */
/* The following functions macros expect that their pointer argument is */
/* _typed_ in order to automatically compute array element sizes. */
/* */
#define FT_MEM_NEW(_pointer_) FT_MEM_ALLOC(_pointer_, sizeof(*(_pointer_)))
#define FT_MEM_NEW_ARRAY(_pointer_, _count_) FT_MEM_ALLOC(_pointer_, (_count_) * sizeof(*(_pointer_)))
#define FT_MEM_RENEW_ARRAY(_pointer_, _old_, _new_) FT_MEM_REALLOC(_pointer_, (_old_) * sizeof(*(_pointer_)), (_new_) * sizeof(*(_pointer_)))
/*************************************************************************/
/* */
/* the following macros are obsolete but kept for compatibility reasons */
/* */
#define FT_MEM_ALLOC_ARRAY(_pointer_, _count_, _type_) FT_MEM_ALLOC(_pointer_, (_count_) * sizeof(_type_))
#define FT_MEM_REALLOC_ARRAY(_pointer_, _old_, _new_, _type_) FT_MEM_REALLOC(_pointer_, (_old_) * sizeof(_type), (_new_) * sizeof(_type_))
/*************************************************************************/
/* */
/* The following macros are variants of their FT_MEM_XXXX equivalents; */
/* they are used to set an _implicit_ `error' variable and return TRUE */
/* if an error occurred (i.e. if 'error != 0'). */
/* */
#define FT_ALLOC(_pointer_, _size_) FT_SET_ERROR(FT_MEM_ALLOC(_pointer_, _size_))
#define FT_REALLOC(_pointer_, _current_, _size_) FT_SET_ERROR(FT_MEM_REALLOC(_pointer_, _current_, _size_))
#define FT_FREE(_pointer_) FT_MEM_FREE(_pointer_)
#define FT_NEW(_pointer_) FT_SET_ERROR(FT_MEM_NEW(_pointer_))
#define FT_NEW_ARRAY(_pointer_, _count_) FT_SET_ERROR(FT_MEM_NEW_ARRAY(_pointer_, _count_))
#define FT_RENEW_ARRAY(_pointer_, _old_, _new_) FT_SET_ERROR(FT_MEM_RENEW_ARRAY(_pointer_, _old_, _new_))
#define FT_ALLOC_ARRAY(_pointer_, _count_, _type_) FT_SET_ERROR(FT_MEM_ALLOC(_pointer_, (_count_) * sizeof(_type_)))
#define FT_REALLOC_ARRAY(_pointer_, _old_, _new_, _type_) FT_SET_ERROR(FT_MEM_REALLOC(_pointer_, (_old_) * sizeof(_type_), (_new_) * sizeof(_type_)))
} // End of namespace FreeType213
} // End of namespace AGS3
#endif /* __FTMEMORY_H__ */

View File

@@ -0,0 +1,108 @@
/* 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/>.
*
*/
/***************************************************************************/
/* */
/* ftutil.c */
/* */
/* FreeType utility file for memory and list management (body). */
/* */
/* Copyright 2002 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
#include <ft2build.h>
#include "ags/lib/freetype-2.1.3/fterrors.h"
#include "ags/lib/freetype-2.1.3/ftmemory.h"
#include "common/debug.h"
#include "common/textconsole.h"
namespace AGS3 {
namespace FreeType213 {
/**** MEMORY MANAGEMENT ****/
FT_Error FT_Alloc(FT_Memory memory, FT_Long size, void **P) {
assert(P != 0);
if (size > 0) {
*P = memory->alloc(memory, size);
if (!*P) {
warning("FT_Alloc: Out of memory? (%ld requested)", size);
return FT_Err_Out_Of_Memory;
}
FT_MEM_ZERO(*P, size);
} else
*P = NULL;
return FT_Err_Ok;
}
FT_Error FT_Realloc(FT_Memory memory, FT_Long current, FT_Long size, void **P) {
void *Q;
assert(P != 0);
/* if the original pointer is NULL, call FT_Alloc() */
if (!*P)
return FT_Alloc(memory, size, P);
/* if the new block if zero-sized, clear the current one */
if (size <= 0) {
FT_Free(memory, P);
return FT_Err_Ok;
}
Q = memory->realloc(memory, current, size, *P);
if (!Q)
goto Fail;
if (size > current)
FT_MEM_ZERO((char *)Q + current, size - current);
*P = Q;
return FT_Err_Ok;
Fail:
warning("FT_Realloc: Failed (current %ld, requested %ld)", current, size);
return FT_Err_Out_Of_Memory;
}
void FT_Free(FT_Memory memory, void **P) {
if (P && *P) {
memory->free(memory, *P);
*P = 0;
}
}
} // End of namespace FreeType213
} // End of namespace AGS3

35
engines/ags/lib/std.h Normal file
View File

@@ -0,0 +1,35 @@
/* 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/>.
*
*/
#ifndef AGS_LIB_STD_H
#define AGS_LIB_STD_H
// Declare Std namespace
namespace Std {
}
// Map Common::Std to AGS3::std
namespace AGS3 {
namespace std = ::Std;
} // namespace AGS3
#endif

View File

@@ -0,0 +1,79 @@
/* 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/>.
*
*/
#include "ags/lib/system/datetime.h"
namespace AGS3 {
/*
* Converts a date/time structure to Unix timestamp
* @author Oryx Embedded SARL (www.oryx-embedded.com)
* @version 2.0.0
*/
time_t convertDateToUnixTime(const TimeDate *date) {
uint y;
uint m;
uint d;
time_t t;
// Year
y = date->tm_year;
// Month of year
m = date->tm_mon;
// Day of month
d = date->tm_mday;
// January and February are counted as months 13 and 14 of the previous year
if (m <= 2) {
m += 12;
y -= 1;
}
// Convert years to days
t = (365 * y) + (y / 4) - (y / 100) + (y / 400);
// Convert months to days
t += (30 * m) + (3 * (m + 1) / 5) + d;
// Unix time starts on January 1st, 1970
t -= 719561;
// Convert days to seconds
t *= 86400;
// Add hours, minutes and seconds
t += (3600 * date->tm_hour) + (60 * date->tm_min) + date->tm_sec;
// Return Unix time
return t;
}
void localTime(tm *time) {
g_system->getTimeAndDate(*time);
time->tm_yday = 0;
time->tm_isdst = 0;
}
time_t getUnixTime() {
tm time;
localTime(&time);
return convertDateToUnixTime(&time);
}
} // namespace AGS3

View File

@@ -0,0 +1,49 @@
/* 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/>.
*
*/
#ifndef AGS_LIB_SYSTEM_DATETIME_H
#define AGS_LIB_SYSTEM_DATETIME_H
#include "common/scummsys.h"
#include "common/system.h"
namespace AGS3 {
struct tm : public TimeDate {
int tm_yday; // days since January 1 - [0, 365]
int tm_isdst; // daylight savings time flag
};
typedef int64 time_t;
/**
* Returns the current date and time
*/
extern void localTime(tm *time);
/**
* Returns the Unix 2038-end time
*/
extern time_t getUnixTime();
} // namespace AGS3
#endif