2017-01-13 12:17:36 +11:00
|
|
|
/* 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.
|
|
|
|
*/
|
|
|
|
|
2017-02-07 20:08:49 +01:00
|
|
|
#include "common/system.h"
|
|
|
|
#include "graphics/macgui/macwindowmanager.h"
|
|
|
|
|
2017-01-13 12:17:36 +11:00
|
|
|
#include "director/director.h"
|
|
|
|
|
|
|
|
namespace Director {
|
|
|
|
|
2020-08-21 00:17:28 +02:00
|
|
|
#include "director/graphics-data.h"
|
2020-03-21 14:19:56 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The sprites colors are in reverse order with respect to the ids in director.
|
2020-03-28 13:09:11 +01:00
|
|
|
* The palette is in reverse order, this eases the code for loading files.
|
2020-03-21 14:19:56 +01:00
|
|
|
* All other color ids can be converted with: 255 - colorId.
|
2020-03-28 13:09:11 +01:00
|
|
|
**/
|
2020-03-21 14:45:08 +01:00
|
|
|
uint32 DirectorEngine::transformColor(uint32 color) {
|
2020-08-15 12:18:35 +02:00
|
|
|
if (_pixelformat.bytesPerPixel == 1)
|
|
|
|
return 255 - color;
|
|
|
|
|
|
|
|
color = 255 - color;
|
|
|
|
|
|
|
|
return _wm->findBestColor(_currentPalette[color * 3], _currentPalette[color * 3 + 1], _currentPalette[color * 3 + 2]);
|
2020-03-21 14:19:56 +01:00
|
|
|
}
|
|
|
|
|
2017-01-13 12:17:36 +11:00
|
|
|
void DirectorEngine::loadPatterns() {
|
|
|
|
for (int i = 0; i < ARRAYSIZE(director3Patterns); i++)
|
|
|
|
_director3Patterns.push_back(director3Patterns[i]);
|
|
|
|
|
|
|
|
for (int i = 0; i < ARRAYSIZE(director3QuickDrawPatterns); i++)
|
|
|
|
_director3QuickDrawPatterns.push_back(director3QuickDrawPatterns[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
Graphics::MacPatterns &DirectorEngine::getPatterns() {
|
2017-03-02 23:12:42 +01:00
|
|
|
// TOOD: implement switch and other version patterns. (use getVersion());
|
2017-01-13 12:17:36 +11:00
|
|
|
return _director3QuickDrawPatterns;
|
|
|
|
}
|
|
|
|
|
2020-07-26 21:26:28 -04:00
|
|
|
void DirectorEngine::loadDefaultPalettes() {
|
|
|
|
_loadedPalettes[kClutSystemMac] = PaletteV4(kClutSystemMac, macPalette, 256);
|
|
|
|
_loadedPalettes[kClutRainbow] = PaletteV4(kClutRainbow, rainbowPalette, 256);
|
|
|
|
_loadedPalettes[kClutGrayscale] = PaletteV4(kClutGrayscale, grayscalePalette, 256);
|
|
|
|
_loadedPalettes[kClutPastels] = PaletteV4(kClutPastels, pastelsPalette, 256);
|
|
|
|
_loadedPalettes[kClutVivid] = PaletteV4(kClutVivid, vividPalette, 256);
|
|
|
|
_loadedPalettes[kClutNTSC] = PaletteV4(kClutNTSC, ntscPalette, 256);
|
|
|
|
_loadedPalettes[kClutMetallic] = PaletteV4(kClutMetallic, metallicPalette, 256);
|
|
|
|
_loadedPalettes[kClutSystemWin] = PaletteV4(kClutSystemWin, winPalette, 256);
|
|
|
|
}
|
|
|
|
|
2020-07-27 09:25:38 -04:00
|
|
|
PaletteV4 *DirectorEngine::getPalette(int id) {
|
|
|
|
if (!_loadedPalettes.contains(id)) {
|
|
|
|
warning("DirectorEngine::addPalette(): Palette %d not found", id);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return &_loadedPalettes[id];
|
|
|
|
}
|
|
|
|
|
2020-07-26 21:26:28 -04:00
|
|
|
void DirectorEngine::addPalette(int id, byte *palette, int length) {
|
|
|
|
if (id < 0) {
|
|
|
|
warning("DirectorEngine::addPalette(): Negative palette ids reserved for default palettes");
|
|
|
|
return;
|
|
|
|
} else if (_loadedPalettes.contains(id)) {
|
2020-08-03 09:43:33 -04:00
|
|
|
delete[] _loadedPalettes[id].palette;
|
2020-01-11 23:30:40 +08:00
|
|
|
}
|
2020-07-26 21:26:28 -04:00
|
|
|
|
|
|
|
_loadedPalettes[id] = PaletteV4(id, palette, length);
|
2020-01-11 23:30:40 +08:00
|
|
|
}
|
|
|
|
|
2020-07-26 21:26:28 -04:00
|
|
|
bool DirectorEngine::setPalette(int id) {
|
2020-07-27 09:25:38 -04:00
|
|
|
if (id == 0) {
|
|
|
|
// Palette id of 0 is unused
|
|
|
|
return false;
|
|
|
|
} else if (!_loadedPalettes.contains(id)) {
|
2020-01-11 23:30:40 +08:00
|
|
|
warning("setPalette(): no palette with matching id %d", id);
|
2020-07-26 21:26:28 -04:00
|
|
|
return false;
|
2020-01-11 23:30:40 +08:00
|
|
|
}
|
2020-07-26 21:26:28 -04:00
|
|
|
|
|
|
|
PaletteV4 pal = _loadedPalettes[id];
|
|
|
|
setPalette(pal.palette, pal.length);
|
|
|
|
|
|
|
|
return true;
|
2020-01-11 23:30:40 +08:00
|
|
|
}
|
|
|
|
|
2017-02-07 20:08:49 +01:00
|
|
|
void DirectorEngine::setPalette(byte *palette, uint16 count) {
|
2020-08-14 10:28:27 +02:00
|
|
|
// Pass the palette to OSystem only for 8bpp mode
|
|
|
|
if (_pixelformat.bytesPerPixel == 1)
|
|
|
|
_system->getPaletteManager()->setPalette(palette, 0, count);
|
|
|
|
|
2017-02-07 20:08:49 +01:00
|
|
|
_currentPalette = palette;
|
|
|
|
_currentPaletteLength = count;
|
2019-12-11 11:49:45 +01:00
|
|
|
|
|
|
|
_wm->passPalette(palette, count);
|
2017-02-07 20:08:49 +01:00
|
|
|
}
|
|
|
|
|
2020-07-26 21:26:28 -04:00
|
|
|
void DirectorEngine::clearPalettes() {
|
|
|
|
for (Common::HashMap<int, PaletteV4>::iterator it = _loadedPalettes.begin(); it != _loadedPalettes.end(); ++it) {
|
|
|
|
if (it->_value.id > 0)
|
|
|
|
delete[] it->_value.palette;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-06 01:00:53 -04:00
|
|
|
void DirectorEngine::setCursor(DirectorCursor type) {
|
2020-03-27 02:01:06 +01:00
|
|
|
switch (type) {
|
|
|
|
case kCursorMouseDown:
|
2021-08-06 01:00:53 -04:00
|
|
|
_wm->replaceCustomCursor(mouseDown, 16, 16, 0, 0, 3);
|
2020-03-27 02:01:06 +01:00
|
|
|
break;
|
|
|
|
case kCursorMouseUp:
|
2021-08-06 01:00:53 -04:00
|
|
|
_wm->replaceCustomCursor(mouseUp, 16, 16, 0, 0, 3);
|
2020-03-27 02:01:06 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-11 12:30:58 +08:00
|
|
|
void DirectorEngine::draw() {
|
|
|
|
_wm->renderZoomBox(true);
|
|
|
|
_wm->draw();
|
2020-07-21 17:31:36 -04:00
|
|
|
g_system->updateScreen();
|
2020-07-11 12:30:58 +08:00
|
|
|
}
|
|
|
|
|
2020-08-16 00:11:51 +02:00
|
|
|
template <typename T>
|
2020-07-09 15:33:03 -04:00
|
|
|
void inkDrawPixel(int x, int y, int src, void *data) {
|
2020-06-29 18:16:48 -04:00
|
|
|
DirectorPlotData *p = (DirectorPlotData *)data;
|
|
|
|
|
|
|
|
if (!p->destRect.contains(x, y))
|
|
|
|
return;
|
|
|
|
|
2020-08-16 00:11:51 +02:00
|
|
|
T dst;
|
|
|
|
uint32 tmpDst;
|
2020-06-29 18:16:48 -04:00
|
|
|
|
2020-08-16 00:11:51 +02:00
|
|
|
dst = (T)p->dst->getBasePtr(x, y);
|
2020-06-29 18:16:48 -04:00
|
|
|
|
2020-07-09 15:33:03 -04:00
|
|
|
if (p->ms) {
|
2020-06-29 18:16:48 -04:00
|
|
|
// Get the pixel that macDrawPixel will give us, but store it to apply the
|
2021-06-30 19:07:57 +08:00
|
|
|
// ink later
|
2020-06-29 18:16:48 -04:00
|
|
|
tmpDst = *dst;
|
2020-08-15 16:08:32 +02:00
|
|
|
(p->_wm->getDrawPixel())(x, y, src, p->ms->pd);
|
2020-07-06 12:36:39 -04:00
|
|
|
src = *dst;
|
2020-06-29 18:16:48 -04:00
|
|
|
|
|
|
|
*dst = tmpDst;
|
2020-07-29 00:11:28 -04:00
|
|
|
} else if (p->alpha) {
|
|
|
|
// Sprite blend does not respect colourization; defaults to matte ink
|
|
|
|
byte rSrc, gSrc, bSrc;
|
|
|
|
byte rDst, gDst, bDst;
|
|
|
|
|
|
|
|
g_director->_wm->decomposeColor(src, rSrc, gSrc, bSrc);
|
|
|
|
g_director->_wm->decomposeColor(*dst, rDst, gDst, bDst);
|
|
|
|
|
|
|
|
double alpha = (double)p->alpha / 100.0;
|
|
|
|
rDst = static_cast<byte>((rSrc * alpha) + (rDst * (1.0 - alpha)));
|
|
|
|
gDst = static_cast<byte>((gSrc * alpha) + (gDst * (1.0 - alpha)));
|
|
|
|
bDst = static_cast<byte>((bSrc * alpha) + (bDst * (1.0 - alpha)));
|
|
|
|
|
|
|
|
*dst = p->_wm->findBestColor(rDst, gDst, bDst);
|
|
|
|
return;
|
2020-06-29 18:16:48 -04:00
|
|
|
}
|
|
|
|
|
2020-07-09 09:29:57 -04:00
|
|
|
switch (p->ink) {
|
2020-06-29 18:16:48 -04:00
|
|
|
case kInkTypeBackgndTrans:
|
2020-08-23 01:23:28 +02:00
|
|
|
if ((uint32)src == p->backColor)
|
2020-06-29 18:16:48 -04:00
|
|
|
break;
|
|
|
|
// fall through
|
2020-07-03 13:15:39 -04:00
|
|
|
case kInkTypeMatte:
|
|
|
|
case kInkTypeMask:
|
|
|
|
// Only unmasked pixels make it here, so copy them straight
|
2020-07-08 09:20:15 -04:00
|
|
|
case kInkTypeCopy: {
|
|
|
|
if (p->applyColor) {
|
|
|
|
// TODO: Improve the efficiency of this composition
|
|
|
|
byte rSrc, gSrc, bSrc;
|
|
|
|
byte rDst, gDst, bDst;
|
|
|
|
byte rFor, gFor, bFor;
|
|
|
|
byte rBak, gBak, bBak;
|
|
|
|
|
|
|
|
g_director->_wm->decomposeColor(src, rSrc, gSrc, bSrc);
|
|
|
|
g_director->_wm->decomposeColor(*dst, rDst, gDst, bDst);
|
|
|
|
g_director->_wm->decomposeColor(p->foreColor, rFor, gFor, bFor);
|
|
|
|
g_director->_wm->decomposeColor(p->backColor, rBak, gBak, bBak);
|
|
|
|
|
|
|
|
*dst = p->_wm->findBestColor((rSrc | rFor) & (~rSrc | rBak),
|
|
|
|
(gSrc | gFor) & (~gSrc | gBak),
|
|
|
|
(bSrc | bFor) & (~bSrc | bBak));
|
|
|
|
} else {
|
|
|
|
*dst = src;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case kInkTypeNotCopy:
|
|
|
|
if (p->applyColor) {
|
|
|
|
// TODO: Improve the efficiency of this composition
|
|
|
|
byte rSrc, gSrc, bSrc;
|
|
|
|
byte rDst, gDst, bDst;
|
|
|
|
byte rFor, gFor, bFor;
|
|
|
|
byte rBak, gBak, bBak;
|
|
|
|
|
|
|
|
g_director->_wm->decomposeColor(src, rSrc, gSrc, bSrc);
|
|
|
|
g_director->_wm->decomposeColor(*dst, rDst, gDst, bDst);
|
|
|
|
g_director->_wm->decomposeColor(p->foreColor, rFor, gFor, bFor);
|
|
|
|
g_director->_wm->decomposeColor(p->backColor, rBak, gBak, bBak);
|
|
|
|
|
|
|
|
*dst = p->_wm->findBestColor((~rSrc | rFor) & (rSrc | rBak),
|
|
|
|
(~gSrc | gFor) & (gSrc | gBak),
|
|
|
|
(~bSrc | bFor) & (bSrc | bBak));
|
|
|
|
} else {
|
|
|
|
*dst = src;
|
|
|
|
}
|
2020-06-29 18:16:48 -04:00
|
|
|
break;
|
|
|
|
case kInkTypeTransparent:
|
2020-07-08 09:20:15 -04:00
|
|
|
*dst = p->applyColor ? (~src & p->foreColor) | (*dst & src) : (*dst & src);
|
|
|
|
break;
|
|
|
|
case kInkTypeNotTrans:
|
|
|
|
*dst = p->applyColor ? (src & p->foreColor) | (*dst & ~src) : (*dst & ~src);
|
2020-06-29 18:16:48 -04:00
|
|
|
break;
|
|
|
|
case kInkTypeReverse:
|
2021-08-17 09:25:35 +08:00
|
|
|
*dst ^= ~(src);
|
2020-06-29 18:16:48 -04:00
|
|
|
break;
|
|
|
|
case kInkTypeNotReverse:
|
2020-07-08 09:20:15 -04:00
|
|
|
*dst ^= src;
|
|
|
|
break;
|
|
|
|
case kInkTypeGhost:
|
|
|
|
*dst = p->applyColor ? (src | p->backColor) & (*dst | ~src) : (*dst | ~src);
|
2020-06-29 18:16:48 -04:00
|
|
|
break;
|
|
|
|
case kInkTypeNotGhost:
|
2020-07-08 09:20:15 -04:00
|
|
|
*dst = p->applyColor ? (~src | p->backColor) & (*dst | src) : *dst | src;
|
2020-06-29 18:16:48 -04:00
|
|
|
break;
|
|
|
|
// Arithmetic ink types
|
2020-07-03 16:51:04 -04:00
|
|
|
default: {
|
2020-08-21 00:20:38 +02:00
|
|
|
byte rSrc, gSrc, bSrc;
|
|
|
|
byte rDst, gDst, bDst;
|
|
|
|
|
|
|
|
g_director->_wm->decomposeColor(src, rSrc, gSrc, bSrc);
|
|
|
|
g_director->_wm->decomposeColor(*dst, rDst, gDst, bDst);
|
2020-07-06 13:03:58 -04:00
|
|
|
|
2020-08-21 00:20:38 +02:00
|
|
|
switch (p->ink) {
|
|
|
|
case kInkTypeBlend:
|
|
|
|
*dst = p->_wm->findBestColor((rSrc + rDst) / 2, (gSrc + gDst) / 2, (bSrc + bDst) / 2);
|
|
|
|
break;
|
|
|
|
case kInkTypeAddPin:
|
|
|
|
*dst = p->_wm->findBestColor(MIN((rSrc + rDst), 0xff), MIN((gSrc + gDst), 0xff), MIN((bSrc + bDst), 0xff));
|
|
|
|
break;
|
|
|
|
case kInkTypeAdd:
|
2021-08-17 09:48:08 +08:00
|
|
|
// in basilisk, D3.1 is exactly using this method, adding color directly without preventing the overflow.
|
|
|
|
// but i think min(src + dst, 255) will give us a better visual effect
|
|
|
|
*dst = p->_wm->findBestColor(rSrc + rDst, gSrc + gDst, bSrc + bDst);
|
2020-08-21 00:20:38 +02:00
|
|
|
break;
|
|
|
|
case kInkTypeSubPin:
|
|
|
|
*dst = p->_wm->findBestColor(MAX(rSrc - rDst, 0), MAX(gSrc - gDst, 0), MAX(bSrc - bDst, 0));
|
|
|
|
break;
|
|
|
|
case kInkTypeLight:
|
|
|
|
*dst = p->_wm->findBestColor(MAX(rSrc, rDst), MAX(gSrc, gDst), MAX(bSrc, bDst));
|
|
|
|
break;
|
|
|
|
case kInkTypeSub:
|
|
|
|
*dst = p->_wm->findBestColor(abs(rSrc - rDst) % 0xff + 1, abs(gSrc - gDst) % 0xff + 1, abs(bSrc - bDst) % 0xff + 1);
|
|
|
|
break;
|
|
|
|
case kInkTypeDark:
|
|
|
|
*dst = p->_wm->findBestColor(MIN(rSrc, rDst), MIN(gSrc, gDst), MIN(bSrc, bDst));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2020-07-03 16:51:04 -04:00
|
|
|
}
|
|
|
|
}
|
2020-06-29 18:16:48 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-16 00:11:51 +02:00
|
|
|
Graphics::MacDrawPixPtr DirectorEngine::getInkDrawPixel() {
|
|
|
|
if (_pixelformat.bytesPerPixel == 1)
|
|
|
|
return &inkDrawPixel<byte *>;
|
|
|
|
else
|
|
|
|
return &inkDrawPixel<uint32 *>;
|
|
|
|
}
|
|
|
|
|
2020-07-09 15:33:03 -04:00
|
|
|
void DirectorPlotData::setApplyColor() {
|
|
|
|
applyColor = false;
|
2020-07-09 11:08:15 -04:00
|
|
|
|
2020-07-09 13:38:25 -04:00
|
|
|
if (foreColor != colorBlack) {
|
2020-07-09 11:08:15 -04:00
|
|
|
if (ink != kInkTypeGhost && ink != kInkTypeNotGhost)
|
2020-07-09 15:33:03 -04:00
|
|
|
applyColor = true;
|
2020-07-09 11:08:15 -04:00
|
|
|
}
|
|
|
|
|
2020-07-09 13:38:25 -04:00
|
|
|
if (backColor != colorWhite) {
|
2021-08-25 11:19:45 +02:00
|
|
|
if (ink != kInkTypeTransparent && ink != kInkTypeNotTrans && ink != kInkTypeBackgndTrans)
|
2020-07-09 15:33:03 -04:00
|
|
|
applyColor = true;
|
2020-07-09 11:08:15 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-09 09:41:27 +08:00
|
|
|
uint32 DirectorPlotData::preprocessColor(uint32 src) {
|
|
|
|
// HACK: Right now this method is just used for adjusting the colourization on text
|
|
|
|
// sprites, as it would be costly to colourize the chunks on the fly each
|
|
|
|
// time a section needs drawing. It's ugly but mostly works.
|
|
|
|
if (sprite == kTextSprite) {
|
|
|
|
switch(ink) {
|
|
|
|
case kInkTypeMask:
|
|
|
|
src = (src == backColor ? foreColor : 0xff);
|
|
|
|
break;
|
|
|
|
case kInkTypeReverse:
|
|
|
|
src = (src == foreColor ? 0 : colorWhite);
|
|
|
|
break;
|
|
|
|
case kInkTypeNotReverse:
|
|
|
|
src = (src == backColor ? colorWhite : 0);
|
|
|
|
break;
|
|
|
|
// looks like this part is wrong, maybe it's very same as reverse?
|
|
|
|
// check warlock/DATA/WARLOCKSHIP/ENG/ABOUT to see more detail.
|
|
|
|
// case kInkTypeGhost:
|
|
|
|
// src = (src == foreColor ? backColor : colorWhite);
|
|
|
|
// break;
|
|
|
|
case kInkTypeNotGhost:
|
|
|
|
src = (src == backColor ? colorWhite : backColor);
|
|
|
|
break;
|
|
|
|
case kInkTypeNotCopy:
|
|
|
|
src = (src == foreColor ? backColor : foreColor);
|
|
|
|
break;
|
|
|
|
case kInkTypeNotTrans:
|
|
|
|
src = (src == foreColor ? backColor : colorWhite);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return src;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DirectorPlotData::inkBlitShape(Common::Rect &srcRect) {
|
|
|
|
if (!ms)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Preprocess shape colours
|
|
|
|
switch (ink) {
|
|
|
|
case kInkTypeNotTrans:
|
|
|
|
case kInkTypeNotReverse:
|
|
|
|
case kInkTypeNotGhost:
|
|
|
|
return;
|
|
|
|
case kInkTypeReverse:
|
|
|
|
ms->foreColor = 0;
|
|
|
|
ms->backColor = 0;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
Common::Rect fillAreaRect((int)srcRect.width(), (int)srcRect.height());
|
|
|
|
fillAreaRect.moveTo(srcRect.left, srcRect.top);
|
|
|
|
Graphics::MacPlotData plotFill(dst, nullptr, &g_director->getPatterns(), ms->pattern, srcRect.left, srcRect.top, 1, ms->backColor);
|
|
|
|
|
|
|
|
Common::Rect strokeRect(MAX((int)srcRect.width() - ms->lineSize, 0), MAX((int)srcRect.height() - ms->lineSize, 0));
|
|
|
|
strokeRect.moveTo(srcRect.left, srcRect.top);
|
|
|
|
Graphics::MacPlotData plotStroke(dst, nullptr, &g_director->getPatterns(), 1, strokeRect.left, strokeRect.top, ms->lineSize, ms->backColor);
|
|
|
|
|
|
|
|
switch (ms->spriteType) {
|
|
|
|
case kRectangleSprite:
|
|
|
|
ms->pd = &plotFill;
|
|
|
|
Graphics::drawFilledRect(fillAreaRect, ms->foreColor, g_director->getInkDrawPixel(), this);
|
|
|
|
// fall through
|
|
|
|
case kOutlinedRectangleSprite:
|
|
|
|
// if we have lineSize <= 0, means we are not drawing anything. so we may return directly.
|
|
|
|
if (ms->lineSize <= 0)
|
|
|
|
break;
|
|
|
|
ms->pd = &plotStroke;
|
|
|
|
Graphics::drawRect(strokeRect, ms->foreColor, g_director->getInkDrawPixel(), this);
|
|
|
|
break;
|
|
|
|
case kRoundedRectangleSprite:
|
|
|
|
ms->pd = &plotFill;
|
|
|
|
Graphics::drawRoundRect(fillAreaRect, 12, ms->foreColor, true, g_director->getInkDrawPixel(), this);
|
|
|
|
// fall through
|
|
|
|
case kOutlinedRoundedRectangleSprite:
|
|
|
|
if (ms->lineSize <= 0)
|
|
|
|
break;
|
|
|
|
ms->pd = &plotStroke;
|
|
|
|
Graphics::drawRoundRect(strokeRect, 12, ms->foreColor, false, g_director->getInkDrawPixel(), this);
|
|
|
|
break;
|
|
|
|
case kOvalSprite:
|
|
|
|
ms->pd = &plotFill;
|
|
|
|
Graphics::drawEllipse(fillAreaRect.left, fillAreaRect.top, fillAreaRect.right, fillAreaRect.bottom, ms->foreColor, true, g_director->getInkDrawPixel(), this);
|
|
|
|
// fall through
|
|
|
|
case kOutlinedOvalSprite:
|
|
|
|
if (ms->lineSize <= 0)
|
|
|
|
break;
|
|
|
|
ms->pd = &plotStroke;
|
|
|
|
Graphics::drawEllipse(strokeRect.left, strokeRect.top, strokeRect.right, strokeRect.bottom, ms->foreColor, false, g_director->getInkDrawPixel(), this);
|
|
|
|
break;
|
|
|
|
case kLineTopBottomSprite:
|
|
|
|
ms->pd = &plotStroke;
|
|
|
|
Graphics::drawLine(strokeRect.left, strokeRect.top, strokeRect.right, strokeRect.bottom, ms->foreColor, g_director->getInkDrawPixel(), this);
|
|
|
|
break;
|
|
|
|
case kLineBottomTopSprite:
|
|
|
|
ms->pd = &plotStroke;
|
|
|
|
Graphics::drawLine(strokeRect.left, strokeRect.bottom, strokeRect.right, strokeRect.top, ms->foreColor, g_director->getInkDrawPixel(), this);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
warning("DirectorPlotData::inkBlitShape: Expected shape type but got type %d", ms->spriteType);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DirectorPlotData::inkBlitSurface(Common::Rect &srcRect, const Graphics::Surface *mask) {
|
|
|
|
if (!srf)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// TODO: Determine why colourization causes problems in Warlock
|
|
|
|
if (sprite == kTextSprite)
|
|
|
|
applyColor = false;
|
|
|
|
|
|
|
|
srcPoint.y = abs(srcRect.top - destRect.top);
|
|
|
|
for (int i = 0; i < destRect.height(); i++, srcPoint.y++) {
|
|
|
|
if (_wm->_pixelformat.bytesPerPixel == 1) {
|
|
|
|
srcPoint.x = abs(srcRect.left - destRect.left);
|
|
|
|
const byte *msk = mask ? (const byte *)mask->getBasePtr(srcPoint.x, srcPoint.y) : nullptr;
|
|
|
|
|
|
|
|
for (int j = 0; j < destRect.width(); j++, srcPoint.x++) {
|
|
|
|
if (!mask || (msk && !(*msk++))) {
|
|
|
|
(g_director->getInkDrawPixel())(destRect.left + j, destRect.top + i,
|
|
|
|
preprocessColor(*((byte *)srf->getBasePtr(srcPoint.x, srcPoint.y))), this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
srcPoint.x = abs(srcRect.left - destRect.left);
|
|
|
|
const uint32 *msk = mask ? (const uint32 *)mask->getBasePtr(srcPoint.x, srcPoint.y) : nullptr;
|
|
|
|
|
|
|
|
for (int j = 0; j < destRect.width(); j++, srcPoint.x++) {
|
|
|
|
if (!mask || (msk && !(*msk++))) {
|
|
|
|
(g_director->getInkDrawPixel())(destRect.left + j, destRect.top + i,
|
|
|
|
preprocessColor(*((int *)srf->getBasePtr(srcPoint.x, srcPoint.y))), this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DirectorPlotData::inkBlitStretchSurface(Common::Rect &srcRect, const Graphics::Surface *mask) {
|
|
|
|
if (!srf)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// TODO: Determine why colourization causes problems in Warlock
|
|
|
|
if (sprite == kTextSprite)
|
|
|
|
applyColor = false;
|
|
|
|
|
|
|
|
int scaleX = SCALE_THRESHOLD * srcRect.width() / destRect.width();
|
|
|
|
int scaleY = SCALE_THRESHOLD * srcRect.height() / destRect.height();
|
|
|
|
|
|
|
|
srcPoint.y = abs(srcRect.top - destRect.top);
|
|
|
|
|
|
|
|
for (int i = 0, scaleYCtr = 0; i < destRect.height(); i++, scaleYCtr += scaleY, srcPoint.y++) {
|
|
|
|
if (_wm->_pixelformat.bytesPerPixel == 1) {
|
|
|
|
srcPoint.x = abs(srcRect.left - destRect.left);
|
|
|
|
const byte *msk = mask ? (const byte *)mask->getBasePtr(srcPoint.x, srcPoint.y) : nullptr;
|
|
|
|
|
|
|
|
for (int xCtr = 0, scaleXCtr = 0; xCtr < destRect.width(); xCtr++, scaleXCtr += scaleX, srcPoint.x++) {
|
|
|
|
if (!mask || !(*msk++)) {
|
|
|
|
(g_director->getInkDrawPixel())(destRect.left + xCtr, destRect.top + i,
|
|
|
|
preprocessColor(*((byte *)srf->getBasePtr(scaleXCtr / SCALE_THRESHOLD, scaleYCtr / SCALE_THRESHOLD))), this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
srcPoint.x = abs(srcRect.left - destRect.left);
|
|
|
|
const uint32 *msk = mask ? (const uint32 *)mask->getBasePtr(srcPoint.x, srcPoint.y) : nullptr;
|
|
|
|
|
|
|
|
for (int xCtr = 0, scaleXCtr = 0; xCtr < destRect.width(); xCtr++, scaleXCtr += scaleX, srcPoint.x++) {
|
|
|
|
if (!mask || !(*msk++)) {
|
|
|
|
(g_director->getInkDrawPixel())(destRect.left + xCtr, destRect.top + i,
|
|
|
|
preprocessColor(*((int *)srf->getBasePtr(scaleXCtr / SCALE_THRESHOLD, scaleYCtr / SCALE_THRESHOLD))), this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-21 00:35:36 +02:00
|
|
|
} // End of namespace Director
|