Switch to Optional

Remove "valid" flag from Rect and Point, derive them directly from
SDL_Rect and SDL_Point structures, simplify logic. Now x/y/w/h member
variables are directly accessible and Rect/Point may be passed as
SDL_Rect/SDL_Point via pointer or reference.

Change all cases where Null Rects and Points were used to Optional.

invalid state related functions like Null(), IsNull() and Get() are
now deprecated but are not removed yet for compatibility sake.
This commit is contained in:
Dmitry Marakasov 2014-12-25 18:30:52 +03:00
parent c576b6bc67
commit 6d0213810b
10 changed files with 103 additions and 178 deletions

View File

@ -25,25 +25,22 @@
namespace SDL2pp { namespace SDL2pp {
Point::Point() : valid_(false) { Point::Point() {
x = 0;
y = 0;
} }
Point::~Point() { Point::Point(int nx, int ny) {
x = nx;
y = ny;
} }
Point::Point(int x, int y) : valid_(true) { Optional<Point> Point::Null() {
point_.x = x; return NullOpt;
point_.y = y;
}
Point Point::Null() {
return Point();
} }
bool Point::operator==(const Point& other) const { bool Point::operator==(const Point& other) const {
if (!valid_ || !other.valid_) return x == other.x && y == other.y;
return valid_ == other.valid_; // true only if both null
return point_.x == other.point_.x && point_.y == other.point_.y;
} }
bool Point::operator!=(const Point& other) const { bool Point::operator!=(const Point& other) const {
@ -51,67 +48,51 @@ bool Point::operator!=(const Point& other) const {
} }
SDL_Point* Point::Get() { SDL_Point* Point::Get() {
return valid_ ? &point_ : nullptr; return this;
} }
const SDL_Point* Point::Get() const { const SDL_Point* Point::Get() const {
return valid_ ? &point_ : nullptr; return this;
} }
bool Point::IsNull() const { bool Point::IsNull() const {
return !valid_; return false;
} }
int Point::GetX() const { int Point::GetX() const {
assert(!IsNull()); return x;
return point_.x;
} }
void Point::SetX(int x) { void Point::SetX(int nx) {
assert(!IsNull()); x = nx;
point_.x = x;
} }
int Point::GetY() const { int Point::GetY() const {
assert(!IsNull()); return y;
return point_.y;
} }
void Point::SetY(int y) { void Point::SetY(int ny) {
assert(!IsNull()); y = ny;
point_.y = y;
} }
Point Point::operator+(const Point& other) const { Point Point::operator+(const Point& other) const {
if (!valid_ || !other.valid_) return Point(x + other.x, y + other.y);
return Point();
return Point(point_.x + other.point_.x, point_.y + other.point_.y);
} }
Point Point::operator-(const Point& other) const { Point Point::operator-(const Point& other) const {
if (!valid_ || !other.valid_) return Point(x - other.x, y - other.y);
return Point();
return Point(point_.x - other.point_.x, point_.y - other.point_.y);
} }
Point& Point::operator+=(const Point& other) { Point& Point::operator+=(const Point& other) {
if (!valid_ || !other.valid_) { x += other.x;
valid_ = false; y += other.y;
} else {
point_.x += other.point_.x;
point_.y += other.point_.y;
}
return *this; return *this;
} }
Point& Point::operator-=(const Point& other) { Point& Point::operator-=(const Point& other) {
if (!valid_ || !other.valid_) { x -= other.x;
valid_ = false; y -= other.y;
} else {
point_.x -= other.point_.x;
point_.y -= other.point_.y;
}
return *this; return *this;
} }

View File

@ -24,21 +24,16 @@
#include <SDL2/SDL_rect.h> #include <SDL2/SDL_rect.h>
#include <SDL2pp/Optional.hh> // for deprecated functionality
namespace SDL2pp { namespace SDL2pp {
class Point { class Point : public SDL_Point{
private:
SDL_Point point_;
bool valid_;
private:
Point();
public: public:
Point(int x, int y); Point();
virtual ~Point(); Point(int nx, int ny);
static Point Null(); static Optional<Point> Null();
Point(const Point&) noexcept = default; Point(const Point&) noexcept = default;
Point(Point&&) noexcept = default; Point(Point&&) noexcept = default;
@ -54,10 +49,10 @@ public:
bool IsNull() const; bool IsNull() const;
int GetX() const; int GetX() const;
void SetX(int x); void SetX(int nx);
int GetY() const; int GetY() const;
void SetY(int y); void SetY(int ny);
Point operator+(const Point& other) const; Point operator+(const Point& other) const;
Point operator-(const Point& other) const; Point operator-(const Point& other) const;

View File

@ -27,28 +27,27 @@
namespace SDL2pp { namespace SDL2pp {
Rect::Rect() : valid_(false) { Rect::Rect() {
x = 0;
y = 0;
w = 0;
h = 0;
} }
Rect::~Rect() { Rect::Rect(int nx, int ny, int nw, int nh) {
x = nx;
y = ny;
w = nw;
h = nh;
} }
Rect::Rect(int x, int y, int w, int h) : valid_(true) { Optional<Rect> Rect::Null() {
rect_.x = x; return NullOpt;
rect_.y = y;
rect_.w = w;
rect_.h = h;
}
Rect Rect::Null() {
return Rect();
} }
bool Rect::operator==(const Rect& other) const { bool Rect::operator==(const Rect& other) const {
if (!valid_ || !other.valid_) return x == other.x && y == other.y &&
return valid_ == other.valid_; // true only if both null w == other.w && h == other.h;
return rect_.x == other.rect_.x && rect_.y == other.rect_.y &&
rect_.w == other.rect_.w && rect_.h == other.rect_.h;
} }
bool Rect::operator!=(const Rect& other) const { bool Rect::operator!=(const Rect& other) const {
@ -56,11 +55,11 @@ bool Rect::operator!=(const Rect& other) const {
} }
SDL_Rect* Rect::Get() { SDL_Rect* Rect::Get() {
return valid_ ? &rect_ : nullptr; return this;
} }
const SDL_Rect* Rect::Get() const { const SDL_Rect* Rect::Get() const {
return valid_ ? &rect_ : nullptr; return this;
} }
Rect Rect::FromCenter(int cx, int cy, int w, int h) { Rect Rect::FromCenter(int cx, int cy, int w, int h) {
@ -68,101 +67,79 @@ Rect Rect::FromCenter(int cx, int cy, int w, int h) {
} }
bool Rect::IsNull() const { bool Rect::IsNull() const {
return !valid_; return false;
} }
int Rect::GetX() const { int Rect::GetX() const {
assert(!IsNull()); return x;
return rect_.x;
} }
void Rect::SetX(int x) { void Rect::SetX(int nx) {
assert(!IsNull()); x = nx;
rect_.x = x;
} }
int Rect::GetY() const { int Rect::GetY() const {
assert(!IsNull()); return y;
return rect_.y;
} }
void Rect::SetY(int y) { void Rect::SetY(int ny) {
assert(!IsNull()); y = ny;
rect_.y = y;
} }
int Rect::GetW() const { int Rect::GetW() const {
assert(!IsNull()); return w;
return rect_.w;
} }
void Rect::SetW(int w) { void Rect::SetW(int nw) {
assert(!IsNull()); w = nw;
rect_.w = w;
} }
int Rect::GetH() const { int Rect::GetH() const {
assert(!IsNull()); return h;
return rect_.h;
} }
void Rect::SetH(int h) { void Rect::SetH(int nh) {
assert(!IsNull()); h = nh;
rect_.h = h;
} }
int Rect::GetX2() const { int Rect::GetX2() const {
assert(!IsNull()); return x + w - 1;
return rect_.x + rect_.w - 1;
} }
void Rect::SetX2(int x2) { void Rect::SetX2(int x2) {
assert(!IsNull()); w = x2 - x + 1;
rect_.w = x2 - rect_.x + 1;
} }
int Rect::GetY2() const { int Rect::GetY2() const {
assert(!IsNull()); return y + h - 1;
return rect_.y + rect_.h - 1;
} }
void Rect::SetY2(int y2) { void Rect::SetY2(int y2) {
assert(!IsNull()); h = y2 - y + 1;
rect_.h = y2 - rect_.y + 1;
} }
bool Rect::Contains(const Point& point) const { bool Rect::Contains(const Point& point) const {
if (IsNull() || point.IsNull()) return !(point.x < x || point.y < y || point.x > GetX2() || point.y > GetY2());
return false;
return !(point.GetX() < GetX() || point.GetY() < GetY() || point.GetX() > GetX2() || point.GetY() > GetY2());
} }
Rect Rect::operator+(const Point& offset) const { Rect Rect::operator+(const Point& offset) const {
assert(!IsNull() && !offset.IsNull()); return Rect(x + offset.x, y + offset.y, w, h);
return Rect(rect_.x + offset.GetX(), rect_.y + offset.GetY(), rect_.w, rect_.h);
} }
Rect& Rect::operator+=(const Point& offset) { Rect& Rect::operator+=(const Point& offset) {
assert(!IsNull() && !offset.IsNull()); x += offset.x;
y += offset.y;
rect_.x += offset.GetX();
rect_.y += offset.GetY();
return *this; return *this;
} }
Rect Rect::operator-(const Point& offset) const { Rect Rect::operator-(const Point& offset) const {
assert(!IsNull() && !offset.IsNull()); return Rect(x - offset.x, y - offset.y, w, h);
return Rect(rect_.x - offset.GetX(), rect_.y - offset.GetY(), rect_.w, rect_.h);
} }
Rect& Rect::operator-=(const Point& offset) { Rect& Rect::operator-=(const Point& offset) {
assert(!IsNull() && !offset.IsNull()); x -= offset.x;
y -= offset.y;
rect_.x -= offset.GetX();
rect_.y -= offset.GetY();
return *this; return *this;
} }

View File

@ -24,25 +24,20 @@
#include <SDL2/SDL_rect.h> #include <SDL2/SDL_rect.h>
#include <SDL2pp/Optional.hh> // for deprecated functionality
struct SDL_Rect; struct SDL_Rect;
namespace SDL2pp { namespace SDL2pp {
class Point; class Point;
class Rect { class Rect : public SDL_Rect {
private:
SDL_Rect rect_;
bool valid_;
private:
Rect();
public: public:
Rect();
Rect(int x, int y, int w, int h); Rect(int x, int y, int w, int h);
virtual ~Rect();
static Rect Null(); static Optional<Rect> Null();
static Rect FromCenter(int cx, int cy, int w, int h); static Rect FromCenter(int cx, int cy, int w, int h);
@ -54,6 +49,7 @@ public:
bool operator==(const Rect& other) const; bool operator==(const Rect& other) const;
bool operator!=(const Rect& other) const; bool operator!=(const Rect& other) const;
// deprecated
SDL_Rect* Get(); SDL_Rect* Get();
const SDL_Rect* Get() const; const SDL_Rect* Get() const;

View File

@ -27,8 +27,6 @@
#include <SDL2pp/Window.hh> #include <SDL2pp/Window.hh>
#include <SDL2pp/Exception.hh> #include <SDL2pp/Exception.hh>
#include <SDL2pp/Texture.hh> #include <SDL2pp/Texture.hh>
#include <SDL2pp/Rect.hh>
#include <SDL2pp/Point.hh>
namespace SDL2pp { namespace SDL2pp {
@ -74,13 +72,13 @@ void Renderer::GetInfo(SDL_RendererInfo* info) {
throw Exception("SDL_GetRendererInfo failed"); throw Exception("SDL_GetRendererInfo failed");
} }
void Renderer::Copy(Texture& texture, const Rect& srcrect, const Rect& dstrect) { void Renderer::Copy(Texture& texture, const Optional<Rect>& srcrect, const Optional<Rect>& dstrect) {
if (SDL_RenderCopy(renderer_, texture.Get(), srcrect.Get(), dstrect.Get()) != 0) if (SDL_RenderCopy(renderer_, texture.Get(), srcrect ? &*srcrect : nullptr, dstrect ? &*dstrect : nullptr) != 0)
throw Exception("SDL_RenderCopy failed"); throw Exception("SDL_RenderCopy failed");
} }
void Renderer::Copy(Texture& texture, const Rect& srcrect, const Rect& dstrect, double angle, const Point& center, int flip) { void Renderer::Copy(Texture& texture, const Optional<Rect>& srcrect, const Optional<Rect>& dstrect, double angle, const Optional<Point>& center, int flip) {
if (SDL_RenderCopyEx(renderer_, texture.Get(), srcrect.Get(), dstrect.Get(), angle, center.Get(), static_cast<SDL_RendererFlip>(flip)) != 0) if (SDL_RenderCopyEx(renderer_, texture.Get(), srcrect ? &*srcrect : nullptr, dstrect ? &*dstrect : nullptr, angle, center ? &*center : nullptr, static_cast<SDL_RendererFlip>(flip)) != 0)
throw Exception("SDL_RenderCopyEx failed"); throw Exception("SDL_RenderCopyEx failed");
} }

View File

@ -25,6 +25,7 @@
#include <SDL2/SDL_stdinc.h> #include <SDL2/SDL_stdinc.h>
#include <SDL2/SDL_blendmode.h> #include <SDL2/SDL_blendmode.h>
#include <SDL2pp/Optional.hh>
#include <SDL2pp/Point.hh> #include <SDL2pp/Point.hh>
#include <SDL2pp/Rect.hh> #include <SDL2pp/Rect.hh>
@ -58,8 +59,8 @@ public:
void GetInfo(SDL_RendererInfo* info); void GetInfo(SDL_RendererInfo* info);
void Copy(Texture& texture, const Rect& srcrect = Rect::Null(), const Rect& dstrect = Rect::Null()); void Copy(Texture& texture, const Optional<Rect>& srcrect = NullOpt, const Optional<Rect>& dstrect = NullOpt);
void Copy(Texture& texture, const Rect& srcrect, const Rect& dstrect, double angle, const Point& center = Point::Null(), int flip = 0); void Copy(Texture& texture, const Optional<Rect>& srcrect, const Optional<Rect>& dstrect, double angle, const Optional<Point>& center = NullOpt, int flip = 0);
void SetDrawColor(Uint8 r, Uint8 g, Uint8 b, Uint8 a = 255); void SetDrawColor(Uint8 r, Uint8 g, Uint8 b, Uint8 a = 255);
void SetTarget(); void SetTarget();

View File

@ -78,8 +78,8 @@ SDL_Texture* Texture::Get() const {
return texture_; return texture_;
} }
void Texture::Update(const Rect& rect, const void* pixels, int pitch) { void Texture::Update(const Optional<Rect>& rect, const void* pixels, int pitch) {
if (SDL_UpdateTexture(texture_, rect.Get(), pixels, pitch) != 0) if (SDL_UpdateTexture(texture_, rect ? &*rect : nullptr, pixels, pitch) != 0)
throw Exception("SDL_UpdateTexture failed"); throw Exception("SDL_UpdateTexture failed");
} }
@ -98,7 +98,7 @@ void Texture::SetColorMod(Uint8 r, Uint8 g, Uint8 b) {
throw Exception("SDL_SetTextureColorMod failed"); throw Exception("SDL_SetTextureColorMod failed");
} }
Texture::LockHandle Texture::Lock(const Rect& rect = Rect::Null()) { Texture::LockHandle Texture::Lock(const Optional<Rect>& rect) {
return LockHandle(this, rect); return LockHandle(this, rect);
} }

View File

@ -27,6 +27,7 @@
#include <SDL2/SDL_stdinc.h> #include <SDL2/SDL_stdinc.h>
#include <SDL2/SDL_blendmode.h> #include <SDL2/SDL_blendmode.h>
#include <SDL2pp/Optional.hh>
#include <SDL2pp/Config.hh> #include <SDL2pp/Config.hh>
struct SDL_Texture; struct SDL_Texture;
@ -50,7 +51,7 @@ public:
int pitch_; int pitch_;
private: private:
LockHandle(Texture* texture, const Rect& rect); LockHandle(Texture* texture, const Optional<Rect>& rect);
public: public:
LockHandle(); LockHandle();
@ -81,13 +82,13 @@ public:
SDL_Texture* Get() const; SDL_Texture* Get() const;
void Update(const Rect& rect, const void* pixels, int pitch); void Update(const Optional<Rect>& rect, const void* pixels, int pitch);
void SetBlendMode(SDL_BlendMode blendMode); void SetBlendMode(SDL_BlendMode blendMode);
void SetAlphaMod(Uint8 alpha = 255); void SetAlphaMod(Uint8 alpha = 255);
void SetColorMod(Uint8 r = 255, Uint8 g = 255, Uint8 b = 255); void SetColorMod(Uint8 r = 255, Uint8 g = 255, Uint8 b = 255);
LockHandle Lock(const Rect& rect); LockHandle Lock(const Optional<Rect>& rect);
Uint32 GetFormat() const; Uint32 GetFormat() const;
int GetAccess() const; int GetAccess() const;

View File

@ -31,8 +31,8 @@ namespace SDL2pp {
Texture::LockHandle::LockHandle() : texture_(nullptr) { Texture::LockHandle::LockHandle() : texture_(nullptr) {
} }
Texture::LockHandle::LockHandle(Texture* texture, const Rect& rect) : texture_(texture) { Texture::LockHandle::LockHandle(Texture* texture, const Optional<Rect>& rect) : texture_(texture) {
if (SDL_LockTexture(texture_->Get(), rect.Get(), &pixels_, &pitch_) != 0) if (SDL_LockTexture(texture_->Get(), rect ? &*rect : nullptr, &pixels_, &pitch_) != 0)
throw Exception("SDL_LockTexture failed"); throw Exception("SDL_LockTexture failed");
} }

View File

@ -10,32 +10,27 @@ BEGIN_TEST()
// Point basic ops // Point basic ops
Point p(1,2); Point p(1,2);
EXPECT_TRUE(!p.IsNull());
EXPECT_TRUE(p.GetX() == 1 && p.GetY() == 2); EXPECT_TRUE(p.GetX() == 1 && p.GetY() == 2);
EXPECT_TRUE(p == Point(1,2)); EXPECT_TRUE(p == Point(1,2));
EXPECT_TRUE(p != Point(1,1)); EXPECT_TRUE(p != Point(1,1));
EXPECT_TRUE(p != Point(2,2)); EXPECT_TRUE(p != Point(2,2));
EXPECT_TRUE(p != Point::Null()); EXPECT_TRUE(p.x == 1);
EXPECT_TRUE(p.Get() != nullptr); EXPECT_TRUE(p.y == 2);
EXPECT_TRUE(p.Get()->x == 1 && p.Get()->y == 2);
p.SetX(4); p.SetX(4);
p.SetY(5); p.SetY(5);
EXPECT_TRUE(p.GetX() == 4 && p.GetY() == 5); EXPECT_TRUE(p.GetX() == 4 && p.GetY() == 5);
EXPECT_TRUE(p == Point(4,5)); EXPECT_TRUE(p == Point(4,5));
EXPECT_TRUE(p.x == 4);
EXPECT_TRUE(p.y == 5);
p = Point(6,7); p = Point(6,7);
EXPECT_TRUE(p.GetX() == 6 && p.GetY() == 7); EXPECT_TRUE(p.GetX() == 6 && p.GetY() == 7);
EXPECT_TRUE(p == Point(6,7)); EXPECT_TRUE(p == Point(6,7));
EXPECT_TRUE(p.x == 6);
p = Point::Null(); EXPECT_TRUE(p.y == 7);
EXPECT_TRUE(p != Point(1,2));
EXPECT_TRUE(p == Point::Null());
EXPECT_TRUE(p.IsNull());
EXPECT_TRUE(p.Get() == nullptr);
} }
{ {
@ -71,35 +66,21 @@ BEGIN_TEST()
EXPECT_TRUE(sum.GetX() == 111 && sum.GetY() == 222); EXPECT_TRUE(sum.GetX() == 111 && sum.GetY() == 222);
EXPECT_TRUE(diff.GetX() == -111 && diff.GetY() == -222); EXPECT_TRUE(diff.GetX() == -111 && diff.GetY() == -222);
sum += Point::Null();
diff -= Point::Null();
EXPECT_TRUE(sum.IsNull());
EXPECT_TRUE(diff.IsNull());
EXPECT_TRUE((Point(1,1) + Point::Null()).IsNull());
EXPECT_TRUE((Point(1,1) - Point::Null()).IsNull());
EXPECT_TRUE((Point::Null() + Point(1,1)).IsNull());
EXPECT_TRUE((Point::Null() - Point(1,1)).IsNull());
EXPECT_TRUE((Point::Null() - Point::Null()).IsNull());
EXPECT_TRUE((Point::Null() - Point::Null()).IsNull());
} }
{ {
// Rect basic ops // Rect basic ops
Rect r(1,2,3,4); Rect r(1,2,3,4);
EXPECT_TRUE(!r.IsNull());
EXPECT_TRUE(r.GetX() == 1 && r.GetY() == 2 && r.GetW() == 3 && r.GetH() == 4); EXPECT_TRUE(r.GetX() == 1 && r.GetY() == 2 && r.GetW() == 3 && r.GetH() == 4);
EXPECT_TRUE(r == Rect(1,2,3,4)); EXPECT_TRUE(r == Rect(1,2,3,4));
EXPECT_TRUE(r != Rect(2,2,3,4)); EXPECT_TRUE(r != Rect(2,2,3,4));
EXPECT_TRUE(r != Rect(1,3,3,4)); EXPECT_TRUE(r != Rect(1,3,3,4));
EXPECT_TRUE(r != Rect(1,2,4,4)); EXPECT_TRUE(r != Rect(1,2,4,4));
EXPECT_TRUE(r != Rect(1,2,3,5)); EXPECT_TRUE(r != Rect(1,2,3,5));
EXPECT_TRUE(r != Rect::Null());
EXPECT_TRUE(r.Get() != nullptr); EXPECT_TRUE(r.Get() != nullptr);
EXPECT_TRUE(r.Get()->x == 1 && r.Get()->y == 2 && r.Get()->w == 3 && r.Get()->h == 4); EXPECT_TRUE(r.Get()->x == 1 && r.Get()->y == 2 && r.Get()->w == 3 && r.Get()->h == 4);
EXPECT_TRUE(r.x == 1 && r.y == 2 && r.w == 3 && r.h == 4);
r.SetX(5); r.SetX(5);
r.SetY(6); r.SetY(6);
@ -108,18 +89,13 @@ BEGIN_TEST()
EXPECT_TRUE(r.GetX() == 5 && r.GetY() == 6 && r.GetW() == 7 && r.GetH() == 8); EXPECT_TRUE(r.GetX() == 5 && r.GetY() == 6 && r.GetW() == 7 && r.GetH() == 8);
EXPECT_TRUE(r == Rect(5,6,7,8)); EXPECT_TRUE(r == Rect(5,6,7,8));
EXPECT_TRUE(r.x == 5 && r.y == 6 && r.w == 7 && r.h == 8);
r = Rect(9,10,11,12); r = Rect(9,10,11,12);
EXPECT_TRUE(r.GetX() == 9 && r.GetY() == 10 && r.GetW() == 11 && r.GetH() == 12); EXPECT_TRUE(r.GetX() == 9 && r.GetY() == 10 && r.GetW() == 11 && r.GetH() == 12);
EXPECT_TRUE(r == Rect(9,10,11,12)); EXPECT_TRUE(r == Rect(9,10,11,12));
EXPECT_TRUE(r.x == 9 && r.y == 10 && r.w == 11 && r.h == 12);
r = Rect::Null();
EXPECT_TRUE(r != Rect(1,2,3,4));
EXPECT_TRUE(r == Rect::Null());
EXPECT_TRUE(r.IsNull());
EXPECT_TRUE(r.Get() == nullptr);
} }
{ {