GRAPHICS: Added ManagedSurface and Screen classes

This commit is contained in:
Paul Gilbert 2016-03-10 21:49:42 -05:00
parent 7105fb23a8
commit 433a2daa6a
7 changed files with 869 additions and 0 deletions

View file

@ -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);
} }

View file

@ -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.

View 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
View 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

View file

@ -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
View 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
View 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