Initial commit
This commit is contained in:
551
engines/ags/lib/aastr-0.1.1/aarot.cpp
Normal file
551
engines/ags/lib/aastr-0.1.1/aarot.cpp
Normal 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
|
||||
218
engines/ags/lib/aastr-0.1.1/aastr.cpp
Normal file
218
engines/ags/lib/aastr-0.1.1/aastr.cpp
Normal 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
|
||||
73
engines/ags/lib/aastr-0.1.1/aastr.h
Normal file
73
engines/ags/lib/aastr-0.1.1/aastr.h
Normal 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
|
||||
1566
engines/ags/lib/aastr-0.1.1/aautil.cpp
Normal file
1566
engines/ags/lib/aastr-0.1.1/aautil.cpp
Normal file
File diff suppressed because it is too large
Load Diff
165
engines/ags/lib/aastr-0.1.1/aautil.h
Normal file
165
engines/ags/lib/aastr-0.1.1/aautil.h
Normal 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
|
||||
5232
engines/ags/lib/alfont/alfont.cpp
Normal file
5232
engines/ags/lib/alfont/alfont.cpp
Normal file
File diff suppressed because it is too large
Load Diff
128
engines/ags/lib/alfont/alfont.h
Normal file
128
engines/ags/lib/alfont/alfont.h
Normal 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
50
engines/ags/lib/allegro.h
Normal 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
|
||||
47
engines/ags/lib/allegro/aintern.h
Normal file
47
engines/ags/lib/allegro/aintern.h
Normal 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
|
||||
83
engines/ags/lib/allegro/alconfig.h
Normal file
83
engines/ags/lib/allegro/alconfig.h
Normal 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
|
||||
52
engines/ags/lib/allegro/base.h
Normal file
52
engines/ags/lib/allegro/base.h
Normal 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
|
||||
974
engines/ags/lib/allegro/color.cpp
Normal file
974
engines/ags/lib/allegro/color.cpp
Normal 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
|
||||
155
engines/ags/lib/allegro/color.h
Normal file
155
engines/ags/lib/allegro/color.h
Normal 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
|
||||
31
engines/ags/lib/allegro/config.cpp
Normal file
31
engines/ags/lib/allegro/config.cpp
Normal 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
|
||||
31
engines/ags/lib/allegro/config.h
Normal file
31
engines/ags/lib/allegro/config.h
Normal 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
|
||||
115
engines/ags/lib/allegro/draw.cpp
Normal file
115
engines/ags/lib/allegro/draw.cpp
Normal 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
|
||||
48
engines/ags/lib/allegro/draw.h
Normal file
48
engines/ags/lib/allegro/draw.h
Normal 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
|
||||
74
engines/ags/lib/allegro/error.h
Normal file
74
engines/ags/lib/allegro/error.h
Normal 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
|
||||
261
engines/ags/lib/allegro/file.cpp
Normal file
261
engines/ags/lib/allegro/file.cpp
Normal 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
|
||||
227
engines/ags/lib/allegro/file.h
Normal file
227
engines/ags/lib/allegro/file.h
Normal 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
|
||||
174
engines/ags/lib/allegro/fixed.cpp
Normal file
174
engines/ags/lib/allegro/fixed.cpp
Normal 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
|
||||
54
engines/ags/lib/allegro/fixed.h
Normal file
54
engines/ags/lib/allegro/fixed.h
Normal 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
|
||||
233
engines/ags/lib/allegro/flood.cpp
Normal file
233
engines/ags/lib/allegro/flood.cpp
Normal 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
|
||||
36
engines/ags/lib/allegro/flood.h
Normal file
36
engines/ags/lib/allegro/flood.h
Normal 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
|
||||
99
engines/ags/lib/allegro/fmaths.cpp
Normal file
99
engines/ags/lib/allegro/fmaths.cpp
Normal 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
|
||||
40
engines/ags/lib/allegro/fmaths.h
Normal file
40
engines/ags/lib/allegro/fmaths.h
Normal 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
|
||||
390
engines/ags/lib/allegro/gfx.cpp
Normal file
390
engines/ags/lib/allegro/gfx.cpp
Normal 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
|
||||
240
engines/ags/lib/allegro/gfx.h
Normal file
240
engines/ags/lib/allegro/gfx.h
Normal 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
|
||||
48
engines/ags/lib/allegro/graphics.cpp
Normal file
48
engines/ags/lib/allegro/graphics.cpp
Normal 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
|
||||
277
engines/ags/lib/allegro/math.cpp
Normal file
277
engines/ags/lib/allegro/math.cpp
Normal 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
|
||||
374
engines/ags/lib/allegro/rotate.cpp
Normal file
374
engines/ags/lib/allegro/rotate.cpp
Normal 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
|
||||
35
engines/ags/lib/allegro/rotate.h
Normal file
35
engines/ags/lib/allegro/rotate.h
Normal 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
|
||||
398
engines/ags/lib/allegro/surface.cpp
Normal file
398
engines/ags/lib/allegro/surface.cpp
Normal 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
|
||||
356
engines/ags/lib/allegro/surface.h
Normal file
356
engines/ags/lib/allegro/surface.h
Normal 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
|
||||
1019
engines/ags/lib/allegro/surface_avx2.cpp
Normal file
1019
engines/ags/lib/allegro/surface_avx2.cpp
Normal file
File diff suppressed because it is too large
Load Diff
212
engines/ags/lib/allegro/surface_generic.cpp
Normal file
212
engines/ags/lib/allegro/surface_generic.cpp
Normal 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
|
||||
989
engines/ags/lib/allegro/surface_neon.cpp
Normal file
989
engines/ags/lib/allegro/surface_neon.cpp
Normal 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
|
||||
1014
engines/ags/lib/allegro/surface_sse2.cpp
Normal file
1014
engines/ags/lib/allegro/surface_sse2.cpp
Normal file
File diff suppressed because it is too large
Load Diff
74
engines/ags/lib/allegro/system.cpp
Normal file
74
engines/ags/lib/allegro/system.cpp
Normal 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
|
||||
151
engines/ags/lib/allegro/system.h
Normal file
151
engines/ags/lib/allegro/system.h
Normal 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
|
||||
1315
engines/ags/lib/allegro/unicode.cpp
Normal file
1315
engines/ags/lib/allegro/unicode.cpp
Normal file
File diff suppressed because it is too large
Load Diff
151
engines/ags/lib/allegro/unicode.h
Normal file
151
engines/ags/lib/allegro/unicode.h
Normal 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
|
||||
155
engines/ags/lib/freetype-2.1.3/autohint/ahangles.cpp
Normal file
155
engines/ags/lib/freetype-2.1.3/autohint/ahangles.cpp
Normal 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
|
||||
75
engines/ags/lib/freetype-2.1.3/autohint/ahangles.h
Normal file
75
engines/ags/lib/freetype-2.1.3/autohint/ahangles.h
Normal 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 */
|
||||
371
engines/ags/lib/freetype-2.1.3/autohint/ahglobal.cpp
Normal file
371
engines/ags/lib/freetype-2.1.3/autohint/ahglobal.cpp
Normal 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
|
||||
64
engines/ags/lib/freetype-2.1.3/autohint/ahglobal.h
Normal file
64
engines/ags/lib/freetype-2.1.3/autohint/ahglobal.h
Normal 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 */
|
||||
1334
engines/ags/lib/freetype-2.1.3/autohint/ahglyph.cpp
Normal file
1334
engines/ags/lib/freetype-2.1.3/autohint/ahglyph.cpp
Normal file
File diff suppressed because it is too large
Load Diff
84
engines/ags/lib/freetype-2.1.3/autohint/ahglyph.h
Normal file
84
engines/ags/lib/freetype-2.1.3/autohint/ahglyph.h
Normal 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 */
|
||||
1231
engines/ags/lib/freetype-2.1.3/autohint/ahhint.cpp
Normal file
1231
engines/ags/lib/freetype-2.1.3/autohint/ahhint.cpp
Normal file
File diff suppressed because it is too large
Load Diff
78
engines/ags/lib/freetype-2.1.3/autohint/ahhint.h
Normal file
78
engines/ags/lib/freetype-2.1.3/autohint/ahhint.h
Normal 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 */
|
||||
68
engines/ags/lib/freetype-2.1.3/autohint/ahloader.h
Normal file
68
engines/ags/lib/freetype-2.1.3/autohint/ahloader.h
Normal 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 */
|
||||
315
engines/ags/lib/freetype-2.1.3/autohint/ahtypes.h
Normal file
315
engines/ags/lib/freetype-2.1.3/autohint/ahtypes.h
Normal 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 */
|
||||
50
engines/ags/lib/freetype-2.1.3/fterrors.h
Normal file
50
engines/ags/lib/freetype-2.1.3/fterrors.h
Normal 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 */
|
||||
285
engines/ags/lib/freetype-2.1.3/ftgloadr.cpp
Normal file
285
engines/ags/lib/freetype-2.1.3/ftgloadr.cpp
Normal 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
|
||||
137
engines/ags/lib/freetype-2.1.3/ftgloadr.h
Normal file
137
engines/ags/lib/freetype-2.1.3/ftgloadr.h
Normal 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 */
|
||||
109
engines/ags/lib/freetype-2.1.3/ftmemory.h
Normal file
109
engines/ags/lib/freetype-2.1.3/ftmemory.h
Normal 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__ */
|
||||
108
engines/ags/lib/freetype-2.1.3/ftutil.cpp
Normal file
108
engines/ags/lib/freetype-2.1.3/ftutil.cpp
Normal 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
35
engines/ags/lib/std.h
Normal 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
|
||||
79
engines/ags/lib/system/datetime.cpp
Normal file
79
engines/ags/lib/system/datetime.cpp
Normal 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
|
||||
49
engines/ags/lib/system/datetime.h
Normal file
49
engines/ags/lib/system/datetime.h
Normal 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
|
||||
Reference in New Issue
Block a user