scummvm/engines/tony/gfxcore.cpp

2159 lines
45 KiB
C++
Raw Normal View History

/* 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
2012-05-14 05:43:50 +00:00
/*
* This code is based on original Tony Tough source code
*
* Copyright (c) 1997-2003 Nayma Software
*/
2012-05-04 12:09:24 +00:00
#include "tony/gfxengine.h"
2012-05-03 03:14:46 +00:00
#include "tony/mpal/mpalutils.h"
#include "tony/tony.h"
namespace Tony {
2012-05-02 23:23:54 +00:00
/****************************************************************************\
* RMGfxTask Methods
2012-05-02 23:23:54 +00:00
\****************************************************************************/
RMGfxTask::RMGfxTask() {
2012-06-05 06:39:55 +00:00
_nPrior = 0;
_nInList = 0;
2012-05-02 23:23:54 +00:00
}
2012-06-05 06:39:55 +00:00
int RMGfxTask::priority() {
return _nPrior;
2012-05-02 23:23:54 +00:00
}
2012-06-05 06:39:55 +00:00
void RMGfxTask::removeThis(CORO_PARAM, bool &result) {
result = true;
2012-05-02 23:23:54 +00:00
}
2012-09-02 08:34:11 +00:00
/**
* Registration
*/
void RMGfxTask::Register() {
_nInList++;
}
void RMGfxTask::unregister() {
2012-09-02 08:34:11 +00:00
_nInList--;
assert(_nInList >= 0);
}
2012-05-02 23:23:54 +00:00
/****************************************************************************\
* RMGfxTaskSetPrior Methods
2012-05-02 23:23:54 +00:00
\****************************************************************************/
2012-06-05 06:39:55 +00:00
void RMGfxTaskSetPrior::setPriority(int nPrior) {
_nPrior = nPrior;
2012-05-02 23:23:54 +00:00
}
/****************************************************************************\
* RMGfxBuffer Methods
2012-05-02 23:23:54 +00:00
\****************************************************************************/
RMGfxBuffer::RMGfxBuffer() {
2012-06-05 06:39:55 +00:00
_dimx = _dimy = 0;
_origBuf = _buf = NULL;
2012-05-02 23:23:54 +00:00
}
RMGfxBuffer::~RMGfxBuffer() {
2012-06-05 06:39:55 +00:00
destroy();
2012-05-02 23:23:54 +00:00
}
void RMGfxBuffer::create(int dimx, int dimy, int nBpp) {
// Destroy the buffer it is already exists
2012-06-05 06:39:55 +00:00
if (_buf != NULL)
destroy();
2012-05-02 23:23:54 +00:00
// Copy the parameters in the private members
2012-06-05 06:39:55 +00:00
_dimx = dimx;
_dimy = dimy;
2012-05-02 23:23:54 +00:00
// Allocate a buffer
_origBuf = _buf = new byte[_dimx * _dimy * nBpp / 8];
assert(_buf != NULL);
Common::fill(_origBuf, _origBuf + _dimx * _dimy * nBpp / 8, 0);
2012-05-02 23:23:54 +00:00
}
void RMGfxBuffer::destroy() {
if (_origBuf != NULL && _origBuf == _buf) {
delete[] _origBuf;
_origBuf = _buf = NULL;
2012-05-02 23:23:54 +00:00
}
}
2012-06-05 06:39:55 +00:00
void RMGfxBuffer::offsetY(int nLines, int nBpp) {
_buf += nLines * getDimx() * nBpp / 8;
2012-05-02 23:23:54 +00:00
}
RMGfxBuffer::operator byte *() {
2012-06-05 06:39:55 +00:00
return _buf;
2012-05-03 03:14:46 +00:00
}
RMGfxBuffer::operator void *() {
2012-06-05 06:39:55 +00:00
return (void *)_buf;
2012-05-03 03:14:46 +00:00
}
RMGfxBuffer::RMGfxBuffer(int dimx, int dimy, int nBpp) {
create(dimx, dimy, nBpp);
2012-05-03 03:14:46 +00:00
}
int RMGfxBuffer::getDimx() {
return _dimx;
}
int RMGfxBuffer::getDimy() {
return _dimy;
}
2012-05-02 23:23:54 +00:00
/****************************************************************************\
* RMGfxSourceBuffer Methods
2012-05-02 23:23:54 +00:00
\****************************************************************************/
2012-06-05 06:39:55 +00:00
int RMGfxSourceBuffer::init(const byte *buf, int dimx, int dimy, bool bLoadPalette) {
2012-06-07 19:14:59 +00:00
create(dimx, dimy, getBpp());
2012-08-25 08:06:10 +00:00
memcpy(_buf, buf, dimx * dimy * getBpp() / 8);
2012-05-14 19:29:27 +00:00
// Invokes the method for preparing the surface (inherited)
2012-06-05 06:39:55 +00:00
prepareImage();
2012-05-02 23:23:54 +00:00
2012-06-07 19:14:59 +00:00
return dimx * dimy * getBpp() / 8;
2012-05-02 23:23:54 +00:00
}
2012-08-28 12:26:00 +00:00
void RMGfxSourceBuffer::init(Common::ReadStream &ds, int dimx, int dimy, bool bLoadPalette) {
2012-06-07 19:14:59 +00:00
create(dimx, dimy, getBpp());
ds.read(_buf, dimx * dimy * getBpp() / 8);
2012-05-14 19:29:27 +00:00
// Invokes the method for preparing the surface (inherited)
2012-06-05 06:39:55 +00:00
prepareImage();
2012-05-02 23:23:54 +00:00
}
RMGfxSourceBuffer::~RMGfxSourceBuffer() {
}
void RMGfxSourceBuffer::prepareImage() {
// Do nothing. Can be overloaded if necessary
2012-05-02 23:23:54 +00:00
}
2012-06-05 06:39:55 +00:00
bool RMGfxSourceBuffer::clip2D(int &x1, int &y1, int &u, int &v, int &width, int &height, bool bUseSrc, RMGfxTargetBuffer *buf) {
2012-05-02 23:23:54 +00:00
int destw, desth;
2012-06-05 06:39:55 +00:00
destw = buf->getDimx();
desth = buf->getDimy();
2012-05-02 23:23:54 +00:00
if (!bUseSrc) {
u = v = 0;
2012-06-05 06:39:55 +00:00
width = _dimx;
height = _dimy;
2012-05-02 23:23:54 +00:00
}
2012-05-14 19:29:27 +00:00
if (x1 > destw - 1)
return false;
2012-05-21 21:53:13 +00:00
2012-05-14 19:29:27 +00:00
if (y1 > desth - 1)
return false;
if (x1 < 0) {
2012-05-02 23:23:54 +00:00
width += x1;
2012-05-14 19:29:27 +00:00
if (width < 0)
return false;
2012-05-02 23:23:54 +00:00
u -= x1;
2012-05-14 19:29:27 +00:00
x1 = 0;
2012-05-02 23:23:54 +00:00
}
2012-05-14 19:29:27 +00:00
if (y1 < 0) {
2012-05-02 23:23:54 +00:00
height += y1;
2012-05-14 19:29:27 +00:00
if (height < 0)
return false;
2012-05-02 23:23:54 +00:00
v -= y1;
y1 = 0;
}
if (x1 + width - 1 > destw - 1)
width = destw - x1;
if (y1 + height - 1 > desth - 1)
height = desth - y1;
return (width > 1 && height > 1);
2012-05-02 23:23:54 +00:00
}
/**
* Initializes a surface by resource Id
*
2012-05-21 21:53:13 +00:00
* @param resID Resource ID
* @param dimx Buffer X dimension
* @param dimy Buffer Y dimension
*/
2012-06-05 06:39:55 +00:00
int RMGfxSourceBuffer::init(uint32 resID, int dimx, int dimy, bool bLoadPalette) {
return init(RMRes(resID), dimx, dimy, bLoadPalette);
2012-05-03 03:14:46 +00:00
}
2012-05-02 23:23:54 +00:00
2012-09-02 08:34:11 +00:00
void RMGfxSourceBuffer::offsetY(int nLines) {
RMGfxBuffer::offsetY(nLines, getBpp());
}
2012-05-02 23:23:54 +00:00
/****************************************************************************\
* RMGfxWoodyBuffer Methods
2012-05-02 23:23:54 +00:00
\****************************************************************************/
RMGfxWoodyBuffer::~RMGfxWoodyBuffer() {
}
2012-06-05 06:39:55 +00:00
void RMGfxWoodyBuffer::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
// Draw the OT list
2012-06-05 06:39:55 +00:00
CORO_INVOKE_0(drawOT);
2012-05-02 23:23:54 +00:00
// Draw itself into the target buffer
2012-06-05 06:39:55 +00:00
CORO_INVOKE_2(RMGfxSourceBuffer16::draw, bigBuf, prim);
CORO_END_CODE;
2012-05-02 23:23:54 +00:00
}
RMGfxWoodyBuffer::RMGfxWoodyBuffer() {
2012-05-03 03:14:46 +00:00
}
RMGfxWoodyBuffer::RMGfxWoodyBuffer(int dimx, int dimy)
: RMGfxBuffer(dimx, dimy, 16) {
2012-05-03 03:14:46 +00:00
}
2012-05-02 23:23:54 +00:00
/****************************************************************************\
* RMGfxTargetBuffer Methods
2012-05-02 23:23:54 +00:00
\****************************************************************************/
RMGfxTargetBuffer::RMGfxTargetBuffer() {
2012-06-07 19:14:59 +00:00
_otlist = NULL;
2012-06-05 06:39:55 +00:00
_otSize = 0;
_trackDirtyRects = false;
2012-05-02 23:23:54 +00:00
}
RMGfxTargetBuffer::~RMGfxTargetBuffer() {
2012-06-05 06:39:55 +00:00
clearOT();
2012-05-02 23:23:54 +00:00
}
void RMGfxTargetBuffer::clearOT() {
2012-05-02 23:23:54 +00:00
OTList *cur, *n;
2012-06-07 19:14:59 +00:00
cur = _otlist;
2012-05-02 23:23:54 +00:00
while (cur != NULL) {
cur->_prim->_task->unregister();
delete cur->_prim;
n = cur->_next;
2012-05-02 23:23:54 +00:00
delete cur;
cur = n;
}
2012-06-07 19:14:59 +00:00
_otlist = NULL;
2012-05-02 23:23:54 +00:00
}
2012-06-05 06:39:55 +00:00
void RMGfxTargetBuffer::drawOT(CORO_PARAM) {
CORO_BEGIN_CONTEXT;
2012-05-14 19:29:27 +00:00
OTList *cur;
OTList *prev;
OTList *next;
RMGfxPrimitive *myprim;
bool result;
CORO_END_CONTEXT(_ctx);
2012-05-02 23:23:54 +00:00
CORO_BEGIN_CODE(_ctx);
_ctx->prev = NULL;
2012-06-07 19:14:59 +00:00
_ctx->cur = _otlist;
2012-05-02 23:23:54 +00:00
2012-05-14 19:29:27 +00:00
while (_ctx->cur != NULL) {
// Call the task Draw method, passing it a copy of the original
_ctx->myprim = _ctx->cur->_prim->duplicate();
CORO_INVOKE_2(_ctx->cur->_prim->_task->draw, *this, _ctx->myprim);
delete _ctx->myprim;
2012-05-02 23:23:54 +00:00
// Check if it's time to remove the task from the OT list
CORO_INVOKE_1(_ctx->cur->_prim->_task->removeThis, _ctx->result);
if (_ctx->result) {
// De-register the task
_ctx->cur->_prim->_task->unregister();
2012-05-02 23:23:54 +00:00
// Delete task, freeing the memory
delete _ctx->cur->_prim;
_ctx->next = _ctx->cur->_next;
delete _ctx->cur;
2012-05-02 23:23:54 +00:00
// If it was the first item, update the list head
if (_ctx->prev == NULL)
2012-06-07 19:14:59 +00:00
_otlist = _ctx->next;
// Otherwise update the next pinter of the previous item
2012-05-02 23:23:54 +00:00
else
_ctx->prev->_next = _ctx->next;
2012-05-02 23:23:54 +00:00
_ctx->cur = _ctx->next;
2012-05-02 23:23:54 +00:00
} else {
// Update the pointer to the previous item, and the current to the next
_ctx->prev = _ctx->cur;
_ctx->cur = _ctx->cur->_next;
2012-05-02 23:23:54 +00:00
}
}
CORO_END_CODE;
2012-05-02 23:23:54 +00:00
}
2012-06-05 06:39:55 +00:00
void RMGfxTargetBuffer::addPrim(RMGfxPrimitive *prim) {
2012-05-02 23:23:54 +00:00
int nPrior;
OTList *cur, *n;
// Warn of the OT listing
2012-06-05 06:39:55 +00:00
prim->_task->Register();
2012-05-02 23:23:54 +00:00
// Check the priority
2012-06-05 06:39:55 +00:00
nPrior = prim->_task->priority();
2012-05-02 23:23:54 +00:00
n = new OTList(prim);
// Empty list
2012-06-07 19:14:59 +00:00
if (_otlist == NULL) {
_otlist = n;
_otlist->_next = NULL;
2012-05-02 23:23:54 +00:00
}
// Inclusion in the head
else if (nPrior < _otlist->_prim->_task->priority()) {
n->_next = _otlist;
2012-06-07 19:14:59 +00:00
_otlist = n;
2012-05-02 23:23:54 +00:00
} else {
2012-06-07 19:14:59 +00:00
cur = _otlist;
while (cur->_next != NULL && nPrior > cur->_next->_prim->_task->priority())
cur = cur->_next;
2012-05-02 23:23:54 +00:00
n->_next = cur->_next;
cur->_next = n;
2012-05-02 23:23:54 +00:00
}
}
void RMGfxTargetBuffer::addDirtyRect(const Common::Rect &r) {
assert(r.isValidRect());
if (_trackDirtyRects && r.width() > 0 && r.height() > 0)
_currentDirtyRects.push_back(r);
}
Common::List<Common::Rect> &RMGfxTargetBuffer::getDirtyRects() {
// Copy rects from both the current and previous frame into the output dirty rects list
Common::List<Common::Rect>::iterator i;
_dirtyRects.clear();
for (i = _previousDirtyRects.begin(); i != _previousDirtyRects.end(); ++i)
_dirtyRects.push_back(*i);
for (i = _currentDirtyRects.begin(); i != _currentDirtyRects.end(); ++i)
_dirtyRects.push_back(*i);
mergeDirtyRects();
return _dirtyRects;
}
/**
* Move the set of dirty rects from the finished current frame into the previous frame list.
*/
void RMGfxTargetBuffer::clearDirtyRects() {
Common::List<Common::Rect>::iterator i;
_previousDirtyRects.clear();
for (i = _currentDirtyRects.begin(); i != _currentDirtyRects.end(); ++i)
_previousDirtyRects.push_back(*i);
_currentDirtyRects.clear();
}
/**
* Merges any clipping rectangles that overlap to try and reduce
* the total number of clip rectangles.
*/
void RMGfxTargetBuffer::mergeDirtyRects() {
if (_dirtyRects.size() <= 1)
return;
Common::List<Common::Rect>::iterator rOuter, rInner;
for (rOuter = _dirtyRects.begin(); rOuter != _dirtyRects.end(); ++rOuter) {
rInner = rOuter;
while (++rInner != _dirtyRects.end()) {
if ((*rOuter).intersects(*rInner)) {
// these two rectangles overlap or
// are next to each other - merge them
(*rOuter).extend(*rInner);
// remove the inner rect from the list
_dirtyRects.erase(rInner);
// move back to beginning of list
rInner = rOuter;
}
}
}
}
2012-05-03 03:14:46 +00:00
uint16 *RMGfxTargetBuffer::_precalcTable = NULL;
/**
* Set up the black & white precalculated mapping table. This is only
* called if the user selects the black & white option.
*/
void RMGfxTargetBuffer::createBWPrecalcTable() {
_precalcTable = new uint16[0x8000];
for (int i = 0; i < 0x8000; i++) {
int r = (i >> 10) & 0x1F;
int g = (i >> 5) & 0x1F;
int b = i & 0x1F;
int min = MIN(r, MIN(g, b));
int max = MAX(r, MAX(g, b));
min = (min + max) / 2;
r = CLIP(min + 8 - 8, 0, 31);
g = CLIP(min + 5 - 8, 0, 31);
b = CLIP(min + 0 - 8, 0, 31);
_precalcTable[i] = (r << 10) | (g << 5) | b;
}
}
/**
* Frees the black & white precalculated mapping table.
*/
void RMGfxTargetBuffer::freeBWPrecalcTable() {
delete[] _precalcTable;
_precalcTable = NULL;
}
2012-09-02 08:34:11 +00:00
RMGfxTargetBuffer::operator byte *() {
return _buf;
}
RMGfxTargetBuffer::operator void *() {
return (void *)_buf;
}
RMGfxTargetBuffer::operator uint16 *() {
// FIXME: This may not be endian safe
return (uint16 *)_buf;
}
/**
* Offseting buffer
*/
void RMGfxTargetBuffer::offsetY(int nLines) {
RMGfxBuffer::offsetY(nLines, 16);
}
void RMGfxTargetBuffer::setTrackDirtyRects(bool v) {
_trackDirtyRects = v;
}
bool RMGfxTargetBuffer::getTrackDirtyRects() const {
return _trackDirtyRects;
}
2012-05-02 23:23:54 +00:00
/****************************************************************************\
* RMGfxSourceBufferPal Methods
2012-05-02 23:23:54 +00:00
\****************************************************************************/
RMGfxSourceBufferPal::~RMGfxSourceBufferPal() {
}
2012-06-05 06:39:55 +00:00
int RMGfxSourceBufferPal::loadPaletteWA(const byte *buf, bool bSwapped) {
2012-06-13 22:11:56 +00:00
if (bSwapped) {
for (int i = 0; i < (1 << getBpp()); i++) {
2012-06-05 06:39:55 +00:00
_pal[i * 3 + 0] = buf[i * 3 + 2];
_pal[i * 3 + 1] = buf[i * 3 + 1];
_pal[i * 3 + 2] = buf[i * 3 + 0];
2012-05-02 23:23:54 +00:00
}
2012-06-13 22:11:56 +00:00
} else {
2012-08-25 08:06:10 +00:00
memcpy(_pal, buf, (1 << getBpp()) * 3);
2012-06-13 22:11:56 +00:00
}
2012-05-14 19:29:27 +00:00
2012-06-05 06:39:55 +00:00
preparePalette();
2012-05-02 23:23:54 +00:00
2012-06-07 19:14:59 +00:00
return (1 << getBpp()) * 3;
2012-05-02 23:23:54 +00:00
}
2012-06-05 06:39:55 +00:00
int RMGfxSourceBufferPal::loadPalette(const byte *buf) {
for (int i = 0; i < 256; i++)
2012-08-25 08:06:10 +00:00
memcpy(_pal + i * 3, buf + i * 4, 3);
2012-05-14 19:29:27 +00:00
2012-06-05 06:39:55 +00:00
preparePalette();
2012-05-02 23:23:54 +00:00
2012-06-07 19:14:59 +00:00
return (1 << getBpp()) * 4;
2012-05-02 23:23:54 +00:00
}
void RMGfxSourceBufferPal::preparePalette() {
for (int i = 0; i < 256; i++) {
2012-06-05 06:39:55 +00:00
_palFinal[i] = (((int)_pal[i * 3 + 0] >> 3) << 10) |
(((int)_pal[i * 3 + 1] >> 3) << 5) |
(((int)_pal[i * 3 + 2] >> 3) << 0);
2012-05-02 23:23:54 +00:00
}
}
2012-06-05 06:39:55 +00:00
int RMGfxSourceBufferPal::init(const byte *buf, int dimx, int dimy, bool bLoadPalette) {
// Load the RAW image
int read = RMGfxSourceBuffer::init(buf, dimx, dimy);
2012-05-14 19:29:27 +00:00
// Load the palette if necessary
2012-05-02 23:23:54 +00:00
if (bLoadPalette)
2012-06-05 06:39:55 +00:00
read += loadPaletteWA(&buf[read]);
2012-05-02 23:23:54 +00:00
return read;
}
2012-08-28 12:26:00 +00:00
void RMGfxSourceBufferPal::init(Common::ReadStream &ds, int dimx, int dimy, bool bLoadPalette) {
// Load the RAW image
2012-06-05 06:39:55 +00:00
RMGfxSourceBuffer::init(ds, dimx, dimy);
2012-05-14 19:29:27 +00:00
// Load the palette if necessary
2012-05-02 23:23:54 +00:00
if (bLoadPalette) {
byte *suxpal = new byte[256 * 3];
ds.read(suxpal, 256 * 3);
2012-06-05 06:39:55 +00:00
loadPaletteWA(suxpal);
2012-05-02 23:23:54 +00:00
delete[] suxpal;
}
}
2012-06-05 06:39:55 +00:00
int RMGfxSourceBufferPal::loadPalette(uint32 resID) {
return loadPalette(RMRes(resID));
2012-05-03 03:14:46 +00:00
}
2012-05-02 23:23:54 +00:00
2012-06-05 06:39:55 +00:00
int RMGfxSourceBufferPal::loadPaletteWA(uint32 resID, bool bSwapped) {
return loadPaletteWA(RMRes(resID), bSwapped);
2012-05-03 03:14:46 +00:00
}
2012-05-02 23:23:54 +00:00
/****************************************************************************\
* RMGfxSourceBuffer4 Methods
2012-05-02 23:23:54 +00:00
\****************************************************************************/
2012-06-05 06:39:55 +00:00
void RMGfxSourceBuffer4::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
2012-05-02 23:23:54 +00:00
}
RMGfxSourceBuffer4::RMGfxSourceBuffer4(int dimx, int dimy)
: RMGfxBuffer(dimx, dimy, 4) {
2012-06-05 06:39:55 +00:00
setPriority(0);
2012-05-03 03:14:46 +00:00
}
2012-05-02 23:23:54 +00:00
/**
* Returns the number of bits per pixel of the surface
*
2012-05-21 21:53:13 +00:00
* @returns Bit per pixel
*/
2012-06-07 19:14:59 +00:00
int RMGfxSourceBuffer4::getBpp() {
2012-05-03 03:14:46 +00:00
return 4;
}
void RMGfxSourceBuffer4::create(int dimx, int dimy) {
RMGfxBuffer::create(dimx, dimy, 4);
2012-05-03 03:14:46 +00:00
}
2012-05-02 23:23:54 +00:00
/****************************************************************************\
* RMGfxSourceBuffer8 Methods
2012-05-02 23:23:54 +00:00
\****************************************************************************/
RMGfxSourceBuffer8::~RMGfxSourceBuffer8() {
}
2012-06-05 06:39:55 +00:00
void RMGfxSourceBuffer8::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
int width = 0, height = 0, u = 0, v = 0;
2012-06-05 06:39:55 +00:00
int bufx = bigBuf.getDimx();
2012-05-02 23:23:54 +00:00
uint16 *buf = bigBuf;
2012-06-05 06:39:55 +00:00
byte *raw = _buf;
2012-05-02 23:23:54 +00:00
// Destination buffer
2012-05-02 23:23:54 +00:00
RMRect dst;
2012-06-05 06:39:55 +00:00
if (prim->haveDst())
2012-06-07 19:14:59 +00:00
dst = prim->getDst();
2012-05-14 19:29:27 +00:00
// Clipping
2012-06-05 06:39:55 +00:00
if (prim->haveSrc()) {
2012-06-11 18:24:25 +00:00
u = prim->getSrc()._x1;
v = prim->getSrc()._y1;
2012-05-14 19:29:27 +00:00
2012-06-07 19:14:59 +00:00
width = prim->getSrc().width();
height = prim->getSrc().height();
2012-05-02 23:23:54 +00:00
}
2012-06-11 18:24:25 +00:00
if (!clip2D(dst._x1, dst._y1, u, v, width, height, prim->haveSrc(), &bigBuf))
2012-05-02 23:23:54 +00:00
return;
// Starting offset into the buffer
2012-06-11 18:24:25 +00:00
buf += dst._y1 * bufx + dst._x1;
2012-05-02 23:23:54 +00:00
// Normal step
2012-06-05 06:39:55 +00:00
if (_bTrasp0) {
for (int y = 0; y < height; y++) {
2012-06-05 06:39:55 +00:00
raw = _buf + (y + v) * _dimx + u;
2012-05-02 23:23:54 +00:00
for (int x = 0; x < width; x++) {
2012-06-05 06:39:55 +00:00
if (*raw)
*buf = _palFinal[*raw];
2012-05-02 23:23:54 +00:00
buf++;
raw++;
}
buf += bufx - width;
}
} else {
for (int y = 0; y < height; y++) {
2012-06-05 06:39:55 +00:00
raw = _buf + (y + v) * _dimx + u;
2012-05-02 23:23:54 +00:00
for (int x = 0; x < width; x += 2) {
2012-06-05 06:39:55 +00:00
buf[0] = _palFinal[raw[0]];
buf[1] = _palFinal[raw[1]];
2012-05-14 19:29:27 +00:00
2012-05-03 13:08:19 +00:00
buf += 2;
raw += 2;
2012-05-02 23:23:54 +00:00
}
2012-05-03 13:08:19 +00:00
buf += bufx - width;
2012-05-02 23:23:54 +00:00
}
}
// Specify the drawn area
bigBuf.addDirtyRect(Common::Rect(dst._x1, dst._y1, dst._x1 + width, dst._y1 + height));
2012-05-03 03:14:46 +00:00
}
RMGfxSourceBuffer8::RMGfxSourceBuffer8(int dimx, int dimy)
: RMGfxBuffer(dimx, dimy, 8) {
2012-06-05 06:39:55 +00:00
setPriority(0);
_bTrasp0 = false;
2012-05-03 03:14:46 +00:00
}
2012-05-02 23:23:54 +00:00
RMGfxSourceBuffer8::RMGfxSourceBuffer8(bool bTrasp0) {
2012-06-05 06:39:55 +00:00
_bTrasp0 = bTrasp0;
2012-05-03 03:14:46 +00:00
}
/**
* Returns the number of bits per pixel of the surface
*
2012-05-21 21:53:13 +00:00
* @returns Bit per pixel
*/
2012-06-07 19:14:59 +00:00
int RMGfxSourceBuffer8::getBpp() {
2012-05-03 03:14:46 +00:00
return 8;
}
void RMGfxSourceBuffer8::create(int dimx, int dimy) {
RMGfxBuffer::create(dimx, dimy, 8);
2012-05-02 23:23:54 +00:00
}
2012-05-14 19:29:27 +00:00
#define GETRED(x) (((x) >> 10) & 0x1F)
2012-05-02 23:23:54 +00:00
#define GETGREEN(x) (((x) >> 5) & 0x1F)
2012-06-07 19:14:59 +00:00
#define GETBLUE(x) ((x) & 0x1F)
2012-05-02 23:23:54 +00:00
/****************************************************************************\
* RMGfxSourceBuffer8AB Methods
2012-05-02 23:23:54 +00:00
\****************************************************************************/
RMGfxSourceBuffer8AB::~RMGfxSourceBuffer8AB() {
}
2012-06-05 06:39:55 +00:00
int RMGfxSourceBuffer8AB::calcTrasp(int fore, int back) {
int r = (GETRED(fore) >> 2) + (GETRED(back) >> 1);
int g = (GETGREEN(fore) >> 2) + (GETGREEN(back) >> 1);
int b = (GETBLUE(fore) >> 2) + (GETBLUE(back) >> 1);
2012-05-02 23:23:54 +00:00
if (r > 0x1F)
r = 0x1F;
if (g > 0x1F)
g = 0x1F;
if (b > 0x1F)
b = 0x1F;
2012-05-02 23:23:54 +00:00
2012-05-14 19:29:27 +00:00
return (r << 10) | (g << 5) | b;
2012-05-02 23:23:54 +00:00
}
2012-06-05 06:39:55 +00:00
void RMGfxSourceBuffer8AB::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
int width = 0, height = 0, u = 0, v = 0;
2012-06-05 06:39:55 +00:00
int bufx = bigBuf.getDimx();
2012-05-02 23:23:54 +00:00
uint16 *buf = bigBuf;
2012-06-05 06:39:55 +00:00
byte *raw = _buf;
2012-05-02 23:23:54 +00:00
// Destination buffer
2012-05-02 23:23:54 +00:00
RMRect dst;
2012-06-05 06:39:55 +00:00
if (prim->haveDst())
2012-06-07 19:14:59 +00:00
dst = prim->getDst();
2012-05-14 19:29:27 +00:00
// Clipping
2012-06-05 06:39:55 +00:00
if (prim->haveSrc()) {
2012-06-11 18:24:25 +00:00
u = prim->getSrc()._x1;
v = prim->getSrc()._y1;
2012-05-14 19:29:27 +00:00
2012-06-07 19:14:59 +00:00
width = prim->getSrc().width();
height = prim->getSrc().height();
2012-05-02 23:23:54 +00:00
}
2012-06-11 18:24:25 +00:00
if (!clip2D(dst._x1, dst._y1, u, v, width, height, prim->haveSrc(), &bigBuf))
2012-05-02 23:23:54 +00:00
return;
// Starting offset into the buffer
2012-06-11 18:24:25 +00:00
buf += dst._y1 * bufx + dst._x1;
2012-05-02 23:23:54 +00:00
// Passaggio normale
2012-06-05 06:39:55 +00:00
if (_bTrasp0) {
for (int y = 0; y < height; y++) {
2012-06-05 06:39:55 +00:00
raw = _buf + (y + v) * _dimx + u;
2012-05-02 23:23:54 +00:00
for (int x = 0; x < width; x++) {
2012-06-05 06:39:55 +00:00
if (*raw)
*buf = calcTrasp(_palFinal[*raw], *buf);
2012-05-02 23:23:54 +00:00
buf++;
raw++;
}
buf += bufx - width;
}
} else {
for (int y = 0; y < height; y++) {
2012-06-05 06:39:55 +00:00
raw = _buf + (y + v) * _dimx + u;
2012-05-02 23:23:54 +00:00
for (int x = 0; x < width; x += 2) {
2012-06-05 06:39:55 +00:00
buf[0] = calcTrasp(_palFinal[raw[0]], buf[0]);
buf[1] = calcTrasp(_palFinal[raw[1]], buf[1]);
2012-05-14 19:29:27 +00:00
2012-05-02 23:23:54 +00:00
buf += 2;
raw += 2;
}
buf += bufx - width;
}
}
// Specify the drawn area
bigBuf.addDirtyRect(Common::Rect(dst._x1, dst._y1, dst._x1 + width, dst._y1 + height));
2012-05-02 23:23:54 +00:00
}
/****************************************************************************\
* RMGfxSourceBuffer8RLE Methods
2012-05-02 23:23:54 +00:00
\****************************************************************************/
2012-06-07 19:14:59 +00:00
byte RMGfxSourceBuffer8RLE::_megaRLEBuf[512 * 1024];
2012-05-02 23:23:54 +00:00
2012-06-05 06:39:55 +00:00
void RMGfxSourceBuffer8RLE::setAlphaBlendColor(int color) {
2012-06-07 19:14:59 +00:00
_alphaBlendColor = color;
2012-05-02 23:23:54 +00:00
}
RMGfxSourceBuffer8RLE::RMGfxSourceBuffer8RLE() {
2012-06-07 19:14:59 +00:00
_alphaBlendColor = -1;
_bNeedRLECompress = true;
2012-06-05 06:39:55 +00:00
_buf = NULL;
_alphaR = _alphaG = _alphaB = 0;
2012-05-02 23:23:54 +00:00
}
RMGfxSourceBuffer8RLE::~RMGfxSourceBuffer8RLE() {
2012-06-05 06:39:55 +00:00
if (_buf != NULL) {
delete[] _buf;
_buf = NULL;
2012-05-02 23:23:54 +00:00
}
}
2012-06-05 06:39:55 +00:00
int RMGfxSourceBuffer8RLE::init(const byte *buf, int dimx, int dimy, bool bLoadPalette) {
return RMGfxSourceBufferPal::init(buf, dimx, dimy, bLoadPalette);
2012-05-02 23:23:54 +00:00
}
2012-08-28 12:26:00 +00:00
void RMGfxSourceBuffer8RLE::init(Common::ReadStream &ds, int dimx, int dimy, bool bLoadPalette) {
2012-06-07 19:14:59 +00:00
if (_bNeedRLECompress) {
2012-06-05 06:39:55 +00:00
RMGfxSourceBufferPal::init(ds, dimx, dimy, bLoadPalette);
2012-05-02 23:23:54 +00:00
} else {
int size = ds.readSint32LE();
2012-06-05 06:39:55 +00:00
_buf = new byte[size];
ds.read(_buf, size);
2012-05-02 23:23:54 +00:00
2012-06-05 06:39:55 +00:00
_dimx = dimx;
_dimy = dimy;
2012-05-02 23:23:54 +00:00
}
}
void RMGfxSourceBuffer8RLE::preparePalette() {
// Invoke the parent method
2012-06-05 06:39:55 +00:00
RMGfxSourceBuffer8::preparePalette();
2012-05-02 23:23:54 +00:00
// Handle RGB alpha blending
2012-06-07 19:14:59 +00:00
if (_alphaBlendColor != -1) {
_alphaR = (_palFinal[_alphaBlendColor] >> 10) & 0x1F;
_alphaG = (_palFinal[_alphaBlendColor] >> 5) & 0x1F;
_alphaB = (_palFinal[_alphaBlendColor]) & 0x1F;
2012-05-02 23:23:54 +00:00
}
}
void RMGfxSourceBuffer8RLE::prepareImage() {
// Invoke the parent method
2012-06-05 06:39:55 +00:00
RMGfxSourceBuffer::prepareImage();
2012-05-02 23:23:54 +00:00
// Compress
2012-06-05 06:39:55 +00:00
compressRLE();
2012-05-02 23:23:54 +00:00
}
void RMGfxSourceBuffer8RLE::setAlreadyCompressed() {
2012-06-07 19:14:59 +00:00
_bNeedRLECompress = false;
2012-05-02 23:23:54 +00:00
}
void RMGfxSourceBuffer8RLE::compressRLE() {
2012-05-02 23:23:54 +00:00
byte *startline;
byte *cur;
byte curdata;
byte *src;
byte *startsrc;
int rep;
2012-05-14 19:29:27 +00:00
// Perform RLE compression for lines
2012-06-07 19:14:59 +00:00
cur = _megaRLEBuf;
2012-06-05 06:39:55 +00:00
src = _buf;
for (int y = 0; y < _dimy; y++) {
// Save the beginning of the line
2012-05-02 23:23:54 +00:00
startline = cur;
2012-05-14 19:29:27 +00:00
// Leave space for the length of the line
2012-05-02 23:23:54 +00:00
cur += 2;
// It starts from the empty space
2012-05-02 23:23:54 +00:00
curdata = 0;
rep = 0;
startsrc = src;
for (int x = 0; x < _dimx;) {
2012-06-07 19:14:59 +00:00
if ((curdata == 0 && *src == 0) || (curdata == 1 && *src == _alphaBlendColor)
|| (curdata == 2 && (*src != _alphaBlendColor && *src != 0))) {
2012-05-02 23:23:54 +00:00
src++;
rep++;
x++;
} else {
if (curdata == 0) {
rleWriteTrasp(cur, rep);
2012-05-02 23:23:54 +00:00
curdata++;
2012-05-14 19:29:27 +00:00
} else if (curdata == 1) {
rleWriteAlphaBlend(cur, rep);
2012-05-02 23:23:54 +00:00
curdata++;
} else {
rleWriteData(cur, rep, startsrc);
2012-05-02 23:23:54 +00:00
curdata = 0;
}
rep = 0;
startsrc = src;
}
2012-05-14 19:29:27 +00:00
}
// Pending data?
2012-05-02 23:23:54 +00:00
if (curdata == 1) {
rleWriteAlphaBlend(cur, rep);
rleWriteData(cur, 0, NULL);
2012-05-02 23:23:54 +00:00
}
2012-05-14 19:29:27 +00:00
2012-05-02 23:23:54 +00:00
if (curdata == 2) {
rleWriteData(cur, rep, startsrc);
2012-05-02 23:23:54 +00:00
}
// End of line
rleWriteEOL(cur);
2012-05-02 23:23:54 +00:00
// Write the length of the line
2012-05-02 23:23:54 +00:00
WRITE_LE_UINT16(startline, (uint16)(cur - startline));
}
2012-05-14 19:29:27 +00:00
// Delete the original image
2012-06-05 06:39:55 +00:00
delete[] _buf;
2012-05-02 23:23:54 +00:00
// Copy the compressed image
int bufSize = cur - _megaRLEBuf;
_buf = new byte[bufSize];
Common::copy(_megaRLEBuf, _megaRLEBuf + bufSize, _buf);
2012-05-02 23:23:54 +00:00
}
2012-06-05 06:39:55 +00:00
void RMGfxSourceBuffer8RLE::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
2012-05-02 23:23:54 +00:00
byte *src;
uint16 *buf = bigBuf;
int u, v, width, height;
2012-05-14 19:29:27 +00:00
// Clipping
int x1 = prim->getDst()._x1;
int y1 = prim->getDst()._y1;
2012-06-05 06:39:55 +00:00
if (!clip2D(x1, y1, u, v, width, height, false, &bigBuf))
2012-05-02 23:23:54 +00:00
return;
// Go forward through the RLE lines
2012-06-05 06:39:55 +00:00
src = _buf;
for (int y = 0; y < v; y++)
2012-05-02 23:23:54 +00:00
src += READ_LE_UINT16(src);
// Calculate the position in the destination buffer
2012-06-05 06:39:55 +00:00
buf += y1 * bigBuf.getDimx();
2012-05-02 23:23:54 +00:00
// Loop
2012-06-05 06:39:55 +00:00
if (prim->isFlipped()) {
// Eliminate horizontal clipping
2012-05-02 23:23:54 +00:00
// width = m_dimx;
// x1=prim->Dst().x1;
// Clipping
2012-06-05 06:39:55 +00:00
u = _dimx - (width + u);
2012-06-11 18:24:25 +00:00
x1 = (prim->getDst()._x1 + _dimx - 1) - u;
2012-05-02 23:23:54 +00:00
if (width > x1)
width = x1;
// Specify the drawn area
bigBuf.addDirtyRect(Common::Rect(x1 - width, y1, x1 + 1, y1 + height));
for (int y = 0; y < height; y++) {
// Decompression
rleDecompressLineFlipped(buf + x1, src + 2, u, width);
2012-05-02 23:23:54 +00:00
// Next line
2012-05-02 23:23:54 +00:00
src += READ_LE_UINT16(src);
// Skip to the next line
2012-06-05 06:39:55 +00:00
buf += bigBuf.getDimx();
2012-05-02 23:23:54 +00:00
}
2012-05-03 13:08:19 +00:00
} else {
// Specify the drawn area
bigBuf.addDirtyRect(Common::Rect(x1, y1, x1 + width, y1 + height));
for (int y = 0; y < height; y++) {
// Decompression
rleDecompressLine(buf + x1, src + 2, u, width);
2012-05-02 23:23:54 +00:00
// Next line
2012-05-02 23:23:54 +00:00
src += READ_LE_UINT16(src);
// Skip to the next line
2012-06-05 06:39:55 +00:00
buf += bigBuf.getDimx();
2012-05-02 23:23:54 +00:00
}
}
}
/****************************************************************************\
* RMGfxSourceBuffer8RLEByte Methods
2012-05-02 23:23:54 +00:00
\****************************************************************************/
RMGfxSourceBuffer8RLEByte::~RMGfxSourceBuffer8RLEByte() {
}
void RMGfxSourceBuffer8RLEByte::rleWriteTrasp(byte *&cur, int rep) {
2012-05-02 23:23:54 +00:00
assert(rep < 255);
2012-05-14 19:29:27 +00:00
*cur ++ = rep;
2012-05-02 23:23:54 +00:00
}
void RMGfxSourceBuffer8RLEByte::rleWriteAlphaBlend(byte *&cur, int rep) {
2012-05-02 23:23:54 +00:00
assert(rep < 255);
2012-05-14 19:29:27 +00:00
*cur ++ = rep;
2012-05-02 23:23:54 +00:00
}
void RMGfxSourceBuffer8RLEByte::rleWriteData(byte *&cur, int rep, byte *src) {
2012-05-02 23:23:54 +00:00
assert(rep < 256);
2012-05-14 19:29:27 +00:00
*cur ++ = rep;
2012-05-02 23:23:54 +00:00
if (rep > 0) {
2012-08-25 08:06:10 +00:00
memcpy(cur, src, rep);
2012-05-02 23:23:54 +00:00
cur += rep;
src += rep;
}
return;
}
void RMGfxSourceBuffer8RLEByte::rleWriteEOL(byte *&cur) {
2012-05-14 19:29:27 +00:00
*cur ++ = 0xFF;
2012-05-02 23:23:54 +00:00
}
void RMGfxSourceBuffer8RLEByte::rleDecompressLine(uint16 *dst, byte *src, int nStartSkip, int nLength) {
int n;
2012-05-02 23:23:54 +00:00
2012-05-14 19:29:27 +00:00
if (nStartSkip == 0)
goto RLEByteDoTrasp;
2012-05-02 23:23:54 +00:00
while (1) {
assert(nStartSkip > 0);
// TRASP
n = *src++;
if (n == 0xFF)
return;
2012-05-14 19:29:27 +00:00
2012-05-03 13:08:19 +00:00
if (n >= nStartSkip) {
2012-05-02 23:23:54 +00:00
dst += n - nStartSkip;
nLength -= n - nStartSkip;
if (nLength > 0)
goto RLEByteDoAlpha;
else
return;
}
nStartSkip -= n;
assert(nStartSkip > 0);
2012-05-14 19:29:27 +00:00
2012-05-02 23:23:54 +00:00
// ALPHA
n = *src++;
if (n >= nStartSkip) {
n -= nStartSkip;
goto RLEByteDoAlpha2;
}
nStartSkip -= n;
assert(nStartSkip > 0);
// DATA
n = *src++;
if (n >= nStartSkip) {
src += nStartSkip;
n -= nStartSkip;
goto RLEByteDoCopy2;
}
nStartSkip -= n;
src += n;
}
while (1) {
RLEByteDoTrasp:
// Get the trasp of s**t
2012-05-02 23:23:54 +00:00
n = *src++;
2012-05-14 19:29:27 +00:00
2012-05-02 23:23:54 +00:00
// EOL?
if (n == 0xFF)
2012-05-14 19:29:27 +00:00
return;
2012-05-02 23:23:54 +00:00
dst += n;
nLength -= n;
if (nLength <= 0)
return;
RLEByteDoAlpha:
// Alpha
n = *src++;
RLEByteDoAlpha2:
if (n > nLength)
n = nLength;
for (int i = 0; i < n; i++) {
int r = (*dst >> 10) & 0x1F;
int g = (*dst >> 5) & 0x1F;
int b = *dst & 0x1F;
2012-05-02 23:23:54 +00:00
2012-06-07 19:14:59 +00:00
r = (r >> 2) + (_alphaR >> 1);
g = (g >> 2) + (_alphaG >> 1);
b = (b >> 2) + (_alphaB >> 1);
2012-05-02 23:23:54 +00:00
2012-05-14 19:29:27 +00:00
*dst ++ = (r << 10) | (g << 5) | b;
2012-05-02 23:23:54 +00:00
}
nLength -= n;
if (!nLength)
return;
assert(nLength > 0);
//RLEByteDoCopy:
// Copy the stuff
2012-05-02 23:23:54 +00:00
n = *src++;
RLEByteDoCopy2:
if (n > nLength)
n = nLength;
2012-05-14 19:29:27 +00:00
for (int i = 0; i < n; i++)
2012-06-05 06:39:55 +00:00
*dst ++ = _palFinal[*src++];
2012-05-02 23:23:54 +00:00
nLength -= n;
if (!nLength)
return;
assert(nLength > 0);
}
}
void RMGfxSourceBuffer8RLEByte::rleDecompressLineFlipped(uint16 *dst, byte *src, int nStartSkip, int nLength) {
int n;
2012-05-02 23:23:54 +00:00
2012-05-14 19:29:27 +00:00
if (nStartSkip == 0)
goto RLEByteFlippedDoTrasp;
2012-05-02 23:23:54 +00:00
while (1) {
assert(nStartSkip > 0);
// TRASP
n = *src++;
if (n == 0xFF)
return;
2012-05-14 19:29:27 +00:00
2012-05-02 23:23:54 +00:00
if (n >= nStartSkip) {
dst -= n - nStartSkip;
nLength -= n - nStartSkip;
if (nLength > 0)
goto RLEByteFlippedDoAlpha;
else
return;
}
nStartSkip -= n;
assert(nStartSkip > 0);
2012-05-14 19:29:27 +00:00
2012-05-02 23:23:54 +00:00
// ALPHA
n = *src++;
if (n >= nStartSkip) {
n -= nStartSkip;
goto RLEByteFlippedDoAlpha2;
}
nStartSkip -= n;
assert(nStartSkip > 0);
// DATA
n = *src++;
2012-05-14 19:29:27 +00:00
if (n >= nStartSkip) {
2012-05-02 23:23:54 +00:00
src += nStartSkip;
n -= nStartSkip;
goto RLEByteFlippedDoCopy2;
}
nStartSkip -= n;
src += n;
}
while (1) {
RLEByteFlippedDoTrasp:
// Get the trasp of s**t
2012-05-02 23:23:54 +00:00
n = *src++;
2012-05-14 19:29:27 +00:00
2012-05-02 23:23:54 +00:00
// EOL?
if (n == 0xFF)
2012-05-14 19:29:27 +00:00
return;
2012-05-02 23:23:54 +00:00
dst -= n;
nLength -= n;
if (nLength <= 0)
return;
RLEByteFlippedDoAlpha:
// Alpha
n = *src++;
RLEByteFlippedDoAlpha2:
if (n > nLength)
n = nLength;
for (int i = 0; i < n; i++) {
int r = (*dst >> 10) & 0x1F;
int g = (*dst >> 5) & 0x1F;
int b = *dst & 0x1F;
2012-05-02 23:23:54 +00:00
2012-06-07 19:14:59 +00:00
r = (r >> 2) + (_alphaR >> 1);
g = (g >> 2) + (_alphaG >> 1);
b = (b >> 2) + (_alphaB >> 1);
2012-05-02 23:23:54 +00:00
2012-05-14 19:29:27 +00:00
*dst-- = (r << 10) | (g << 5) | b;
2012-05-02 23:23:54 +00:00
}
nLength -= n;
if (!nLength)
return;
assert(nLength > 0);
//RLEByteFlippedDoCopy:
// Copy the data
2012-05-02 23:23:54 +00:00
n = *src++;
RLEByteFlippedDoCopy2:
if (n > nLength)
n = nLength;
2012-05-14 19:29:27 +00:00
for (int i = 0; i < n; i++)
2012-06-05 06:39:55 +00:00
*dst-- = _palFinal[*src++];
2012-05-02 23:23:54 +00:00
nLength -= n;
if (!nLength)
return;
assert(nLength > 0);
}
}
/****************************************************************************\
* RMGfxSourceBuffer8RLEWord Methods
2012-05-02 23:23:54 +00:00
\****************************************************************************/
2012-05-14 19:29:27 +00:00
RMGfxSourceBuffer8RLEWord::~RMGfxSourceBuffer8RLEWord() {
2012-05-02 23:23:54 +00:00
}
void RMGfxSourceBuffer8RLEWord::rleWriteTrasp(byte *&cur, int rep) {
2012-05-02 23:23:54 +00:00
WRITE_LE_UINT16(cur, rep);
cur += 2;
}
void RMGfxSourceBuffer8RLEWord::rleWriteAlphaBlend(byte *&cur, int rep) {
2012-05-02 23:23:54 +00:00
WRITE_LE_UINT16(cur, rep);
cur += 2;
}
void RMGfxSourceBuffer8RLEWord::rleWriteData(byte *&cur, int rep, byte *src) {
2012-05-02 23:23:54 +00:00
WRITE_LE_UINT16(cur, rep);
cur += 2;
if (rep > 0) {
2012-08-25 08:06:10 +00:00
memcpy(cur, src, rep);
2012-05-02 23:23:54 +00:00
cur += rep;
2012-05-14 19:29:27 +00:00
src += rep;
2012-05-02 23:23:54 +00:00
}
}
void RMGfxSourceBuffer8RLEWord::rleWriteEOL(byte *&cur) {
2012-05-14 19:29:27 +00:00
*cur ++ = 0xFF;
*cur ++ = 0xFF;
2012-05-02 23:23:54 +00:00
}
void RMGfxSourceBuffer8RLEWord::rleDecompressLine(uint16 *dst, byte *src, int nStartSkip, int nLength) {
int n;
2012-05-02 23:23:54 +00:00
2012-05-14 19:29:27 +00:00
if (nStartSkip == 0)
goto RLEWordDoTrasp;
2012-05-02 23:23:54 +00:00
while (1) {
assert(nStartSkip > 0);
// TRASP
n = READ_LE_UINT16(src);
src += 2;
if (n == 0xFFFF)
return;
2012-05-14 19:29:27 +00:00
2012-05-02 23:23:54 +00:00
if (n >= nStartSkip) {
dst += n - nStartSkip;
nLength -= n - nStartSkip;
2012-05-14 19:29:27 +00:00
2012-05-02 23:23:54 +00:00
if (nLength > 0)
goto RLEWordDoAlpha;
else
return;
}
nStartSkip -= n;
assert(nStartSkip > 0);
// ALPHA
n = READ_LE_UINT16(src);
src += 2;
if (n >= nStartSkip) {
n -= nStartSkip;
goto RLEWordDoAlpha2;
}
nStartSkip -= n;
// DATA
n = READ_LE_UINT16(src);
src += 2;
2012-05-14 19:29:27 +00:00
2012-05-03 13:08:19 +00:00
if (n >= nStartSkip) {
2012-05-02 23:23:54 +00:00
src += nStartSkip;
n -= nStartSkip;
goto RLEWordDoCopy2;
}
nStartSkip -= n;
src += n;
}
2012-05-03 13:08:19 +00:00
while (1) {
2012-05-02 23:23:54 +00:00
RLEWordDoTrasp:
// Get the trasp of s**t
2012-05-02 23:23:54 +00:00
n = READ_LE_UINT16(src);
src += 2;
2012-05-14 19:29:27 +00:00
2012-05-02 23:23:54 +00:00
// EOL?
if (n == 0xFFFF)
2012-05-14 19:29:27 +00:00
return;
2012-05-02 23:23:54 +00:00
dst += n;
nLength -= n;
if (nLength <= 0)
return;
RLEWordDoAlpha:
n = READ_LE_UINT16(src);
src += 2;
RLEWordDoAlpha2:
if (n > nLength)
n = nLength;
for (int i = 0; i < n; i++) {
int r = (*dst >> 10) & 0x1F;
int g = (*dst >> 5) & 0x1F;
int b = *dst & 0x1F;
2012-05-02 23:23:54 +00:00
2012-06-07 19:14:59 +00:00
r = (r >> 2) + (_alphaR >> 1);
g = (g >> 2) + (_alphaG >> 1);
b = (b >> 2) + (_alphaB >> 1);
2012-05-02 23:23:54 +00:00
2012-05-14 19:29:27 +00:00
*dst++ = (r << 10) | (g << 5) | b;
2012-05-02 23:23:54 +00:00
}
nLength -= n;
if (!nLength)
return;
assert(nLength > 0);
//RLEWordDoCopy:
// Copy the data
2012-05-02 23:23:54 +00:00
n = READ_LE_UINT16(src);
src += 2;
2012-05-14 19:29:27 +00:00
2012-05-02 23:23:54 +00:00
RLEWordDoCopy2:
if (n > nLength)
n = nLength;
for (int i = 0; i < n; i++)
2012-06-05 06:39:55 +00:00
*dst++ = _palFinal[*src++];
2012-05-02 23:23:54 +00:00
nLength -= n;
if (!nLength)
return;
2012-05-14 19:29:27 +00:00
2012-05-02 23:23:54 +00:00
assert(nLength > 0);
}
}
void RMGfxSourceBuffer8RLEWord::rleDecompressLineFlipped(uint16 *dst, byte *src, int nStartSkip, int nLength) {
int n;
2012-05-02 23:23:54 +00:00
2012-05-14 19:29:27 +00:00
if (nStartSkip == 0)
goto RLEWordFlippedDoTrasp;
2012-05-02 23:23:54 +00:00
while (1) {
assert(nStartSkip > 0);
// TRASP
n = READ_LE_UINT16(src);
src += 2;
if (n == 0xFFFF)
return;
2012-05-14 19:29:27 +00:00
2012-05-03 13:08:19 +00:00
if (n >= nStartSkip) {
2012-05-02 23:23:54 +00:00
dst -= n - nStartSkip;
nLength -= n - nStartSkip;
2012-05-14 19:29:27 +00:00
2012-05-02 23:23:54 +00:00
if (nLength > 0)
goto RLEWordFlippedDoAlpha;
else
return;
}
nStartSkip -= n;
assert(nStartSkip > 0);
// ALPHA
n = READ_LE_UINT16(src);
src += 2;
2012-05-03 13:08:19 +00:00
if (n >= nStartSkip) {
2012-05-02 23:23:54 +00:00
n -= nStartSkip;
goto RLEWordFlippedDoAlpha2;
}
nStartSkip -= n;
// DATA
n = READ_LE_UINT16(src);
src += 2;
2012-05-14 19:29:27 +00:00
2012-05-02 23:23:54 +00:00
if (n >= nStartSkip) {
src += nStartSkip;
n -= nStartSkip;
goto RLEWordFlippedDoCopy2;
}
nStartSkip -= n;
src += n;
}
while (1) {
RLEWordFlippedDoTrasp:
// Get the trasp of s**t
2012-05-02 23:23:54 +00:00
n = READ_LE_UINT16(src);
src += 2;
2012-05-14 19:29:27 +00:00
2012-05-02 23:23:54 +00:00
// EOL?
if (n == 0xFFFF)
2012-05-14 19:29:27 +00:00
return;
2012-05-02 23:23:54 +00:00
dst -= n;
nLength -= n;
if (nLength <= 0)
return;
RLEWordFlippedDoAlpha:
n = READ_LE_UINT16(src);
src += 2;
RLEWordFlippedDoAlpha2:
if (n > nLength)
n = nLength;
for (int i = 0; i < n; i++) {
int r = (*dst >> 10) & 0x1F;
int g = (*dst >> 5) & 0x1F;
int b = *dst & 0x1F;
2012-05-02 23:23:54 +00:00
2012-06-07 19:14:59 +00:00
r = (r >> 2) + (_alphaR >> 1);
g = (g >> 2) + (_alphaG >> 1);
b = (b >> 2) + (_alphaB >> 1);
2012-05-02 23:23:54 +00:00
2012-05-14 19:29:27 +00:00
*dst-- = (r << 10) | (g << 5) | b;
2012-05-02 23:23:54 +00:00
}
nLength -= n;
if (!nLength)
return;
assert(nLength > 0);
//RLEWordFlippedDoCopy:
// Copy the data
2012-05-02 23:23:54 +00:00
n = READ_LE_UINT16(src);
src += 2;
2012-05-14 19:29:27 +00:00
2012-05-02 23:23:54 +00:00
RLEWordFlippedDoCopy2:
if (n > nLength)
n = nLength;
for (int i = 0; i < n; i++)
2012-06-05 06:39:55 +00:00
*dst-- = _palFinal[*src++];
2012-05-02 23:23:54 +00:00
nLength -= n;
if (!nLength)
return;
2012-05-14 19:29:27 +00:00
2012-05-02 23:23:54 +00:00
assert(nLength > 0);
}
}
/****************************************************************************\
* Methods for RMGfxSourceBuffer8RLEWord
2012-05-02 23:23:54 +00:00
\****************************************************************************/
RMGfxSourceBuffer8RLEWordAB::~RMGfxSourceBuffer8RLEWordAB() {
}
void RMGfxSourceBuffer8RLEWordAB::rleDecompressLine(uint16 *dst, byte *src, int nStartSkip, int nLength) {
int n;
2012-05-02 23:23:54 +00:00
2012-06-08 22:52:38 +00:00
if (!GLOBALS._bCfgTransparence) {
RMGfxSourceBuffer8RLEWord::rleDecompressLine(dst, src, nStartSkip, nLength);
2012-05-02 23:23:54 +00:00
return;
}
2012-05-14 19:29:27 +00:00
if (nStartSkip == 0)
goto RLEWordDoTrasp;
2012-05-02 23:23:54 +00:00
while (1) {
assert(nStartSkip > 0);
// TRASP
n = READ_LE_UINT16(src);
src += 2;
if (n == 0xFFFF)
return;
2012-05-14 19:29:27 +00:00
2012-05-02 23:23:54 +00:00
if (n >= nStartSkip) {
dst += n - nStartSkip;
nLength -= n - nStartSkip;
2012-05-14 19:29:27 +00:00
2012-05-02 23:23:54 +00:00
if (nLength > 0)
goto RLEWordDoAlpha;
else
return;
}
nStartSkip -= n;
assert(nStartSkip > 0);
// ALPHA
n = READ_LE_UINT16(src);
src += 2;
if (n >= nStartSkip) {
n -= nStartSkip;
goto RLEWordDoAlpha2;
}
nStartSkip -= n;
// DATA
n = READ_LE_UINT16(src);
src += 2;
2012-05-14 19:29:27 +00:00
2012-05-03 13:08:19 +00:00
if (n >= nStartSkip) {
2012-05-02 23:23:54 +00:00
src += nStartSkip;
n -= nStartSkip;
goto RLEWordDoCopy2;
}
nStartSkip -= n;
src += n;
}
while (1) {
RLEWordDoTrasp:
// Get the trasp of s**t
2012-05-02 23:23:54 +00:00
n = READ_LE_UINT16(src);
src += 2;
2012-05-14 19:29:27 +00:00
2012-05-02 23:23:54 +00:00
// EOL?
if (n == 0xFFFF)
2012-05-14 19:29:27 +00:00
return;
2012-05-02 23:23:54 +00:00
dst += n;
nLength -= n;
if (nLength <= 0)
return;
RLEWordDoAlpha:
n = READ_LE_UINT16(src);
src += 2;
RLEWordDoAlpha2:
if (n > nLength)
n = nLength;
// @@@ SHOULD NOT BE THERE !!!!!
for (int i = 0; i < n; i++) {
int r = (*dst >> 10) & 0x1F;
int g = (*dst >> 5) & 0x1F;
int b = *dst & 0x1F;
2012-05-02 23:23:54 +00:00
2012-06-07 19:14:59 +00:00
r = (r >> 2) + (_alphaR >> 1);
g = (g >> 2) + (_alphaG >> 1);
b = (b >> 2) + (_alphaB >> 1);
2012-05-02 23:23:54 +00:00
2012-05-14 19:29:27 +00:00
*dst++ = (r << 10) | (g << 5) | b;
2012-05-02 23:23:54 +00:00
}
nLength -= n;
if (!nLength)
return;
assert(nLength > 0);
//RLEWordDoCopy:
// Copy the data
2012-05-02 23:23:54 +00:00
n = READ_LE_UINT16(src);
src += 2;
2012-05-14 19:29:27 +00:00
2012-05-02 23:23:54 +00:00
RLEWordDoCopy2:
if (n > nLength)
n = nLength;
for (int i = 0; i < n; i++) {
int r = (*dst >> 10) & 0x1F;
int g = (*dst >> 5) & 0x1F;
int b = *dst & 0x1F;
2012-05-02 23:23:54 +00:00
int r2 = (_palFinal[*src] >> 10) & 0x1F;
int g2 = (_palFinal[*src] >> 5) & 0x1F;
int b2 = _palFinal[*src] & 0x1F;
2012-05-02 23:23:54 +00:00
2012-05-03 13:08:19 +00:00
r = (r >> 1) + (r2 >> 1);
g = (g >> 1) + (g2 >> 1);
b = (b >> 1) + (b2 >> 1);
2012-05-02 23:23:54 +00:00
2012-05-14 19:29:27 +00:00
*dst ++ = (r << 10) | (g << 5) | b;
2012-05-02 23:23:54 +00:00
src++;
}
nLength -= n;
if (!nLength)
return;
2012-05-14 19:29:27 +00:00
2012-05-02 23:23:54 +00:00
assert(nLength > 0);
}
}
/****************************************************************************\
* Methods for RMGfxSourceBuffer8AA
2012-05-02 23:23:54 +00:00
\****************************************************************************/
2012-06-07 19:14:59 +00:00
byte RMGfxSourceBuffer8AA::_megaAABuf[256 * 1024];
byte RMGfxSourceBuffer8AA::_megaAABuf2[64 * 1024];
2012-05-02 23:23:54 +00:00
void RMGfxSourceBuffer8AA::prepareImage() {
// Invoke the parent method
2012-06-05 06:39:55 +00:00
RMGfxSourceBuffer::prepareImage();
2012-05-14 19:29:27 +00:00
// Prepare the buffer for anti-aliasing
2012-06-05 06:39:55 +00:00
calculateAA();
2012-05-02 23:23:54 +00:00
}
void RMGfxSourceBuffer8AA::calculateAA() {
2012-05-02 23:23:54 +00:00
byte *src, *srcaa;
// First pass: fill the edges
2012-06-07 19:14:59 +00:00
Common::fill(_megaAABuf, _megaAABuf + _dimx * _dimy, 0);
2012-05-14 19:29:27 +00:00
2012-06-05 06:39:55 +00:00
src = _buf;
2012-06-07 19:14:59 +00:00
srcaa = _megaAABuf;
for (int y = 0; y < _dimy; y++) {
for (int x = 0; x < _dimx; x++) {
2012-05-02 23:23:54 +00:00
if (*src == 0) {
2012-06-05 06:39:55 +00:00
if ((y > 0 && src[-_dimx] != 0) ||
(y < _dimy - 1 && src[_dimx] != 0) ||
(x > 0 && src[-1] != 0) ||
(x < _dimx - 1 && src[1] != 0))
2012-05-02 23:23:54 +00:00
*srcaa = 1;
}
src++;
srcaa++;
2012-05-14 19:29:27 +00:00
}
2012-05-02 23:23:54 +00:00
}
2012-06-05 06:39:55 +00:00
src = _buf;
2012-06-07 19:14:59 +00:00
srcaa = _megaAABuf;
for (int y = 0; y < _dimy; y++) {
for (int x = 0; x < _dimx; x++) {
2012-05-02 23:23:54 +00:00
if (*src != 0) {
2012-06-05 06:39:55 +00:00
if ((y > 0 && srcaa[-_dimx] == 1) ||
(y < _dimy - 1 && srcaa[_dimx] == 1) ||
(x > 0 && srcaa[-1] == 1) ||
(x < _dimx - 1 && srcaa[1] == 1))
2012-05-02 23:23:54 +00:00
*srcaa = 2;
}
src++;
srcaa++;
2012-05-14 19:29:27 +00:00
}
2012-05-02 23:23:54 +00:00
}
2012-06-05 06:39:55 +00:00
if (_aabuf != NULL)
delete[] _aabuf;
2012-05-02 23:23:54 +00:00
2012-06-05 06:39:55 +00:00
_aabuf = new byte[_dimx * _dimy];
2012-08-25 08:06:10 +00:00
memcpy(_aabuf, _megaAABuf, _dimx * _dimy);
2012-05-02 23:23:54 +00:00
}
RMGfxSourceBuffer8AA::RMGfxSourceBuffer8AA() : RMGfxSourceBuffer8() {
2012-06-05 06:39:55 +00:00
_aabuf = NULL;
2012-05-02 23:23:54 +00:00
}
RMGfxSourceBuffer8AA::~RMGfxSourceBuffer8AA() {
2012-06-05 06:39:55 +00:00
if (_aabuf != NULL)
delete[] _aabuf;
2012-05-02 23:23:54 +00:00
}
2012-06-05 06:39:55 +00:00
void RMGfxSourceBuffer8AA::drawAA(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
2012-05-02 23:23:54 +00:00
byte *src;
uint16 *mybuf;
uint16 *buf;
int u, v, width, height;
2012-05-14 19:29:27 +00:00
// Clip the sprite
int x1 = prim->getDst()._x1;
int y1 = prim->getDst()._y1;
2012-06-05 06:39:55 +00:00
if (!clip2D(x1, y1, u, v, width, height, false, &bigBuf))
2012-05-02 23:23:54 +00:00
return;
// Go forward through the RLE lines
2012-06-05 06:39:55 +00:00
src = _buf;
for (int y = 0; y < v; y++)
2012-05-02 23:23:54 +00:00
src += READ_LE_UINT16(src);
// Eliminate horizontal clipping
2012-06-05 06:39:55 +00:00
if (prim->isFlipped()) {
u = _dimx - (width + u);
2012-06-11 18:24:25 +00:00
x1 = (prim->getDst()._x1 + _dimx - 1) - u;
if (width > x1)
width = x1;
// Specify the drawn area
bigBuf.addDirtyRect(Common::Rect(x1 - width, y1, x1 + 1, y1 + height));
} else {
// Specify the drawn area
bigBuf.addDirtyRect(Common::Rect(x1, y1, x1 + width, y1 + height));
2012-05-02 23:23:54 +00:00
}
//width = _dimx;
//x1 = prim->Dst().x1;
2012-05-14 19:29:27 +00:00
// Position into the destination buffer
2012-05-02 23:23:54 +00:00
buf = bigBuf;
2012-06-05 06:39:55 +00:00
buf += y1 * bigBuf.getDimx();
2012-05-02 23:23:54 +00:00
int step;
2012-06-05 06:39:55 +00:00
if (prim->isFlipped())
2012-05-02 23:23:54 +00:00
step = -1;
else
step = 1;
// Loop
2012-06-05 06:39:55 +00:00
buf += bigBuf.getDimx(); // Skip the first line
for (int y = 1; y < height - 1; y++) {
// if (prim->IsFlipped())
// mybuf=&buf[x1+m_dimx-1];
// else
2012-05-14 19:29:27 +00:00
mybuf = &buf[x1];
2012-05-02 23:23:54 +00:00
for (int x = 0; x < width; x++, mybuf += step) {
2012-06-05 06:39:55 +00:00
if (_aabuf[(y + v) * _dimx + x + u] == 2 && x != 0 && x != width - 1) {
int r = GETRED(mybuf[1]) + GETRED(mybuf[-1]) + GETRED(mybuf[-bigBuf.getDimx()]) + GETRED(mybuf[bigBuf.getDimx()]);
int g = GETGREEN(mybuf[1]) + GETGREEN(mybuf[-1]) + GETGREEN(mybuf[-bigBuf.getDimx()]) + GETGREEN(mybuf[bigBuf.getDimx()]);
int b = GETBLUE(mybuf[1]) + GETBLUE(mybuf[-1]) + GETBLUE(mybuf[-bigBuf.getDimx()]) + GETBLUE(mybuf[bigBuf.getDimx()]);
2012-05-02 23:23:54 +00:00
r += GETRED(mybuf[0]);
g += GETGREEN(mybuf[0]);
b += GETBLUE(mybuf[0]);
2012-05-14 19:29:27 +00:00
2012-05-02 23:23:54 +00:00
r /= 5;
g /= 5;
b /= 5;
if (r > 31)
r = 31;
if (g > 31)
g = 31;
if (b > 31)
b = 31;
2012-05-02 23:23:54 +00:00
2012-05-14 19:29:27 +00:00
mybuf[0] = (r << 10) | (g << 5) | b;
2012-05-02 23:23:54 +00:00
}
}
2012-05-14 19:29:27 +00:00
// Skip to the next line
2012-06-05 06:39:55 +00:00
buf += bigBuf.getDimx();
2012-05-02 23:23:54 +00:00
}
// Position into the destination buffer
2012-05-02 23:23:54 +00:00
buf = bigBuf;
2012-06-05 06:39:55 +00:00
buf += y1 * bigBuf.getDimx();
2012-05-02 23:23:54 +00:00
// Looppone
2012-06-05 06:39:55 +00:00
buf += bigBuf.getDimx();
for (int y = 1; y < height - 1; y++) {
// if (prim->IsFlipped())
// mybuf=&buf[x1+m_dimx-1];
// else
2012-05-14 19:29:27 +00:00
mybuf = &buf[x1];
2012-05-02 23:23:54 +00:00
for (int x = 0; x < width; x++, mybuf += step) {
2012-06-05 06:39:55 +00:00
if (_aabuf[(y + v) * _dimx + x + u] == 1 && x != 0 && x != width - 1) {
int r = GETRED(mybuf[1]) + GETRED(mybuf[-1]) + GETRED(mybuf[-bigBuf.getDimx()]) + GETRED(mybuf[bigBuf.getDimx()]);
int g = GETGREEN(mybuf[1]) + GETGREEN(mybuf[-1]) + GETGREEN(mybuf[-bigBuf.getDimx()]) + GETGREEN(mybuf[bigBuf.getDimx()]);
int b = GETBLUE(mybuf[1]) + GETBLUE(mybuf[-1]) + GETBLUE(mybuf[-bigBuf.getDimx()]) + GETBLUE(mybuf[bigBuf.getDimx()]);
2012-05-02 23:23:54 +00:00
r += GETRED(mybuf[0]) * 2;
g += GETGREEN(mybuf[0]) * 2;
b += GETBLUE(mybuf[0]) * 2;
2012-05-14 19:29:27 +00:00
2012-05-02 23:23:54 +00:00
r /= 6;
g /= 6;
b /= 6;
if (r > 31)
r = 31;
if (g > 31)
g = 31;
if (b > 31)
b = 31;
2012-05-02 23:23:54 +00:00
2012-05-14 19:29:27 +00:00
mybuf[0] = (r << 10) | (g << 5) | b;
2012-05-02 23:23:54 +00:00
}
}
2012-05-14 19:29:27 +00:00
// Skip to the next line
2012-06-05 06:39:55 +00:00
buf += bigBuf.getDimx();
2012-05-02 23:23:54 +00:00
}
}
2012-06-05 06:39:55 +00:00
void RMGfxSourceBuffer8AA::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
2012-06-05 06:39:55 +00:00
CORO_INVOKE_2(RMGfxSourceBuffer8::draw, bigBuf, prim);
drawAA(bigBuf, prim);
CORO_END_CODE;
2012-05-02 23:23:54 +00:00
}
/****************************************************************************\
* RMGfxSourceBuffer8RLEAA Methods
2012-05-02 23:23:54 +00:00
\****************************************************************************/
RMGfxSourceBuffer8RLEByteAA::~RMGfxSourceBuffer8RLEByteAA() {
}
void RMGfxSourceBuffer8RLEByteAA::prepareImage() {
2012-06-05 06:39:55 +00:00
RMGfxSourceBuffer::prepareImage();
calculateAA();
compressRLE();
2012-05-02 23:23:54 +00:00
}
2012-06-05 06:39:55 +00:00
void RMGfxSourceBuffer8RLEByteAA::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
2012-06-05 06:39:55 +00:00
CORO_INVOKE_2(RMGfxSourceBuffer8RLE::draw, bigBuf, prim);
2012-06-08 22:52:38 +00:00
if (GLOBALS._bCfgAntiAlias)
2012-06-05 06:39:55 +00:00
drawAA(bigBuf, prim);
CORO_END_CODE;
2012-05-02 23:23:54 +00:00
}
2012-06-05 06:39:55 +00:00
int RMGfxSourceBuffer8RLEByteAA::init(const byte *buf, int dimx, int dimy, bool bLoadPalette) {
return RMGfxSourceBuffer8RLE::init(buf, dimx, dimy, bLoadPalette);
2012-05-02 23:23:54 +00:00
}
2012-08-28 12:26:00 +00:00
void RMGfxSourceBuffer8RLEByteAA::init(Common::ReadStream &ds, int dimx, int dimy, bool bLoadPalette) {
2012-06-05 06:39:55 +00:00
RMGfxSourceBuffer8RLE::init(ds, dimx, dimy, bLoadPalette);
2012-05-02 23:23:54 +00:00
2012-06-07 19:14:59 +00:00
if (!_bNeedRLECompress) {
// Load the anti-aliasing mask
2012-06-05 06:39:55 +00:00
_aabuf = new byte[dimx * dimy];
ds.read(_aabuf, dimx * dimy);
2012-05-02 23:23:54 +00:00
}
}
RMGfxSourceBuffer8RLEWordAA::~RMGfxSourceBuffer8RLEWordAA() {
}
void RMGfxSourceBuffer8RLEWordAA::prepareImage() {
2012-06-05 06:39:55 +00:00
RMGfxSourceBuffer::prepareImage();
calculateAA();
compressRLE();
2012-05-02 23:23:54 +00:00
}
2012-06-05 06:39:55 +00:00
void RMGfxSourceBuffer8RLEWordAA::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
2012-06-05 06:39:55 +00:00
CORO_INVOKE_2(RMGfxSourceBuffer8RLE::draw, bigBuf, prim);
2012-06-08 22:52:38 +00:00
if (GLOBALS._bCfgAntiAlias)
2012-06-05 06:39:55 +00:00
drawAA(bigBuf, prim);
CORO_END_CODE;
2012-05-02 23:23:54 +00:00
}
2012-06-05 06:39:55 +00:00
int RMGfxSourceBuffer8RLEWordAA::init(byte *buf, int dimx, int dimy, bool bLoadPalette) {
return RMGfxSourceBuffer8RLE::init(buf, dimx, dimy, bLoadPalette);
2012-05-02 23:23:54 +00:00
}
2012-08-28 12:26:00 +00:00
void RMGfxSourceBuffer8RLEWordAA::init(Common::ReadStream &ds, int dimx, int dimy, bool bLoadPalette) {
2012-06-05 06:39:55 +00:00
RMGfxSourceBuffer8RLE::init(ds, dimx, dimy, bLoadPalette);
2012-05-02 23:23:54 +00:00
2012-06-07 19:14:59 +00:00
if (!_bNeedRLECompress) {
// Load the anti-aliasing mask
2012-06-05 06:39:55 +00:00
_aabuf = new byte[dimx * dimy];
ds.read(_aabuf, dimx * dimy);
2012-05-02 23:23:54 +00:00
}
}
/****************************************************************************\
* RMGfxSourceBuffer16 Methods
2012-05-02 23:23:54 +00:00
\****************************************************************************/
RMGfxSourceBuffer16::RMGfxSourceBuffer16(bool bTrasp0) {
2012-06-05 06:39:55 +00:00
_bTrasp0 = bTrasp0;
2012-05-02 23:23:54 +00:00
}
RMGfxSourceBuffer16::~RMGfxSourceBuffer16() {
}
2012-06-05 06:39:55 +00:00
void RMGfxSourceBuffer16::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
2012-05-02 23:23:54 +00:00
uint16 *buf = bigBuf;
2012-06-05 06:39:55 +00:00
uint16 *raw = (uint16 *)_buf;
2012-05-02 23:23:54 +00:00
int dimx = _dimx;
int dimy = _dimy;
int u = 0;
int v = 0;
int x1 = 0;
int y1 = 0;
2012-05-02 23:23:54 +00:00
2012-06-05 06:39:55 +00:00
if (prim->haveSrc()) {
2012-06-11 18:24:25 +00:00
u = prim->getSrc()._x1;
v = prim->getSrc()._y1;
2012-06-07 19:14:59 +00:00
dimx = prim->getSrc().width();
dimy = prim->getSrc().height();
2012-05-02 23:23:54 +00:00
}
2012-06-05 06:39:55 +00:00
if (prim->haveDst()) {
2012-06-11 18:24:25 +00:00
x1 = prim->getDst()._x1;
y1 = prim->getDst()._y1;
2012-05-02 23:23:54 +00:00
}
2012-06-05 06:39:55 +00:00
if (!clip2D(x1, y1, u, v, dimx, dimy, true, &bigBuf))
2012-05-02 23:23:54 +00:00
return;
2012-06-05 06:39:55 +00:00
raw += v * _dimx + u;
buf += y1 * bigBuf.getDimx() + x1;
2012-05-02 23:23:54 +00:00
2012-06-05 06:39:55 +00:00
if (_bTrasp0) {
2012-06-13 22:11:56 +00:00
for (int y = 0; y < dimy; y++) {
for (int x = 0; x < dimx;) {
2012-05-14 19:29:27 +00:00
while (x < dimx && raw[x] == 0)
2012-05-02 23:23:54 +00:00
x++;
2012-05-14 19:29:27 +00:00
while (x < dimx && raw[x] != 0) {
2012-05-02 23:23:54 +00:00
buf[x] = raw[x];
x++;
}
}
2012-06-05 06:39:55 +00:00
raw += _dimx;
buf += bigBuf.getDimx();
2012-05-02 23:23:54 +00:00
}
} else {
2012-06-13 22:11:56 +00:00
for (int y = 0; y < dimy; y++) {
Common::copy(raw, raw + dimx, buf);
2012-06-05 06:39:55 +00:00
buf += bigBuf.getDimx();
raw += _dimx;
2012-05-02 23:23:54 +00:00
}
}
// Specify the drawn area
bigBuf.addDirtyRect(Common::Rect(x1, y1, x1 + dimx, y1 + dimy));
2012-05-02 23:23:54 +00:00
}
void RMGfxSourceBuffer16::prepareImage() {
// Color space conversion if necessary!
2012-06-05 06:39:55 +00:00
uint16 *buf = (uint16 *)_buf;
2012-05-02 23:23:54 +00:00
for (int i = 0; i < _dimx * _dimy; i++)
buf[i] = FROM_LE_16(buf[i]) & 0x7FFF;
2012-05-02 23:23:54 +00:00
}
RMGfxSourceBuffer16::RMGfxSourceBuffer16(int dimx, int dimy)
: RMGfxBuffer(dimx, dimy, 16) {
2012-06-05 06:39:55 +00:00
setPriority(0);
_bTrasp0 = false;
2012-05-03 03:14:46 +00:00
}
/**
* Returns the number of bits per pixel of the surface
*
2012-05-21 21:53:13 +00:00
* @returns Bit per pixel
*/
2012-06-07 19:14:59 +00:00
int RMGfxSourceBuffer16::getBpp() {
2012-05-03 03:14:46 +00:00
return 16;
}
void RMGfxSourceBuffer16::create(int dimx, int dimy) {
RMGfxBuffer::create(dimx, dimy, 16);
2012-05-03 03:14:46 +00:00
}
2012-05-02 23:23:54 +00:00
/****************************************************************************\
* RMGfxBox Methods
2012-05-02 23:23:54 +00:00
\****************************************************************************/
2012-06-05 06:39:55 +00:00
void RMGfxBox::removeThis(CORO_PARAM, bool &result) {
result = true;
2012-05-02 23:23:54 +00:00
}
2012-06-07 19:14:59 +00:00
void RMGfxBox::setColor(byte r, byte g, byte b) {
2012-05-02 23:23:54 +00:00
r >>= 3;
g >>= 3;
b >>= 3;
2012-06-07 19:14:59 +00:00
_wFillColor = (r << 10) | (g << 5) | b;
2012-05-02 23:23:54 +00:00
}
2012-06-05 06:39:55 +00:00
void RMGfxBox::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
2012-05-02 23:23:54 +00:00
uint16 *buf = bigBuf;
RMRect rcDst;
2012-05-14 19:29:27 +00:00
// It takes the destination rectangle
2012-06-07 19:14:59 +00:00
rcDst = prim->getDst();
2012-06-11 18:24:25 +00:00
buf += rcDst._y1 * bigBuf.getDimx() + rcDst._x1;
2012-05-02 23:23:54 +00:00
// Loop through the pixels
for (int j = 0; j < rcDst.height(); j++) {
for (int i = 0; i < rcDst.width(); i++)
2012-06-07 19:14:59 +00:00
*buf++ = _wFillColor;
2012-05-02 23:23:54 +00:00
buf += bigBuf.getDimx() - rcDst.width();
2012-05-02 23:23:54 +00:00
}
// Specify the drawn area
bigBuf.addDirtyRect(rcDst);
2012-05-02 23:23:54 +00:00
}
2012-05-03 03:14:46 +00:00
/****************************************************************************\
* RMGfxClearTask Methods
2012-05-03 03:14:46 +00:00
\****************************************************************************/
2012-06-05 16:51:20 +00:00
int RMGfxClearTask::priority() {
// Maximum priority (must be done first)
2012-05-03 03:14:46 +00:00
return 1;
}
2012-06-05 06:39:55 +00:00
void RMGfxClearTask::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *) {
// Clean the target buffer
2012-06-05 06:39:55 +00:00
Common::fill((byte *)bigBuf, (byte *)bigBuf + (bigBuf.getDimx() * bigBuf.getDimy() * 2), 0x0);
bigBuf.addDirtyRect(Common::Rect(bigBuf.getDimx(), bigBuf.getDimy()));
2012-05-03 03:14:46 +00:00
}
2012-06-05 06:39:55 +00:00
void RMGfxClearTask::removeThis(CORO_PARAM, bool &result) {
// The task is fine to be removed
result = true;
2012-05-03 03:14:46 +00:00
}
/****************************************************************************\
* RMGfxPrimitive Methods
\****************************************************************************/
RMGfxPrimitive::RMGfxPrimitive() {
_bFlag = 0;
_task = NULL;
_src.setEmpty();
_dst.setEmpty();
_bStretch = false;
}
RMGfxPrimitive::RMGfxPrimitive(RMGfxTask *task) {
_task = task;
_bFlag = 0;
_bStretch = false;
}
RMGfxPrimitive::RMGfxPrimitive(RMGfxTask *task, const RMRect &src, RMRect &dst) {
_task = task;
_src = src;
_dst = dst;
_bFlag = 0;
_bStretch = (src.width() != dst.width() || src.height() != dst.height());
}
RMGfxPrimitive::RMGfxPrimitive(RMGfxTask *task, const RMPoint &src, RMRect &dst) {
_task = task;
_src.topLeft() = src;
_dst = dst;
_bFlag = 0;
_bStretch = false;
}
RMGfxPrimitive::RMGfxPrimitive(RMGfxTask *task, const RMPoint &src, RMPoint &dst) {
_task = task;
_src.topLeft() = src;
_dst.topLeft() = dst;
_bFlag = 0;
_bStretch = false;
}
RMGfxPrimitive::RMGfxPrimitive(RMGfxTask *task, const RMRect &src, RMPoint &dst) {
_task = task;
_src = src;
_dst.topLeft() = dst;
_bFlag = 0;
_bStretch = false;
}
RMGfxPrimitive::RMGfxPrimitive(RMGfxTask *task, const RMRect &dst) {
_task = task;
_dst = dst;
_src.setEmpty();
_bFlag = 0;
_bStretch = false;
}
RMGfxPrimitive::RMGfxPrimitive(RMGfxTask *task, const RMPoint &dst) {
_task = task;
_dst.topLeft() = dst;
_src.setEmpty();
_bFlag = 0;
_bStretch = false;
}
RMGfxPrimitive::~RMGfxPrimitive() {
}
void RMGfxPrimitive::setFlag(byte bFlag) {
_bFlag = bFlag;
}
void RMGfxPrimitive::setTask(RMGfxTask *task) {
_task = task;
}
void RMGfxPrimitive::setSrc(const RMRect &src) {
_src = src;
}
void RMGfxPrimitive::setSrc(const RMPoint &src) {
_src.topLeft() = src;
}
void RMGfxPrimitive::setDst(const RMRect &dst) {
_dst = dst;
}
void RMGfxPrimitive::setDst(const RMPoint &dst) {
_dst.topLeft() = dst;
}
void RMGfxPrimitive::setStretch(bool bStretch) {
_bStretch = bStretch;
}
bool RMGfxPrimitive::haveDst() {
return !_dst.isEmpty();
}
RMRect &RMGfxPrimitive::getDst() {
return _dst;
}
bool RMGfxPrimitive::haveSrc() {
return !_src.isEmpty();
}
RMRect &RMGfxPrimitive::getSrc() {
return _src;
}
/**
* Flags
*/
bool RMGfxPrimitive::isFlipped() {
return _bFlag & 1;
}
/**
* Duplicate
*/
RMGfxPrimitive *RMGfxPrimitive::duplicate() {
return new RMGfxPrimitive(*this);
}
} // End of namespace Tony