GRAPHICS: Added ManagedSurface and Screen classes
This commit is contained in:
parent
7105fb23a8
commit
433a2daa6a
7 changed files with 869 additions and 0 deletions
|
@ -21,6 +21,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "graphics/font.h"
|
#include "graphics/font.h"
|
||||||
|
#include "graphics/managed_surface.h"
|
||||||
|
|
||||||
#include "common/array.h"
|
#include "common/array.h"
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
|
@ -273,6 +274,16 @@ void Font::drawString(Surface *dst, const Common::U32String &str, int x, int y,
|
||||||
drawStringImpl(*this, dst, str, x, y, w, color, align, 0);
|
drawStringImpl(*this, dst, str, x, y, w, color, align, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Font::drawString(ManagedSurface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align, int deltax, bool useEllipsis) const {
|
||||||
|
drawString(&dst->_innerSurface, str, x, y, w, color, align, deltax, useEllipsis);
|
||||||
|
dst->addDirtyRect(Common::Rect(x, y, x + w, y + getFontHeight()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Font::drawString(ManagedSurface *dst, const Common::U32String &str, int x, int y, int w, uint32 color, TextAlign align) const {
|
||||||
|
drawString(&dst->_innerSurface, str, x, y, w, color, align);
|
||||||
|
dst->addDirtyRect(Common::Rect(x, y, x + w, y + getFontHeight()));
|
||||||
|
}
|
||||||
|
|
||||||
int Font::wordWrapText(const Common::String &str, int maxWidth, Common::Array<Common::String> &lines) const {
|
int Font::wordWrapText(const Common::String &str, int maxWidth, Common::Array<Common::String> &lines) const {
|
||||||
return wordWrapTextImpl(*this, str, maxWidth, lines);
|
return wordWrapTextImpl(*this, str, maxWidth, lines);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ template<class T> class Array;
|
||||||
namespace Graphics {
|
namespace Graphics {
|
||||||
|
|
||||||
struct Surface;
|
struct Surface;
|
||||||
|
class ManagedSurface;
|
||||||
|
|
||||||
/** Text alignment modes */
|
/** Text alignment modes */
|
||||||
enum TextAlign {
|
enum TextAlign {
|
||||||
|
@ -145,6 +146,8 @@ public:
|
||||||
// TODO: Add doxygen comments to this
|
// TODO: Add doxygen comments to this
|
||||||
void drawString(Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const;
|
void drawString(Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const;
|
||||||
void drawString(Surface *dst, const Common::U32String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft) const;
|
void drawString(Surface *dst, const Common::U32String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft) const;
|
||||||
|
void drawString(ManagedSurface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const;
|
||||||
|
void drawString(ManagedSurface *dst, const Common::U32String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute and return the width the string str has when rendered using this font.
|
* Compute and return the width the string str has when rendered using this font.
|
||||||
|
|
258
graphics/managed_surface.cpp
Normal file
258
graphics/managed_surface.cpp
Normal file
|
@ -0,0 +1,258 @@
|
||||||
|
/* 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/managed_surface.h"
|
||||||
|
#include "common/algorithm.h"
|
||||||
|
#include "common/textconsole.h"
|
||||||
|
|
||||||
|
namespace Graphics {
|
||||||
|
|
||||||
|
const int SCALE_THRESHOLD = 0x100;
|
||||||
|
|
||||||
|
ManagedSurface::ManagedSurface() :
|
||||||
|
w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format),
|
||||||
|
_isManaged(false), _owner(nullptr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ManagedSurface::ManagedSurface(const ManagedSurface &surf) :
|
||||||
|
w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format),
|
||||||
|
_isManaged(false), _owner(nullptr) {
|
||||||
|
*this = surf;
|
||||||
|
}
|
||||||
|
|
||||||
|
ManagedSurface::ManagedSurface(int width, int height) :
|
||||||
|
w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format),
|
||||||
|
_isManaged(false), _owner(nullptr) {
|
||||||
|
create(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
ManagedSurface::ManagedSurface(int width, int height, const Graphics::PixelFormat &pixelFormat) :
|
||||||
|
w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format),
|
||||||
|
_isManaged(false), _owner(nullptr) {
|
||||||
|
create(width, height, format);
|
||||||
|
}
|
||||||
|
|
||||||
|
ManagedSurface::ManagedSurface(ManagedSurface &surf, const Common::Rect &bounds) :
|
||||||
|
w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format),
|
||||||
|
_isManaged(false), _owner(nullptr) {
|
||||||
|
create(surf, bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
ManagedSurface::~ManagedSurface() {
|
||||||
|
free();
|
||||||
|
}
|
||||||
|
|
||||||
|
ManagedSurface &ManagedSurface::operator=(const ManagedSurface &surf) {
|
||||||
|
if (surf._isManaged) {
|
||||||
|
// Create a new surface and copy the pixels from the source surface
|
||||||
|
create(surf.w, surf.h, surf.format);
|
||||||
|
Common::copy((const byte *)surf.getPixels(), (const byte *)surf.getPixels() +
|
||||||
|
surf.w * surf.h * surf.format.bytesPerPixel, (byte *)this->getPixels());
|
||||||
|
} else {
|
||||||
|
// Source isn't managed, so simply copy it's fields
|
||||||
|
_isManaged = false;
|
||||||
|
_owner = surf._owner;
|
||||||
|
_offsetFromOwner = surf._offsetFromOwner;
|
||||||
|
|
||||||
|
void *srcPixels = (void *)surf._innerSurface.getPixels();
|
||||||
|
_innerSurface.setPixels(srcPixels);
|
||||||
|
_innerSurface.w = surf.w;
|
||||||
|
_innerSurface.h = surf.h;
|
||||||
|
_innerSurface.pitch = surf.pitch;
|
||||||
|
this->format = surf.format;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ManagedSurface::setPixels(void *newPixels) {
|
||||||
|
free();
|
||||||
|
_innerSurface.setPixels(newPixels);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ManagedSurface::create(uint16 width, uint16 height) {
|
||||||
|
create(width, height, PixelFormat::createFormatCLUT8());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ManagedSurface::create(uint16 width, uint16 height, const PixelFormat &pixelFormat) {
|
||||||
|
free();
|
||||||
|
_innerSurface.create(width, height, pixelFormat);
|
||||||
|
|
||||||
|
_isManaged = true;
|
||||||
|
markAllDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ManagedSurface::create(ManagedSurface &surf, const Common::Rect &bounds) {
|
||||||
|
free();
|
||||||
|
|
||||||
|
_offsetFromOwner = Common::Point(bounds.left, bounds.top);
|
||||||
|
_innerSurface.setPixels(surf.getBasePtr(bounds.left, bounds.top));
|
||||||
|
_innerSurface.pitch = surf.pitch;
|
||||||
|
_innerSurface.format = surf.format;
|
||||||
|
_innerSurface.w = bounds.width();
|
||||||
|
_innerSurface.h = bounds.height();
|
||||||
|
_owner = &surf;
|
||||||
|
_isManaged = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ManagedSurface::free() {
|
||||||
|
if (_isManaged)
|
||||||
|
_innerSurface.free();
|
||||||
|
|
||||||
|
_isManaged = false;
|
||||||
|
_owner = nullptr;
|
||||||
|
_offsetFromOwner = Common::Point(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ManagedSurface::clip(Common::Rect &srcBounds, Common::Rect &destBounds) {
|
||||||
|
if (destBounds.left >= this->w || destBounds.top >= this->h ||
|
||||||
|
destBounds.right <= 0 || destBounds.bottom <= 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Clip the bounds if necessary to fit on-screen
|
||||||
|
if (destBounds.right > this->w) {
|
||||||
|
srcBounds.right -= destBounds.right - this->w;
|
||||||
|
destBounds.right = this->w;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (destBounds.bottom > this->h) {
|
||||||
|
srcBounds.bottom -= destBounds.bottom - this->h;
|
||||||
|
destBounds.bottom = this->h;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (destBounds.top < 0) {
|
||||||
|
srcBounds.top += -destBounds.top;
|
||||||
|
destBounds.top = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (destBounds.left < 0) {
|
||||||
|
srcBounds.left += -destBounds.left;
|
||||||
|
destBounds.left = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ManagedSurface::blitFrom(const Surface &src) {
|
||||||
|
blitFrom(src, Common::Rect(0, 0, src.w, src.h), Common::Point(0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ManagedSurface::blitFrom(const Surface &src, const Common::Point &destPos) {
|
||||||
|
blitFrom(src, Common::Rect(0, 0, src.w, src.h), destPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ManagedSurface::blitFrom(const Surface &src, const Common::Rect &srcRect,
|
||||||
|
const Common::Point &destPos) {
|
||||||
|
Common::Rect srcBounds = srcRect;
|
||||||
|
Common::Rect destBounds(destPos.x, destPos.y, destPos.x + srcRect.width(),
|
||||||
|
destPos.y + srcRect.height());
|
||||||
|
assert(src.format.bytesPerPixel == format.bytesPerPixel);
|
||||||
|
|
||||||
|
if (!srcRect.isValidRect() || !clip(srcBounds, destBounds))
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int y = 0; y < srcBounds.height(); ++y) {
|
||||||
|
const byte *srcP = (const byte *)src.getBasePtr(srcBounds.left, srcBounds.top + y);
|
||||||
|
byte *destP = (byte *)getBasePtr(destBounds.left, destBounds.top + y);
|
||||||
|
Common::copy(srcP, srcP + srcBounds.width() * format.bytesPerPixel, destP);
|
||||||
|
}
|
||||||
|
|
||||||
|
addDirtyRect(Common::Rect(0, 0, this->w, this->h));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ManagedSurface::transBlitFrom(const Surface &src, uint transColor, bool flipped, uint overrideColor) {
|
||||||
|
transBlitFrom(src, Common::Rect(0, 0, src.w, src.h), Common::Rect(0, 0, this->w, this->h),
|
||||||
|
transColor, false, overrideColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ManagedSurface::transBlitFrom(const Surface &src, const Common::Point &destPos,
|
||||||
|
uint transColor, bool flipped, uint overrideColor) {
|
||||||
|
transBlitFrom(src, Common::Rect(0, 0, src.w, src.h), Common::Rect(destPos.x, destPos.y,
|
||||||
|
destPos.x + src.w, destPos.y + src.h), transColor, false, overrideColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ManagedSurface::transBlitFrom(const Surface &src, const Common::Rect &srcRect,
|
||||||
|
const Common::Point &destPos, uint transColor, bool flipped, uint overrideColor) {
|
||||||
|
transBlitFrom(src, srcRect, Common::Rect(destPos.x, destPos.y,
|
||||||
|
destPos.x + src.w, destPos.y + src.h), transColor, false, overrideColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void transBlit(const Surface &src, const Common::Rect &srcRect, const Surface *dest, const Common::Rect &destRect, uint transColor, bool flipped, uint overrideColor) {
|
||||||
|
int scaleX = SCALE_THRESHOLD * srcRect.width() / destRect.width();
|
||||||
|
int scaleY = SCALE_THRESHOLD * srcRect.height() / destRect.height();
|
||||||
|
|
||||||
|
// Loop through drawing output lines
|
||||||
|
for (int destY = destRect.top, scaleYCtr = 0; destY < destRect.bottom; ++destY, scaleYCtr += scaleY) {
|
||||||
|
if (destY < 0 || destY >= dest->h)
|
||||||
|
continue;
|
||||||
|
const T *srcLine = (const T *)src.getBasePtr(0, scaleYCtr / SCALE_THRESHOLD);
|
||||||
|
T *destLine = (T *)dest->getBasePtr(destRect.left, destY);
|
||||||
|
|
||||||
|
// Loop through drawing the pixels of the row
|
||||||
|
for (int destX = destRect.left, xCtr = 0, scaleXCtr = 0; destX < destRect.right; ++destX, ++xCtr, scaleXCtr += scaleX) {
|
||||||
|
if (destX < 0 || destX >= dest->w)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
T srcVal = srcLine[flipped ? src.w - scaleXCtr / SCALE_THRESHOLD - 1 : scaleXCtr / SCALE_THRESHOLD];
|
||||||
|
if (srcVal != transColor) {
|
||||||
|
destLine[xCtr] = overrideColor ? overrideColor : srcVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ManagedSurface::transBlitFrom(const Surface &src, const Common::Rect &srcRect,
|
||||||
|
const Common::Rect &destRect, uint transColor, bool flipped, uint overrideColor) {
|
||||||
|
if (src.w == 0 || src.h == 0 || destRect.width() == 0 || destRect.height() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (format.bytesPerPixel == 1)
|
||||||
|
transBlit<byte>(src, srcRect, &_innerSurface, destRect, transColor, flipped, overrideColor);
|
||||||
|
else if (format.bytesPerPixel == 2)
|
||||||
|
transBlit<uint16>(src, srcRect, &_innerSurface, destRect, transColor, flipped, overrideColor);
|
||||||
|
else if (format.bytesPerPixel == 4)
|
||||||
|
transBlit<uint32>(src, srcRect, &_innerSurface, destRect, transColor, flipped, overrideColor);
|
||||||
|
else
|
||||||
|
error("Surface::transBlitFrom: bytesPerPixel must be 1, 2, or 4");
|
||||||
|
|
||||||
|
// Mark the affected area
|
||||||
|
addDirtyRect(destRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ManagedSurface::markAllDirty() {
|
||||||
|
addDirtyRect(Common::Rect(0, 0, this->w, this->h));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ManagedSurface::addDirtyRect(const Common::Rect &r) {
|
||||||
|
if (_owner) {
|
||||||
|
Common::Rect bounds = r;
|
||||||
|
bounds.translate(_offsetFromOwner.x, _offsetFromOwner.y);
|
||||||
|
_owner->addDirtyRect(bounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ManagedSurface::clear(uint color) {
|
||||||
|
fillRect(getBounds(), color);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End of namespace Graphics
|
355
graphics/managed_surface.h
Normal file
355
graphics/managed_surface.h
Normal file
|
@ -0,0 +1,355 @@
|
||||||
|
/* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GRAPHICS_MANAGED_SURFACE_H
|
||||||
|
#define GRAPHICS_MANAGED_SURFACE_H
|
||||||
|
|
||||||
|
#include "graphics/pixelformat.h"
|
||||||
|
#include "graphics/surface.h"
|
||||||
|
#include "common/rect.h"
|
||||||
|
|
||||||
|
namespace Graphics {
|
||||||
|
|
||||||
|
class Font;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A derived graphics surface, which handles automatically managing the allocated
|
||||||
|
* surface data block, as well as introducing several new blitting methods
|
||||||
|
*/
|
||||||
|
class ManagedSurface {
|
||||||
|
friend class Font;
|
||||||
|
private:
|
||||||
|
Surface _innerSurface;
|
||||||
|
bool _isManaged;
|
||||||
|
ManagedSurface *_owner;
|
||||||
|
Common::Point _offsetFromOwner;
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* Clips the given source bounds so the passed destBounds will be entirely on-screen
|
||||||
|
*/
|
||||||
|
bool clip(Common::Rect &srcBounds, Common::Rect &destBounds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base method that descendent classes can override for recording affected
|
||||||
|
* dirty areas of the surface
|
||||||
|
*/
|
||||||
|
virtual void addDirtyRect(const Common::Rect &r);
|
||||||
|
public:
|
||||||
|
uint16 &w;
|
||||||
|
uint16 &h;
|
||||||
|
uint16 &pitch;
|
||||||
|
PixelFormat &format;
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Create the managed surface
|
||||||
|
*/
|
||||||
|
ManagedSurface();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a managed surface from another one
|
||||||
|
* Note that if the source has a managed surface, it will be duplicated
|
||||||
|
*/
|
||||||
|
ManagedSurface(const ManagedSurface &surf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the managed surface
|
||||||
|
*/
|
||||||
|
ManagedSurface(int width, int height);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the managed surface
|
||||||
|
*/
|
||||||
|
ManagedSurface(int width, int height, const Graphics::PixelFormat &pixelFormat);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the managed surface
|
||||||
|
*/
|
||||||
|
ManagedSurface(ManagedSurface &surf, const Common::Rect &bounds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy the managed surface
|
||||||
|
*/
|
||||||
|
virtual ~ManagedSurface();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements automatic conversion to a Graphics::Surface by
|
||||||
|
* simply returning the inner surface. This must be const,
|
||||||
|
* because we don't want changes being done directly to it,
|
||||||
|
* since it would bypass dirty rect handling
|
||||||
|
*/
|
||||||
|
operator const Surface &() const { return _innerSurface; }
|
||||||
|
const Surface &rawSurface() const { return _innerSurface; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reassign one managed surface to another one
|
||||||
|
* Note that if the source has a managed surface, it will be duplicated
|
||||||
|
*/
|
||||||
|
ManagedSurface &operator=(const ManagedSurface &surf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the surface has not yet been allocated
|
||||||
|
*/
|
||||||
|
bool empty() const { return w == 0 || h == 0 || _innerSurface.getPixels() == nullptr; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the surface is managing it's own pixels
|
||||||
|
*/
|
||||||
|
bool isManaged() const { return _isManaged; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a pointer to the pixel at the specified point.
|
||||||
|
*
|
||||||
|
* @param x The x coordinate of the pixel.
|
||||||
|
* @param y The y coordinate of the pixel.
|
||||||
|
* @return Pointer to the pixel.
|
||||||
|
*/
|
||||||
|
inline const void *getBasePtr(int x, int y) const {
|
||||||
|
return _innerSurface.getBasePtr(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a pointer to the pixel at the specified point.
|
||||||
|
*
|
||||||
|
* @param x The x coordinate of the pixel.
|
||||||
|
* @param y The y coordinate of the pixel.
|
||||||
|
* @return Pointer to the pixel.
|
||||||
|
*/
|
||||||
|
inline void *getBasePtr(int x, int y) {
|
||||||
|
return _innerSurface.getBasePtr(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a reference to the pixel data
|
||||||
|
*/
|
||||||
|
inline void *getPixels() { return _innerSurface.getPixels(); }
|
||||||
|
inline const void *getPixels() const { return _innerSurface.getPixels(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the pixel data.
|
||||||
|
*/
|
||||||
|
virtual void setPixels(void *newPixels);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate memory for the pixel data of the surface.
|
||||||
|
*/
|
||||||
|
virtual void create(uint16 width, uint16 height);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate memory for the pixel data of the surface.
|
||||||
|
*/
|
||||||
|
virtual void create(uint16 width, uint16 height, const PixelFormat &pixelFormat);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up the surface as a sub-section of another passed parent surface. This surface
|
||||||
|
* will not own the pixels, and any dirty rect notifications will automatically be
|
||||||
|
* passed to the original parent surface.
|
||||||
|
* @remarks Note that this differs from Graphics::Surface::getSubArea, in that that
|
||||||
|
* method only adds a single initial dirty rect for the whole area, and then none further
|
||||||
|
*/
|
||||||
|
virtual void create(ManagedSurface &surf, const Common::Rect &bounds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release the memory used by the pixels memory of this surface. This is the
|
||||||
|
* counterpart to create().
|
||||||
|
*/
|
||||||
|
virtual void free();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears any pending dirty rects that have been generated for the surface
|
||||||
|
*/
|
||||||
|
virtual void clearDirtyRects() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When the managed surface is a sub-section of a parent surface, returns the
|
||||||
|
* the offset in the parent surface that the surface starts at
|
||||||
|
*/
|
||||||
|
const Common::Point getOffsetFromOwner() const { return _offsetFromOwner; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a rect giving the bounds of the surface
|
||||||
|
*/
|
||||||
|
const Common::Rect getBounds() const {
|
||||||
|
return Common::Rect(0, 0, this->w, this->h);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies another surface into this one
|
||||||
|
*/
|
||||||
|
void blitFrom(const Surface &src);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies another surface into this one at a given destination position
|
||||||
|
*/
|
||||||
|
void blitFrom(const Surface &src, const Common::Point &destPos);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies another surface into this one at a given destination position
|
||||||
|
*/
|
||||||
|
void blitFrom(const Surface &src, const Common::Rect &srcRect,
|
||||||
|
const Common::Point &destPos);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies another surface into this one ignoring pixels of a designated transparent color
|
||||||
|
* @param src Source surface
|
||||||
|
* @param transColor Transparency color to ignore copying
|
||||||
|
* @param flipped Specifies whether to horizontally flip the image
|
||||||
|
* @param overrideColor Optional color to use instead of non-transparent pixels from
|
||||||
|
* the source surface
|
||||||
|
*/
|
||||||
|
void transBlitFrom(const Surface &src, uint transColor = 0, bool flipped = false, uint overrideColor = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies another surface into this one ignoring pixels of a designated transparent color
|
||||||
|
* @param src Source surface
|
||||||
|
* @param destPos Destination position to draw the surface
|
||||||
|
* @param transColor Transparency color to ignore copying
|
||||||
|
* @param flipped Specifies whether to horizontally flip the image
|
||||||
|
* @param overrideColor Optional color to use instead of non-transparent pixels from
|
||||||
|
* the source surface
|
||||||
|
*/
|
||||||
|
void transBlitFrom(const Surface &src, const Common::Point &destPos,
|
||||||
|
uint transColor = 0, bool flipped = false, uint overrideColor = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies another surface into this one ignoring pixels of a designated transparent color
|
||||||
|
* @param src Source surface
|
||||||
|
* @param srcRect Sub-section of source surface to draw
|
||||||
|
* @param destPos Destination position to draw the surface
|
||||||
|
* @param transColor Transparency color to ignore copying
|
||||||
|
* @param flipped Specifies whether to horizontally flip the image
|
||||||
|
* @param overrideColor Optional color to use instead of non-transparent pixels from
|
||||||
|
* the source surface
|
||||||
|
*/
|
||||||
|
void transBlitFrom(const Surface &src, const Common::Rect &srcRect, const Common::Point &destPos,
|
||||||
|
uint transColor = 0, bool flipped = false, uint overrideColor = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies another surface into this one ignoring pixels of a designated transparent color
|
||||||
|
* @param src Source surface
|
||||||
|
* @param srcRect Sub-section of source surface to draw
|
||||||
|
* @param destRect Destination area to draw the surface in. This can be sized differently
|
||||||
|
* then srcRect, allowing for arbitrary scaling of the image
|
||||||
|
* @param transColor Transparency color to ignore copying
|
||||||
|
* @param flipped Specifies whether to horizontally flip the image
|
||||||
|
* @param overrideColor Optional color to use instead of non-transparent pixels from
|
||||||
|
* the source surface
|
||||||
|
*/
|
||||||
|
void transBlitFrom(const Surface &src, const Common::Rect &srcRect, const Common::Rect &destRect,
|
||||||
|
uint transColor = 0, bool flipped = false, uint overrideColor = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the entire surface
|
||||||
|
*/
|
||||||
|
void clear(uint color = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark the entire surface as dirty
|
||||||
|
*/
|
||||||
|
void markAllDirty();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies a bitmap to the Surface internal buffer. The pixel format
|
||||||
|
* of buffer must match the pixel format of the Surface.
|
||||||
|
*/
|
||||||
|
void copyRectToSurface(const void *buffer, int srcPitch, int destX, int destY, int width, int height) {
|
||||||
|
_innerSurface.copyRectToSurface(buffer, srcPitch, destX, destY, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies a bitmap to the Surface internal buffer. The pixel format
|
||||||
|
* of buffer must match the pixel format of the Surface.
|
||||||
|
*/
|
||||||
|
void copyRectToSurface(const Graphics::Surface &srcSurface, int destX, int destY, const Common::Rect subRect) {
|
||||||
|
_innerSurface.copyRectToSurface(srcSurface, destX, destY, subRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the data from another Surface, reinitializing the
|
||||||
|
* surface to match the dimensions of the passed surface
|
||||||
|
*/
|
||||||
|
void copyFrom(const ManagedSurface &surf) {
|
||||||
|
clearDirtyRects();
|
||||||
|
_innerSurface.copyFrom(surf._innerSurface);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw a line.
|
||||||
|
*/
|
||||||
|
void drawLine(int x0, int y0, int x1, int y1, uint32 color) {
|
||||||
|
_innerSurface.drawLine(x0, y0, x1, y1, color);
|
||||||
|
addDirtyRect(Common::Rect(x0, y0, x1, y1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw a thick line.
|
||||||
|
*/
|
||||||
|
void drawThickLine(int x0, int y0, int x1, int y1, int penX, int penY, uint32 color) {
|
||||||
|
_innerSurface.drawThickLine(x0, y0, x1, y1, penX, penY, color);
|
||||||
|
addDirtyRect(Common::Rect(x0, y0, x1, y1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw a horizontal line.
|
||||||
|
*/
|
||||||
|
void hLine(int x, int y, int x2, uint32 color) {
|
||||||
|
_innerSurface.hLine(x, y, x2, color);
|
||||||
|
addDirtyRect(Common::Rect(x, y, x2 + 1, y + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw a vertical line.
|
||||||
|
*/
|
||||||
|
void vLine(int x, int y, int y2, uint32 color) {
|
||||||
|
_innerSurface.vLine(x, y, y2, color);
|
||||||
|
addDirtyRect(Common::Rect(x, y, x + 1, y2 + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill a rect with a given color.
|
||||||
|
*/
|
||||||
|
void fillRect(Common::Rect r, uint32 color) {
|
||||||
|
_innerSurface.fillRect(r, color);
|
||||||
|
addDirtyRect(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw a frame around a specified rect.
|
||||||
|
*/
|
||||||
|
void frameRect(const Common::Rect &r, uint32 color) {
|
||||||
|
_innerSurface.frameRect(r, color);
|
||||||
|
addDirtyRect(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a sub-area of the screen, but only adds a single initial dirty rect
|
||||||
|
* for the retrieved area.
|
||||||
|
*/
|
||||||
|
Surface getSubArea(const Common::Rect &area) {
|
||||||
|
addDirtyRect(area);
|
||||||
|
return _innerSurface.getSubArea(area);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End of namespace Graphics
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -12,10 +12,12 @@ MODULE_OBJS := \
|
||||||
fonts/ttf.o \
|
fonts/ttf.o \
|
||||||
fonts/winfont.o \
|
fonts/winfont.o \
|
||||||
maccursor.o \
|
maccursor.o \
|
||||||
|
managed_surface.o \
|
||||||
pixelformat.o \
|
pixelformat.o \
|
||||||
primitives.o \
|
primitives.o \
|
||||||
scaler.o \
|
scaler.o \
|
||||||
scaler/thumbnail_intern.o \
|
scaler/thumbnail_intern.o \
|
||||||
|
screen.o \
|
||||||
sjis.o \
|
sjis.o \
|
||||||
surface.o \
|
surface.o \
|
||||||
transform_struct.o \
|
transform_struct.o \
|
||||||
|
|
129
graphics/screen.cpp
Normal file
129
graphics/screen.cpp
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
/* 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/system.h"
|
||||||
|
#include "common/algorithm.h"
|
||||||
|
#include "graphics/screen.h"
|
||||||
|
#include "graphics/palette.h"
|
||||||
|
|
||||||
|
namespace Graphics {
|
||||||
|
|
||||||
|
Screen::Screen(): ManagedSurface() {
|
||||||
|
create(g_system->getWidth(), g_system->getHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
Screen::Screen(int width, int height): ManagedSurface() {
|
||||||
|
create(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
Screen::Screen(int width, int height, PixelFormat pixelFormat): ManagedSurface() {
|
||||||
|
create(width, height, pixelFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Screen::update() {
|
||||||
|
// Merge the dirty rects
|
||||||
|
mergeDirtyRects();
|
||||||
|
|
||||||
|
// Loop through copying dirty areas to the physical screen
|
||||||
|
Common::List<Common::Rect>::iterator i;
|
||||||
|
for (i = _dirtyRects.begin(); i != _dirtyRects.end(); ++i) {
|
||||||
|
const Common::Rect &r = *i;
|
||||||
|
const byte *srcP = (const byte *)getBasePtr(r.left, r.top);
|
||||||
|
g_system->copyRectToScreen(srcP, pitch, r.left, r.top,
|
||||||
|
r.width(), r.height());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signal the physical screen to update
|
||||||
|
g_system->updateScreen();
|
||||||
|
_dirtyRects.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Screen::addDirtyRect(const Common::Rect &r) {
|
||||||
|
Common::Rect bounds = r;
|
||||||
|
bounds.clip(getBounds());
|
||||||
|
bounds.translate(getOffsetFromOwner().x, getOffsetFromOwner().y);
|
||||||
|
|
||||||
|
if (bounds.width() > 0 && bounds.height() > 0)
|
||||||
|
_dirtyRects.push_back(bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Screen::makeAllDirty() {
|
||||||
|
addDirtyRect(Common::Rect(0, 0, this->w, this->h));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Screen::mergeDirtyRects() {
|
||||||
|
Common::List<Common::Rect>::iterator rOuter, rInner;
|
||||||
|
|
||||||
|
// Process the dirty rect list to find any rects to merge
|
||||||
|
for (rOuter = _dirtyRects.begin(); rOuter != _dirtyRects.end(); ++rOuter) {
|
||||||
|
rInner = rOuter;
|
||||||
|
while (++rInner != _dirtyRects.end()) {
|
||||||
|
|
||||||
|
if ((*rOuter).intersects(*rInner)) {
|
||||||
|
// These two rectangles overlap, so merge them
|
||||||
|
unionRectangle(*rOuter, *rOuter, *rInner);
|
||||||
|
|
||||||
|
// remove the inner rect from the list
|
||||||
|
_dirtyRects.erase(rInner);
|
||||||
|
|
||||||
|
// move back to beginning of list
|
||||||
|
rInner = rOuter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Screen::unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2) {
|
||||||
|
destRect = src1;
|
||||||
|
destRect.extend(src2);
|
||||||
|
|
||||||
|
return !destRect.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Screen::getPalette(byte palette[PALETTE_SIZE]) {
|
||||||
|
assert(format.bytesPerPixel == 1);
|
||||||
|
g_system->getPaletteManager()->grabPalette(palette, 0, PALETTE_COUNT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Screen::getPalette(byte *palette, uint start, uint num) {
|
||||||
|
assert(format.bytesPerPixel == 1);
|
||||||
|
g_system->getPaletteManager()->grabPalette(palette, start, num);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Screen::setPalette(const byte palette[PALETTE_SIZE]) {
|
||||||
|
assert(format.bytesPerPixel == 1);
|
||||||
|
g_system->getPaletteManager()->setPalette(palette, 0, PALETTE_COUNT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Screen::setPalette(const byte *palette, uint start, uint num) {
|
||||||
|
assert(format.bytesPerPixel == 1);
|
||||||
|
g_system->getPaletteManager()->setPalette(palette, start, num);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Screen::clearPalette() {
|
||||||
|
byte palette[PALETTE_SIZE];
|
||||||
|
Common::fill(&palette[0], &palette[PALETTE_SIZE], 0);
|
||||||
|
setPalette(palette);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End of namespace Graphics
|
111
graphics/screen.h
Normal file
111
graphics/screen.h
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
/* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GRAPHICS_SCREEN_H
|
||||||
|
#define GRAPHICS_SCREEN_H
|
||||||
|
|
||||||
|
#include "graphics/managed_surface.h"
|
||||||
|
#include "graphics/pixelformat.h"
|
||||||
|
#include "common/list.h"
|
||||||
|
#include "common/rect.h"
|
||||||
|
|
||||||
|
namespace Graphics {
|
||||||
|
|
||||||
|
#define PALETTE_COUNT 256
|
||||||
|
#define PALETTE_SIZE (256 * 3)
|
||||||
|
|
||||||
|
class Screen : virtual public ManagedSurface {
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* List of affected areas of the screen
|
||||||
|
*/
|
||||||
|
Common::List<Common::Rect> _dirtyRects;
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Merges together overlapping dirty areas of the screen
|
||||||
|
*/
|
||||||
|
void mergeDirtyRects();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the union of two dirty area rectangles
|
||||||
|
*/
|
||||||
|
bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2);
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* Adds a rectangle to the list of modified areas of the screen during the
|
||||||
|
* current frame
|
||||||
|
*/
|
||||||
|
virtual void addDirtyRect(const Common::Rect &r);
|
||||||
|
public:
|
||||||
|
Screen();
|
||||||
|
Screen(int width, int height);
|
||||||
|
Screen(int width, int height, PixelFormat pixelFormat);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if there are any pending screen updates
|
||||||
|
*/
|
||||||
|
bool isDirty() const { return _dirtyRects.empty(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes the whole screen dirty
|
||||||
|
*/
|
||||||
|
void makeAllDirty();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the current dirty rects list
|
||||||
|
*/
|
||||||
|
virtual void clearDirtyRects() { _dirtyRects.clear(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the screen by copying any affected areas to the system
|
||||||
|
*/
|
||||||
|
virtual void update();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the currently active palette
|
||||||
|
*/
|
||||||
|
void getPalette(byte palette[PALETTE_SIZE]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a portion of the currently active palette
|
||||||
|
*/
|
||||||
|
void getPalette(byte *palette, uint start, uint num);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the palette
|
||||||
|
*/
|
||||||
|
void setPalette(const byte palette[PALETTE_SIZE]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a subsection of the palette
|
||||||
|
*/
|
||||||
|
void setPalette(const byte *palette, uint start, uint num);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the current palette, setting all entries to black
|
||||||
|
*/
|
||||||
|
void clearPalette();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End of namespace Graphics
|
||||||
|
|
||||||
|
#endif
|
Loading…
Add table
Add a link
Reference in a new issue