DIRECTOR: Move methods from Window to DirectorPlotData

This commit is contained in:
Scott Percival 2021-10-09 09:41:27 +08:00
parent e4f767c916
commit 8963cf211a
4 changed files with 191 additions and 190 deletions

View File

@ -126,6 +126,8 @@ struct MacShape {
Graphics::MacPlotData *pd;
};
const int SCALE_THRESHOLD = 0x100;
// An extension of MacPlotData for interfacing with inks and patterns without
// needing extra surfaces.
struct DirectorPlotData {
@ -148,7 +150,12 @@ struct DirectorPlotData {
uint32 foreColor;
bool applyColor;
void setApplyColor(); // graphics.cpp
// graphics.cpp
void setApplyColor();
uint32 preprocessColor(uint32 src);
void inkBlitShape(Common::Rect &srcRect);
void inkBlitSurface(Common::Rect &srcRect, const Graphics::Surface *mask);
void inkBlitStretchSurface(Common::Rect &srcRect, const Graphics::Surface *mask);
DirectorPlotData(Graphics::MacWindowManager *w, SpriteType s, InkType i, int a, uint32 b, uint32 f) : _wm(w), sprite(s), ink(i), alpha(a), backColor(b), foreColor(f) {
srf = nullptr;

View File

@ -300,4 +300,184 @@ void DirectorPlotData::setApplyColor() {
}
}
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);
}
}
}
}
}
} // End of namespace Director

View File

@ -198,13 +198,13 @@ void Window::inkBlitFrom(Channel *channel, Common::Rect destRect, Graphics::Mana
pd.dst = blitTo;
if (pd.ms) {
inkBlitShape(&pd, srcRect);
pd.inkBlitShape(srcRect);
} else if (pd.srf) {
if (channel->isStretched()) {
srcRect = channel->getBbox(true);
inkBlitStretchSurface(&pd, srcRect, channel->getMask());
pd.inkBlitStretchSurface(srcRect, channel->getMask());
} else {
inkBlitSurface(&pd, srcRect, channel->getMask());
pd.inkBlitSurface(srcRect, channel->getMask());
}
} else {
if (debugChannelSet(kDebugImages, 2))
@ -212,186 +212,6 @@ void Window::inkBlitFrom(Channel *channel, Common::Rect destRect, Graphics::Mana
}
}
void Window::inkBlitShape(DirectorPlotData *pd, Common::Rect &srcRect) {
if (!pd->ms)
return;
// Preprocess shape colours
switch (pd->ink) {
case kInkTypeNotTrans:
case kInkTypeNotReverse:
case kInkTypeNotGhost:
return;
case kInkTypeReverse:
pd->ms->foreColor = 0;
pd->ms->backColor = 0;
break;
default:
break;
}
Common::Rect fillAreaRect((int)srcRect.width(), (int)srcRect.height());
fillAreaRect.moveTo(srcRect.left, srcRect.top);
Graphics::MacPlotData plotFill(pd->dst, nullptr, &g_director->getPatterns(), pd->ms->pattern, srcRect.left, srcRect.top, 1, pd->ms->backColor);
Common::Rect strokeRect(MAX((int)srcRect.width() - pd->ms->lineSize, 0), MAX((int)srcRect.height() - pd->ms->lineSize, 0));
strokeRect.moveTo(srcRect.left, srcRect.top);
Graphics::MacPlotData plotStroke(pd->dst, nullptr, &g_director->getPatterns(), 1, strokeRect.left, strokeRect.top, pd->ms->lineSize, pd->ms->backColor);
switch (pd->ms->spriteType) {
case kRectangleSprite:
pd->ms->pd = &plotFill;
Graphics::drawFilledRect(fillAreaRect, pd->ms->foreColor, g_director->getInkDrawPixel(), pd);
// fall through
case kOutlinedRectangleSprite:
// if we have lineSize <= 0, means we are not drawing anything. so we may return directly.
if (pd->ms->lineSize <= 0)
break;
pd->ms->pd = &plotStroke;
Graphics::drawRect(strokeRect, pd->ms->foreColor, g_director->getInkDrawPixel(), pd);
break;
case kRoundedRectangleSprite:
pd->ms->pd = &plotFill;
Graphics::drawRoundRect(fillAreaRect, 12, pd->ms->foreColor, true, g_director->getInkDrawPixel(), pd);
// fall through
case kOutlinedRoundedRectangleSprite:
if (pd->ms->lineSize <= 0)
break;
pd->ms->pd = &plotStroke;
Graphics::drawRoundRect(strokeRect, 12, pd->ms->foreColor, false, g_director->getInkDrawPixel(), pd);
break;
case kOvalSprite:
pd->ms->pd = &plotFill;
Graphics::drawEllipse(fillAreaRect.left, fillAreaRect.top, fillAreaRect.right, fillAreaRect.bottom, pd->ms->foreColor, true, g_director->getInkDrawPixel(), pd);
// fall through
case kOutlinedOvalSprite:
if (pd->ms->lineSize <= 0)
break;
pd->ms->pd = &plotStroke;
Graphics::drawEllipse(strokeRect.left, strokeRect.top, strokeRect.right, strokeRect.bottom, pd->ms->foreColor, false, g_director->getInkDrawPixel(), pd);
break;
case kLineTopBottomSprite:
pd->ms->pd = &plotStroke;
Graphics::drawLine(strokeRect.left, strokeRect.top, strokeRect.right, strokeRect.bottom, pd->ms->foreColor, g_director->getInkDrawPixel(), pd);
break;
case kLineBottomTopSprite:
pd->ms->pd = &plotStroke;
Graphics::drawLine(strokeRect.left, strokeRect.bottom, strokeRect.right, strokeRect.top, pd->ms->foreColor, g_director->getInkDrawPixel(), pd);
break;
default:
warning("Window::inkBlitFrom: Expected shape type but got type %d", pd->ms->spriteType);
}
}
void Window::inkBlitSurface(DirectorPlotData *pd, Common::Rect &srcRect, const Graphics::Surface *mask) {
if (!pd->srf)
return;
// TODO: Determine why colourization causes problems in Warlock
if (pd->sprite == kTextSprite)
pd->applyColor = false;
pd->srcPoint.y = abs(srcRect.top - pd->destRect.top);
for (int i = 0; i < pd->destRect.height(); i++, pd->srcPoint.y++) {
if (_wm->_pixelformat.bytesPerPixel == 1) {
pd->srcPoint.x = abs(srcRect.left - pd->destRect.left);
const byte *msk = mask ? (const byte *)mask->getBasePtr(pd->srcPoint.x, pd->srcPoint.y) : nullptr;
for (int j = 0; j < pd->destRect.width(); j++, pd->srcPoint.x++) {
if (!mask || (msk && !(*msk++))) {
(g_director->getInkDrawPixel())(pd->destRect.left + j, pd->destRect.top + i,
preprocessColor(pd, *((byte *)pd->srf->getBasePtr(pd->srcPoint.x, pd->srcPoint.y))), pd);
}
}
} else {
pd->srcPoint.x = abs(srcRect.left - pd->destRect.left);
const uint32 *msk = mask ? (const uint32 *)mask->getBasePtr(pd->srcPoint.x, pd->srcPoint.y) : nullptr;
for (int j = 0; j < pd->destRect.width(); j++, pd->srcPoint.x++) {
if (!mask || (msk && !(*msk++))) {
(g_director->getInkDrawPixel())(pd->destRect.left + j, pd->destRect.top + i,
preprocessColor(pd, *((int *)pd->srf->getBasePtr(pd->srcPoint.x, pd->srcPoint.y))), pd);
}
}
}
}
}
void Window::inkBlitStretchSurface(DirectorPlotData *pd, Common::Rect &srcRect, const Graphics::Surface *mask) {
if (!pd->srf)
return;
// TODO: Determine why colourization causes problems in Warlock
if (pd->sprite == kTextSprite)
pd->applyColor = false;
int scaleX = SCALE_THRESHOLD * srcRect.width() / pd->destRect.width();
int scaleY = SCALE_THRESHOLD * srcRect.height() / pd->destRect.height();
pd->srcPoint.y = abs(srcRect.top - pd->destRect.top);
for (int i = 0, scaleYCtr = 0; i < pd->destRect.height(); i++, scaleYCtr += scaleY, pd->srcPoint.y++) {
if (_wm->_pixelformat.bytesPerPixel == 1) {
pd->srcPoint.x = abs(srcRect.left - pd->destRect.left);
const byte *msk = mask ? (const byte *)mask->getBasePtr(pd->srcPoint.x, pd->srcPoint.y) : nullptr;
for (int xCtr = 0, scaleXCtr = 0; xCtr < pd->destRect.width(); xCtr++, scaleXCtr += scaleX, pd->srcPoint.x++) {
if (!mask || !(*msk++)) {
(g_director->getInkDrawPixel())(pd->destRect.left + xCtr, pd->destRect.top + i,
preprocessColor(pd, *((byte *)pd->srf->getBasePtr(scaleXCtr / SCALE_THRESHOLD, scaleYCtr / SCALE_THRESHOLD))), pd);
}
}
} else {
pd->srcPoint.x = abs(srcRect.left - pd->destRect.left);
const uint32 *msk = mask ? (const uint32 *)mask->getBasePtr(pd->srcPoint.x, pd->srcPoint.y) : nullptr;
for (int xCtr = 0, scaleXCtr = 0; xCtr < pd->destRect.width(); xCtr++, scaleXCtr += scaleX, pd->srcPoint.x++) {
if (!mask || !(*msk++)) {
(g_director->getInkDrawPixel())(pd->destRect.left + xCtr, pd->destRect.top + i,
preprocessColor(pd, *((int *)pd->srf->getBasePtr(scaleXCtr / SCALE_THRESHOLD, scaleYCtr / SCALE_THRESHOLD))), pd);
}
}
}
}
}
int Window::preprocessColor(DirectorPlotData *p, 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 (p->sprite == kTextSprite) {
switch(p->ink) {
case kInkTypeMask:
src = (src == p->backColor ? p->foreColor : 0xff);
break;
case kInkTypeReverse:
src = (src == p->foreColor ? 0 : p->colorWhite);
break;
case kInkTypeNotReverse:
src = (src == p->backColor ? p->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 == p->foreColor ? p->backColor : p->colorWhite);
// break;
case kInkTypeNotGhost:
src = (src == p->backColor ? p->colorWhite : p->backColor);
break;
case kInkTypeNotCopy:
src = (src == p->foreColor ? p->backColor : p->foreColor);
break;
case kInkTypeNotTrans:
src = (src == p->foreColor ? p->backColor : p->colorWhite);
break;
default:
break;
}
}
return src;
}
Common::Point Window::getMousePos() {
return g_system->getEventManager()->getMousePos() - Common::Point(_innerDims.left, _innerDims.top);
}

View File

@ -38,8 +38,6 @@ class MacWindowManager;
namespace Director {
const int SCALE_THRESHOLD = 0x100;
class Channel;
class MacArchive;
struct MacShape;
@ -201,13 +199,9 @@ private:
bool _titleVisible;
private:
int preprocessColor(DirectorPlotData *p, uint32 src);
void inkBlitFrom(Channel *channel, Common::Rect destRect, Graphics::ManagedSurface *blitTo = nullptr);
void inkBlitShape(DirectorPlotData *pd, Common::Rect &srcRect);
void inkBlitSurface(DirectorPlotData *pd, Common::Rect &srcRect, const Graphics::Surface *mask);
void inkBlitStretchSurface(DirectorPlotData *pd, Common::Rect &srcRect, const Graphics::Surface *mask);
};
} // End of namespace Director