scummvm/graphics/VectorRenderer.cpp
2019-12-08 17:06:42 +01:00

183 lines
5.4 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 "common/textconsole.h"
#include "common/util.h"
#include "graphics/VectorRenderer.h"
#define VECTOR_RENDERER_FAST_TRIANGLES
namespace Graphics {
/********************************************************************
* DRAWSTEP handling functions
********************************************************************/
void VectorRenderer::drawStep(const Common::Rect &area, const Common::Rect &clip, const DrawStep &step, uint32 extra) {
if (step.bgColor.set)
setBgColor(step.bgColor.r, step.bgColor.g, step.bgColor.b);
if (step.fgColor.set)
setFgColor(step.fgColor.r, step.fgColor.g, step.fgColor.b);
if (step.bevelColor.set)
setBevelColor(step.bevelColor.r, step.bevelColor.g, step.bevelColor.b);
if (step.gradColor1.set && step.gradColor2.set)
setGradientColors(step.gradColor1.r, step.gradColor1.g, step.gradColor1.b,
step.gradColor2.r, step.gradColor2.g, step.gradColor2.b);
setShadowOffset(_disableShadows ? 0 : step.shadow);
setBevel(step.bevel);
setGradientFactor(step.factor);
setStrokeWidth(step.stroke);
setFillMode((FillMode)step.fillMode);
setClippingRect(applyStepClippingRect(area, clip, step));
_dynamicData = extra;
(this->*(step.drawingCall))(area, step);
}
Common::Rect VectorRenderer::applyStepClippingRect(const Common::Rect &area, const Common::Rect &clip, const DrawStep &step) {
if (step.clip == Common::Rect()) {
return clip;
}
Common::Rect finalClip = clip;
if (step.clip.left > 0) {
finalClip.left = area.left + step.clip.left;
} else if (step.clip.left < 0) {
finalClip.left = area.right + step.clip.left;
}
if (step.clip.top > 0) {
finalClip.top = area.top + step.clip.top;
} else if (step.clip.top < 0) {
finalClip.top = area.bottom + step.clip.top;
}
if (step.clip.right > 0) {
finalClip.right = area.left + step.clip.right;
} else if (step.clip.right < 0) {
finalClip.right = area.right + step.clip.right;
}
if (step.clip.bottom > 0) {
finalClip.bottom = area.top + step.clip.bottom;
} else if (step.clip.bottom < 0) {
finalClip.bottom = area.bottom + step.clip.bottom;
}
finalClip.clip(clip);
return finalClip;
}
int VectorRenderer::stepGetRadius(const DrawStep &step, const Common::Rect &area) {
int radius = 0;
if (step.radius == 0xFF)
radius = MIN(area.width(), area.height()) / 2;
else
radius = step.radius;
if (step.scale != (1 << 16) && step.scale != 0)
radius = (radius * step.scale) >> 16;
return radius;
}
void VectorRenderer::stepGetPositions(const DrawStep &step, const Common::Rect &area, uint16 &in_x, uint16 &in_y, uint16 &in_w, uint16 &in_h) {
if (!step.autoWidth) {
in_w = step.w == -1 ? area.height() : step.w;
switch (step.xAlign) {
case Graphics::DrawStep::kVectorAlignManual:
if (step.x >= 0)
in_x = area.left + step.x + step.padding.left;
else
in_x = area.left + area.width() + step.x + step.padding.left; // value relative to the opposite corner.
break;
case Graphics::DrawStep::kVectorAlignCenter:
in_x = area.left + (area.width() / 2) - (in_w / 2) + ((step.padding.left + step.padding.right ) / 2);
break;
case Graphics::DrawStep::kVectorAlignLeft:
in_x = area.left + step.padding.left;
break;
case Graphics::DrawStep::kVectorAlignRight:
in_x = area.left + area.width() - in_w - step.padding.right;
break;
default:
error("Vertical alignment in horizontal data");
}
} else {
in_x = area.left + step.padding.left;
in_w = area.width() - step.padding.left - step.padding.right;
}
if (!step.autoHeight) {
in_h = step.h == -1 ? area.width() : step.h;
switch (step.yAlign) {
case Graphics::DrawStep::kVectorAlignManual:
if (step.y >= 0)
in_y = area.top + step.y + step.padding.top;
else
in_y = area.top + area.height() + step.y + step.padding.top; // relative
break;
case Graphics::DrawStep::kVectorAlignCenter:
in_y = area.top + (area.height() / 2) - (in_h / 2) + ((step.padding.top + step.padding.bottom ) / 2);
break;
case Graphics::DrawStep::kVectorAlignTop:
in_y = area.top + step.padding.top;
break;
case Graphics::DrawStep::kVectorAlignBottom:
in_y = area.top + area.height() - in_h - step.padding.bottom;
break;
default:
error("Horizontal alignment in vertical data");
}
} else {
in_y = area.top + step.padding.top;
in_h = area.height() - step.padding.top - step.padding.bottom;
}
if (step.scale != (1 << 16) && step.scale != 0) {
in_x = (in_x * step.scale) >> 16;
in_y = (in_y * step.scale) >> 16;
in_w = (in_w * step.scale) >> 16;
in_h = (in_h * step.scale) >> 16;
}
}
} // End of namespace Graphics