scummvm/graphics/scalerplugin.cpp
2021-04-15 21:20:36 +02:00

139 lines
4.2 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 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.
*/
#include "graphics/scalerplugin.h"
void ScalerPluginObject::initialize(const Graphics::PixelFormat &format) {
_format = format;
}
namespace {
/**
* Trivial 'scaler' - in fact it doesn't do any scaling but just copies the
* source to the destination.
*/
template<typename Pixel>
void Normal1x(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch,
int width, int height) {
// Spot the case when it can all be done in 1 hit
int BytesPerPixel = sizeof(Pixel);
if ((srcPitch == BytesPerPixel * (uint)width) && (dstPitch == BytesPerPixel * (uint)width)) {
memcpy(dstPtr, srcPtr, BytesPerPixel * width * height);
return;
}
while (height--) {
memcpy(dstPtr, srcPtr, BytesPerPixel * width);
srcPtr += srcPitch;
dstPtr += dstPitch;
}
}
} // End of anonymous namespace
void ScalerPluginObject::scale(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr,
uint32 dstPitch, int width, int height, int x, int y) {
if (_factor == 1) {
if (_format.bytesPerPixel == 2) {
Normal1x<uint16>(srcPtr, srcPitch, dstPtr, dstPitch, width, height);
} else {
Normal1x<uint32>(srcPtr, srcPitch, dstPtr, dstPitch, width, height);
}
} else {
scaleIntern(srcPtr, srcPitch, dstPtr, dstPitch, width, height, x, y);
}
}
SourceScaler::SourceScaler() : _width(0), _height(0), _oldSrc(NULL), _enable(false) {
}
SourceScaler::~SourceScaler() {
if (_oldSrc != NULL)
delete[] _oldSrc;
}
void SourceScaler::deinitialize() {
_bufferedOutput.free();
ScalerPluginObject::deinitialize();
}
void SourceScaler::setSource(const byte *src, uint pitch, int width, int height, int padding) {
if (_oldSrc != NULL)
delete[] _oldSrc;
_width = width;
_height = height;
_padding = padding;
// Give _oldSrc same pitch
int size = (height + padding * 2) * pitch;
_oldSrc = new byte[size];
memset(_oldSrc, 0, size);
_bufferedOutput.create(_width * _factor, _height * _factor, _format);
}
uint SourceScaler::setFactor(uint factor) {
uint oldFactor = _factor;
_factor = factor;
if (factor != oldFactor && _width != 0 && _height != 0) {
_bufferedOutput.create(_width * _factor, _height * _factor, _format);
}
return oldFactor;
}
void SourceScaler::scaleIntern(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr,
uint32 dstPitch, int width, int height, int x, int y) {
if (!_enable) {
// Do not pass _oldSrc, do not update _oldSrc
internScale(srcPtr, srcPitch,
dstPtr, dstPitch,
NULL, 0,
width, height,
NULL, 0);
return;
}
int offset = (_padding + x) * _format.bytesPerPixel + (_padding + y) * srcPitch;
// Call user defined scale function
internScale(srcPtr, srcPitch,
dstPtr, dstPitch,
_oldSrc + offset, srcPitch,
width, height,
(uint8 *)_bufferedOutput.getBasePtr(x * _factor, y * _factor), _bufferedOutput.pitch);
// Update the destination buffer
byte *buffer = (byte *)_bufferedOutput.getBasePtr(x * _factor, y * _factor);
for (uint i = 0; i < height * _factor; ++i) {
memcpy(buffer, dstPtr, width * _factor * _format.bytesPerPixel);
buffer += _bufferedOutput.pitch;
dstPtr += dstPitch;
}
// Update old src
byte *oldSrc = _oldSrc + offset;
while (height--) {
memcpy(oldSrc, srcPtr, width * _format.bytesPerPixel);
oldSrc += srcPitch;
srcPtr += srcPitch;
}
}