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/managed_surface.h"
|
||||
|
||||
#include "common/array.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);
|
||||
}
|
||||
|
||||
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 {
|
||||
return wordWrapTextImpl(*this, str, maxWidth, lines);
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ template<class T> class Array;
|
|||
namespace Graphics {
|
||||
|
||||
struct Surface;
|
||||
class ManagedSurface;
|
||||
|
||||
/** Text alignment modes */
|
||||
enum TextAlign {
|
||||
|
@ -145,6 +146,8 @@ public:
|
|||
// 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::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.
|
||||
|
|
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/winfont.o \
|
||||
maccursor.o \
|
||||
managed_surface.o \
|
||||
pixelformat.o \
|
||||
primitives.o \
|
||||
scaler.o \
|
||||
scaler/thumbnail_intern.o \
|
||||
screen.o \
|
||||
sjis.o \
|
||||
surface.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