From b86c4627abf3158781433a4572fbbd846306e01d Mon Sep 17 00:00:00 2001
From: laurentgom <laurentgom@4e206d99-4929-0410-ac5d-dfc041789085>
Date: Sat, 13 Jun 2009 21:13:43 +0000
Subject: [PATCH] Added functions and overloads to sf::Rect Slightly changed
 the sf::View interface

git-svn-id: https://sfml.svn.sourceforge.net/svnroot/sfml/branches/sfml2@1138 4e206d99-4929-0410-ac5d-dfc041789085
---
 include/SFML/Graphics/Matrix3.hpp  |   9 ++
 include/SFML/Graphics/Matrix3.inl  |  21 +++++
 include/SFML/Graphics/Rect.hpp     |  48 ++++++++--
 include/SFML/Graphics/Rect.inl     |  66 ++++++++++---
 include/SFML/Graphics/View.hpp     |  91 +++++++++---------
 samples/pong/Pong.cpp              |  16 ++--
 src/SFML/Graphics/Drawable.cpp     |   2 +-
 src/SFML/Graphics/Image.cpp        |  12 +--
 src/SFML/Graphics/RenderTarget.cpp |   2 +-
 src/SFML/Graphics/RenderWindow.cpp |  14 +--
 src/SFML/Graphics/Sprite.cpp       |  14 +--
 src/SFML/Graphics/View.cpp         | 143 +++++++++++++++--------------
 12 files changed, 276 insertions(+), 162 deletions(-)

diff --git a/include/SFML/Graphics/Matrix3.hpp b/include/SFML/Graphics/Matrix3.hpp
index eeea1b0b..2b8db6ea 100644
--- a/include/SFML/Graphics/Matrix3.hpp
+++ b/include/SFML/Graphics/Matrix3.hpp
@@ -30,6 +30,7 @@
 ////////////////////////////////////////////////////////////
 #include <SFML/Config.hpp>
 #include <SFML/System/Vector2.hpp>
+#include <SFML/Graphics/Rect.hpp>
 #include <math.h>
 
 
@@ -68,6 +69,14 @@ public :
     ////////////////////////////////////////////////////////////
     void SetFromTransformations(const Vector2f& Center, const Vector2f& Translation, float Rotation, const Vector2f& Scale);
 
+    ////////////////////////////////////////////////////////////
+    /// Build a matrix from a projection
+    ///
+    /// \param Rectangle : Rectangle defining the region to project
+    ///
+    ////////////////////////////////////////////////////////////
+    void SetFromProjection(const FloatRect& Rectangle);
+
     ////////////////////////////////////////////////////////////
     /// Transform a point by the matrix
     ///
diff --git a/include/SFML/Graphics/Matrix3.inl b/include/SFML/Graphics/Matrix3.inl
index 73c78b70..4f1734ba 100644
--- a/include/SFML/Graphics/Matrix3.inl
+++ b/include/SFML/Graphics/Matrix3.inl
@@ -54,6 +54,7 @@ inline Matrix3::Matrix3(float a00, float a01, float a02,
 ////////////////////////////////////////////////////////////
 inline void Matrix3::SetFromTransformations(const Vector2f& Center, const Vector2f& Translation, float Rotation, const Vector2f& Scale)
 {
+    // Combine the transformations
     float Angle = Rotation * 3.141592654f / 180.f;
     float Cos   = static_cast<float>(cos(Angle));
     float Sin   = static_cast<float>(sin(Angle));
@@ -64,6 +65,7 @@ inline void Matrix3::SetFromTransformations(const Vector2f& Center, const Vector
     float Tx    = -Center.x * SxCos - Center.y * SySin + Translation.x;
     float Ty    =  Center.x * SxSin - Center.y * SyCos + Translation.y;
 
+    // Rebuild the matrix
     myData[0] =  SxCos; myData[4] = SySin; myData[8]  = 0.f; myData[12] = Tx;
     myData[1] = -SxSin; myData[5] = SyCos; myData[9]  = 0.f; myData[13] = Ty;
     myData[2] =  0.f;   myData[6] = 0.f;   myData[10] = 1.f; myData[14] = 0.f;
@@ -71,6 +73,25 @@ inline void Matrix3::SetFromTransformations(const Vector2f& Center, const Vector
 }
 
 
+////////////////////////////////////////////////////////////
+/// Build a matrix from a projection
+////////////////////////////////////////////////////////////
+inline void Matrix3::SetFromProjection(const FloatRect& Rectangle)
+{
+    // Projection components
+    float A =  2.f / Rectangle.GetSize().x;
+    float B = -2.f / Rectangle.GetSize().y;
+    float C = -(Rectangle.Left + Rectangle.Right) / Rectangle.GetSize().x;
+    float D =  (Rectangle.Bottom + Rectangle.Top) / Rectangle.GetSize().y;
+
+    // Rebuild the projection matrix
+    myData[0] = A;   myData[4] = 0.f; myData[8]  = 0.f; myData[12] = C;
+    myData[1] = 0.f; myData[5] = B;   myData[9]  = 0.f; myData[13] = D;
+    myData[2] = 0.f; myData[6] = 0.f; myData[10] = 1.f; myData[14] = 0.f;
+    myData[3] = 0.f; myData[7] = 0.f; myData[11] = 0.f; myData[15] = 1.f;
+}
+
+
 ////////////////////////////////////////////////////////////
 /// Transform a point by the matrix
 ////////////////////////////////////////////////////////////
diff --git a/include/SFML/Graphics/Rect.hpp b/include/SFML/Graphics/Rect.hpp
index 5decd3c5..e956d6ac 100644
--- a/include/SFML/Graphics/Rect.hpp
+++ b/include/SFML/Graphics/Rect.hpp
@@ -28,6 +28,7 @@
 ////////////////////////////////////////////////////////////
 // Headers
 ////////////////////////////////////////////////////////////
+#include <SFML/System/Vector2.hpp>
 #include <algorithm>
 
 
@@ -60,20 +61,20 @@ public :
     Rect(T LeftCoord, T TopCoord, T RightCoord, T BottomCoord);
 
     ////////////////////////////////////////////////////////////
-    /// Get the width of the rectangle
+    /// Get the size of the rectangle
     ///
-    /// \return Width of rectangle
+    /// \return Size of rectangle
     ///
     ////////////////////////////////////////////////////////////
-    T GetWidth() const;
+    Vector2<T> GetSize() const;
 
     ////////////////////////////////////////////////////////////
-    /// Get the height of the rectangle
+    /// Get the center of the rectangle
     ///
-    /// \return Height of rectangle
+    /// \return Center of rectangle
     ///
     ////////////////////////////////////////////////////////////
-    T GetHeight() const;
+    Vector2<T> GetCenter() const;
 
     ////////////////////////////////////////////////////////////
     /// Move the whole rectangle by the given offset
@@ -84,6 +85,14 @@ public :
     ////////////////////////////////////////////////////////////
     void Offset(T OffsetX, T OffsetY);
 
+    ////////////////////////////////////////////////////////////
+    /// Move the whole rectangle by the given offset
+    ///
+    /// \param Off : Offset to apply to the current position
+    ///
+    ////////////////////////////////////////////////////////////
+    void Offset(const Vector2<T>& Off);
+
     ////////////////////////////////////////////////////////////
     /// Check if a point is inside the rectangle's area
     ///
@@ -95,16 +104,37 @@ public :
     ////////////////////////////////////////////////////////////
     bool Contains(T X, T Y) const;
 
+    ////////////////////////////////////////////////////////////
+    /// Check if a point is inside the rectangle's area
+    ///
+    /// \param Point : Point to test
+    ///
+    /// \return True if the point is inside
+    ///
+    ////////////////////////////////////////////////////////////
+    bool Contains(const Vector2<T>& Point) const;
+
     ////////////////////////////////////////////////////////////
     /// Check intersection between two rectangles
     ///
-    /// \param Rectangle :       Rectangle to test
-    /// \param OverlappingRect : Rectangle to be filled with overlapping rect (NULL by default)
+    /// \param Rectangle : Rectangle to test
     ///
     /// \return True if rectangles overlap
     ///
     ////////////////////////////////////////////////////////////
-    bool Intersects(const Rect<T>& Rectangle, Rect<T>* OverlappingRect = NULL) const;
+    bool Intersects(const Rect<T>& Rectangle) const;
+
+    ////////////////////////////////////////////////////////////
+    /// Check intersection between two rectangles and return the
+    /// resulting rectangle
+    ///
+    /// \param Rectangle :       Rectangle to test
+    /// \param OverlappingRect : Rectangle to be filled with the overlapping rect
+    ///
+    /// \return True if rectangles overlap
+    ///
+    ////////////////////////////////////////////////////////////
+    bool Intersects(const Rect<T>& Rectangle, Rect<T>& OverlappingRect) const;
 
     ////////////////////////////////////////////////////////////
     // Member data
diff --git a/include/SFML/Graphics/Rect.inl b/include/SFML/Graphics/Rect.inl
index 6c5962dd..e22ed571 100644
--- a/include/SFML/Graphics/Rect.inl
+++ b/include/SFML/Graphics/Rect.inl
@@ -52,22 +52,22 @@ Bottom(BottomCoord)
 
 
 ////////////////////////////////////////////////////////////
-/// Get the width of the rectangle
+/// Get the size of the rectangle
 ////////////////////////////////////////////////////////////
 template <typename T>
-T Rect<T>::GetWidth() const
+Vector2<T> Rect<T>::GetSize() const
 {
-    return Right - Left;
+    return Vector2<T>(Right - Left, Bottom - Top);
 }
 
 
 ////////////////////////////////////////////////////////////
-/// Get the height of the rectangle
+/// Get the center of the rectangle
 ////////////////////////////////////////////////////////////
 template <typename T>
-T Rect<T>::GetHeight() const
+Vector2<T> Rect<T>::GetCenter() const
 {
-    return Bottom - Top;
+    return Vector2<T>((Left + Right) / 2, (Top + Bottom) / 2);
 }
 
 
@@ -84,6 +84,16 @@ void Rect<T>::Offset(T OffsetX, T OffsetY)
 }
 
 
+////////////////////////////////////////////////////////////
+/// Move the whole rectangle by the given offset
+////////////////////////////////////////////////////////////
+template <typename T>
+void Rect<T>::Offset(const Vector2<T>& Off)
+{
+    Offset(Off.x, Off.y);
+}
+
+
 ////////////////////////////////////////////////////////////
 /// Check if a point is inside the rectangle's area
 ////////////////////////////////////////////////////////////
@@ -94,29 +104,55 @@ bool Rect<T>::Contains(T X, T Y) const
 }
 
 
+////////////////////////////////////////////////////////////
+/// Check if a point is inside the rectangle's area
+////////////////////////////////////////////////////////////
+template <typename T>
+bool Rect<T>::Contains(const Vector2<T>& Point) const
+{
+    return Contains(Point.x, Point.y);
+}
+
+
 ////////////////////////////////////////////////////////////
 /// Check intersection between two rectangles
 ////////////////////////////////////////////////////////////
 template <typename T>
-bool Rect<T>::Intersects(const Rect<T>& Rectangle, Rect<T>* OverlappingRect) const
+bool Rect<T>::Intersects(const Rect<T>& Rectangle) const
 {
     // Compute overlapping rect
-    Rect Overlapping(std::max(Left,   Rectangle.Left),
-                     std::max(Top,    Rectangle.Top),
-                     std::min(Right,  Rectangle.Right),
-                     std::min(Bottom, Rectangle.Bottom));
+    Rect<T> Overlapping(std::max(Left,   Rectangle.Left),
+                        std::max(Top,    Rectangle.Top),
+                        std::min(Right,  Rectangle.Right),
+                        std::min(Bottom, Rectangle.Bottom));
+
+    // If overlapping rect is valid, then there is intersection
+    return (Overlapping.Left < Overlapping.Right) && (Overlapping.Top < Overlapping.Bottom);
+}
+
+
+////////////////////////////////////////////////////////////
+/// Check intersection between two rectangles and return the
+/// resulting rectangle
+////////////////////////////////////////////////////////////
+template <typename T>
+bool Rect<T>::Intersects(const Rect<T>& Rectangle, Rect<T>& OverlappingRect) const
+{
+    // Compute overlapping rect
+    Rect<T> Overlapping(std::max(Left,   Rectangle.Left),
+                        std::max(Top,    Rectangle.Top),
+                        std::min(Right,  Rectangle.Right),
+                        std::min(Bottom, Rectangle.Bottom));
 
     // If overlapping rect is valid, then there is intersection
     if ((Overlapping.Left < Overlapping.Right) && (Overlapping.Top < Overlapping.Bottom))
     {
-        if (OverlappingRect)
-            *OverlappingRect = Overlapping;
+        OverlappingRect = Overlapping;
         return true;
     }
     else
     {
-        if (OverlappingRect)
-            *OverlappingRect = Rect(0, 0, 0, 0);
+        OverlappingRect = Rect<T>(0, 0, 0, 0);
         return false;
     }
 }
diff --git a/include/SFML/Graphics/View.hpp b/include/SFML/Graphics/View.hpp
index d5e401a3..f0ae84af 100644
--- a/include/SFML/Graphics/View.hpp
+++ b/include/SFML/Graphics/View.hpp
@@ -36,10 +36,8 @@
 
 namespace sf
 {
-class RenderTarget;
-
 ////////////////////////////////////////////////////////////
-/// This class defines a view (position, size, etc.) ;
+/// This class defines a view (position, size, etc.);
 /// you can consider it as a 2D camera
 ////////////////////////////////////////////////////////////
 class SFML_API View
@@ -55,13 +53,30 @@ public :
     explicit View(const FloatRect& ViewRect = FloatRect(0, 0, 1000, 1000));
 
     ////////////////////////////////////////////////////////////
-    /// Construct the view from its center and half-size
+    /// Construct the view from its center and size
     ///
     /// \param Center :   Center of the view
-    /// \param HalfSize : Half-size of the view (from center to corner)
+    /// \param HalfSize : Size of the view
     ///
     ////////////////////////////////////////////////////////////
-    View(const sf::Vector2f& Center, const sf::Vector2f& HalfSize);
+    View(const Vector2f& Center, const Vector2f& Size);
+
+    ////////////////////////////////////////////////////////////
+    /// Set the rectangle defining the view by its center and size
+    ///
+    /// \param Center : Center of the view rectangle
+    /// \param Size :   Size of the view rectangle
+    ///
+    ////////////////////////////////////////////////////////////
+    void SetRect(const Vector2f& Center, const Vector2f& Size);
+
+    ////////////////////////////////////////////////////////////
+    /// Set the rectangle defining the view
+    ///
+    /// \param Rect : Rectangle defining the center and size of the view
+    ///
+    ////////////////////////////////////////////////////////////
+    void SetRect(const FloatRect& Rect);
 
     ////////////////////////////////////////////////////////////
     /// Change the center of the view (take 2 values)
@@ -78,32 +93,33 @@ public :
     /// \param Center : New center
     ///
     ////////////////////////////////////////////////////////////
-    void SetCenter(const sf::Vector2f& Center);
+    void SetCenter(const Vector2f& Center);
 
     ////////////////////////////////////////////////////////////
-    /// Change the half-size of the view (take 2 values)
+    /// Change the size of the view (take 2 values)
     ///
-    /// \param HalfWidth :  New half-width
-    /// \param HalfHeight : New half-height
+    /// \param Width :  New width
+    /// \param Height : New height
     ///
     ////////////////////////////////////////////////////////////
-    void SetHalfSize(float HalfWidth, float HalfHeight);
+    void SetSize(float Width, float Height);
 
     ////////////////////////////////////////////////////////////
-    /// Change the half-size of the view (take a vector)
+    /// Change the size of the view (take a vector)
     ///
     /// \param HalfSize : New half-size
     ///
     ////////////////////////////////////////////////////////////
-    void SetHalfSize(const sf::Vector2f& HalfSize);
+    void SetSize(const Vector2f& Size);
 
     ////////////////////////////////////////////////////////////
-    /// Rebuild the view from a rectangle
+    /// Get the rectangle defining the view,
+    /// which is the combined center and size.
     ///
-    /// \param ViewRect : Rectangle defining the position and size of the view
+    /// \return View rectangle
     ///
     ////////////////////////////////////////////////////////////
-    void SetFromRect(const FloatRect& ViewRect);
+    FloatRect GetRect() const;
 
     ////////////////////////////////////////////////////////////
     /// Get the center of the view
@@ -111,23 +127,15 @@ public :
     /// \return Center of the view
     ///
     ////////////////////////////////////////////////////////////
-    const sf::Vector2f& GetCenter() const;
+    const Vector2f& GetCenter() const;
 
     ////////////////////////////////////////////////////////////
-    /// Get the half-size of the view
+    /// Get the size of the view
     ///
-    /// \return Half-size of the view
+    /// \return Size of the view
     ///
     ////////////////////////////////////////////////////////////
-    const sf::Vector2f& GetHalfSize() const;
-
-    ////////////////////////////////////////////////////////////
-    /// Get the bounding rectangle of the view
-    ///
-    /// \return Bounding rectangle of the view
-    ///
-    ////////////////////////////////////////////////////////////
-    const sf::FloatRect& GetRect() const;
+    const Vector2f& GetSize() const;
 
     ////////////////////////////////////////////////////////////
     /// Move the view (take 2 values)
@@ -144,7 +152,7 @@ public :
     /// \param Offset : Offset to move the view
     ///
     ////////////////////////////////////////////////////////////
-    void Move(const sf::Vector2f& Offset);
+    void Move(const Vector2f& Offset);
 
     ////////////////////////////////////////////////////////////
     /// Resize the view rectangle to simulate a zoom / unzoom effect
@@ -154,32 +162,33 @@ public :
     ////////////////////////////////////////////////////////////
     void Zoom(float Factor);
 
-private :
-
-    friend class RenderTarget;
-
     ////////////////////////////////////////////////////////////
     /// Get the projection matrix of the view
     ///
-    /// \return Projection matrix containing the view settings
+    /// \return Projection matrix
     ///
     ////////////////////////////////////////////////////////////
     const Matrix3& GetMatrix() const;
 
     ////////////////////////////////////////////////////////////
-    /// Recompute the view rectangle and the projection matrix
+    /// Get the inverse projection matrix of the view
+    ///
+    /// \return Inverse projection matrix
     ///
     ////////////////////////////////////////////////////////////
-    void RecomputeMatrix();
+    const Matrix3& GetInverseMatrix() const;
+
+private :
 
     ////////////////////////////////////////////////////////////
     // Member data
     ////////////////////////////////////////////////////////////
-    sf::Vector2f myCenter;     ///< Center of the view
-    sf::Vector2f myHalfSize;   ///< Half-size of the view
-    FloatRect    myRect;       ///< Rectangle defining the bounds of the view
-    Matrix3      myMatrix;     ///< Precomputed projection matrix corresponding to the view
-    bool         myNeedUpdate; ///< Internal state telling if the matrix needs to be updated
+    sf::Vector2f    myCenter;        ///< Center of the view
+    sf::Vector2f    mySize;          ///< Size of the view
+    mutable Matrix3 myMatrix;        ///< Precomputed projection matrix corresponding to the view
+    mutable Matrix3 myInverseMatrix; ///< Precomputed inverse projection matrix corresponding to the view
+    mutable bool    myNeedUpdate;    ///< Internal state telling if the matrix needs to be updated
+    mutable bool    myNeedInvUpdate; ///< Internal state telling if the matrix needs to be updated
 };
 
 } // namespace sf
diff --git a/samples/pong/Pong.cpp b/samples/pong/Pong.cpp
index 6ca169cf..2ed82ccc 100644
--- a/samples/pong/Pong.cpp
+++ b/samples/pong/Pong.cpp
@@ -57,9 +57,9 @@ int main()
     sf::Sprite RightPaddle(RightPaddleImage);
     sf::Sprite Ball(BallImage);
 
-    LeftPaddle.Move(10, (App.GetView().GetRect().GetHeight() - LeftPaddle.GetSize().y) / 2);
-    RightPaddle.Move(App.GetView().GetRect().GetWidth() - RightPaddle.GetSize().x - 10, (App.GetView().GetRect().GetHeight() - RightPaddle.GetSize().y) / 2);
-    Ball.Move((App.GetView().GetRect().GetWidth() - Ball.GetSize().x) / 2, (App.GetView().GetRect().GetHeight() - Ball.GetSize().y) / 2);
+    LeftPaddle.Move(10, (App.GetView().GetSize().y - LeftPaddle.GetSize().y) / 2);
+    RightPaddle.Move(App.GetView().GetSize().x - RightPaddle.GetSize().x - 10, (App.GetView().GetSize().y - RightPaddle.GetSize().y) / 2);
+    Ball.Move((App.GetView().GetSize().x - Ball.GetSize().x) / 2, (App.GetView().GetSize().y - Ball.GetSize().y) / 2);
 
     // Define the paddles properties
     sf::Clock AITimer;
@@ -97,12 +97,12 @@ int main()
 			// Move the player's paddle
             if (App.GetInput().IsKeyDown(sf::Key::Up) && (LeftPaddle.GetPosition().y > 5.f))
 				LeftPaddle.Move(0.f, -LeftPaddleSpeed * App.GetFrameTime());
-            if (App.GetInput().IsKeyDown(sf::Key::Down) && (LeftPaddle.GetPosition().y < App.GetView().GetRect().GetHeight() - LeftPaddle.GetSize().y - 5.f))
+            if (App.GetInput().IsKeyDown(sf::Key::Down) && (LeftPaddle.GetPosition().y < App.GetView().GetSize().y - LeftPaddle.GetSize().y - 5.f))
 				LeftPaddle.Move(0.f, LeftPaddleSpeed * App.GetFrameTime());
 
 			// Move the computer's paddle
             if (((RightPaddleSpeed < 0.f) && (RightPaddle.GetPosition().y > 5.f)) ||
-                ((RightPaddleSpeed > 0.f) && (RightPaddle.GetPosition().y < App.GetView().GetRect().GetHeight() - RightPaddle.GetSize().y - 5.f)))
+                ((RightPaddleSpeed > 0.f) && (RightPaddle.GetPosition().y < App.GetView().GetSize().y - RightPaddle.GetSize().y - 5.f)))
             {
                 RightPaddle.Move(0.f, RightPaddleSpeed * App.GetFrameTime());
             }
@@ -127,7 +127,7 @@ int main()
 				IsPlaying = false;
 				End.SetText("You lost !\n(press escape to exit)");
 			}
-			if (Ball.GetPosition().x + Ball.GetSize().x > App.GetView().GetRect().GetWidth())
+			if (Ball.GetPosition().x + Ball.GetSize().x > App.GetView().GetSize().x)
 			{
 				IsPlaying = false;
 				End.SetText("You won !\n(press escape to exit)");
@@ -138,11 +138,11 @@ int main()
 				BallAngle = -BallAngle;
 				Ball.SetY(0.1f);
 			}
-			if (Ball.GetPosition().y + Ball.GetSize().y > App.GetView().GetRect().GetHeight())
+			if (Ball.GetPosition().y + Ball.GetSize().y > App.GetView().GetSize().y)
 			{
 				BallSound.Play();
 				BallAngle = -BallAngle;
-				Ball.SetY(App.GetView().GetRect().GetHeight() - Ball.GetSize().y - 0.1f);
+				Ball.SetY(App.GetView().GetSize().y - Ball.GetSize().y - 0.1f);
 			}
 
 			// Check the collisions between the ball and the paddles
diff --git a/src/SFML/Graphics/Drawable.cpp b/src/SFML/Graphics/Drawable.cpp
index e2484c65..788ff264 100644
--- a/src/SFML/Graphics/Drawable.cpp
+++ b/src/SFML/Graphics/Drawable.cpp
@@ -381,7 +381,7 @@ void Drawable::Draw(RenderTarget& Target) const
 
         // We have to use glBlendFuncSeparate so that the resulting alpha is
         // not alpha�, which is incorrect and would cause problems when rendering
-        // alpha pixels to a RenderImage that would be in turn rendered to another render target
+        // alpha pixels to a RenderImage that would be in turn be rendered to another render target
         switch (myBlendMode)
         {
             case Blend::Alpha :
diff --git a/src/SFML/Graphics/Image.cpp b/src/SFML/Graphics/Image.cpp
index 04e06c8d..538fa3e4 100644
--- a/src/SFML/Graphics/Image.cpp
+++ b/src/SFML/Graphics/Image.cpp
@@ -288,7 +288,7 @@ void Image::Copy(const Image& Source, unsigned int DestX, unsigned int DestY, co
 
     // Adjust the source rectangle
     IntRect SrcRect = SourceRect;
-    if (SrcRect.GetWidth() == 0 || (SrcRect.GetHeight() == 0))
+    if (SrcRect.GetSize().x == 0 || (SrcRect.GetSize().y == 0))
     {
         SrcRect.Left   = 0;
         SrcRect.Top    = 0;
@@ -304,8 +304,8 @@ void Image::Copy(const Image& Source, unsigned int DestX, unsigned int DestY, co
     }
 
     // Then find the valid bounds of the destination rectangle
-    int Width  = SrcRect.GetWidth();
-    int Height = SrcRect.GetHeight();
+    int Width  = SrcRect.GetSize().x;
+    int Height = SrcRect.GetSize().y;
     if (DestX + Width  > myWidth)  Width  = myWidth  - DestX;
     if (DestY + Height > myHeight) Height = myHeight - DestY;
 
@@ -368,7 +368,7 @@ bool Image::CopyScreen(RenderWindow& Window, const IntRect& SourceRect)
 {
     // Adjust the source rectangle
     IntRect SrcRect = SourceRect;
-    if (SrcRect.GetWidth() == 0 || (SrcRect.GetHeight() == 0))
+    if (SrcRect.GetSize().x == 0 || (SrcRect.GetSize().y == 0))
     {
         SrcRect.Left   = 0;
         SrcRect.Top    = 0;
@@ -384,8 +384,8 @@ bool Image::CopyScreen(RenderWindow& Window, const IntRect& SourceRect)
     }
 
     // Store the texture dimensions
-    myWidth  = SrcRect.GetWidth();
-    myHeight = SrcRect.GetHeight();
+    myWidth  = SrcRect.GetSize().x;
+    myHeight = SrcRect.GetSize().y;
 
     // We can then create the texture
     if (Window.SetActive() && CreateTexture())
diff --git a/src/SFML/Graphics/RenderTarget.cpp b/src/SFML/Graphics/RenderTarget.cpp
index 234a5a1c..8393c24b 100644
--- a/src/SFML/Graphics/RenderTarget.cpp
+++ b/src/SFML/Graphics/RenderTarget.cpp
@@ -175,7 +175,7 @@ void RenderTarget::Initialize()
         SetRenderStates();
 
         // Setup the default view
-        myDefaultView.SetFromRect(FloatRect(0, 0, static_cast<float>(GetWidth()), static_cast<float>(GetHeight())));
+        myDefaultView.SetRect(FloatRect(0, 0, static_cast<float>(GetWidth()), static_cast<float>(GetHeight())));
         SetView(myDefaultView);
 
         Activate(false);
diff --git a/src/SFML/Graphics/RenderWindow.cpp b/src/SFML/Graphics/RenderWindow.cpp
index 6d859a19..c28e69f7 100644
--- a/src/SFML/Graphics/RenderWindow.cpp
+++ b/src/SFML/Graphics/RenderWindow.cpp
@@ -142,13 +142,15 @@ sf::Vector2f RenderWindow::ConvertCoords(unsigned int WindowX, unsigned int Wind
     if (!TargetView)
         TargetView = &GetView();
 
-    float Left   = TargetView->GetCenter().x - TargetView->GetHalfSize().x;
-    float Top    = TargetView->GetCenter().y - TargetView->GetHalfSize().y;
-    float Right  = TargetView->GetCenter().x + TargetView->GetHalfSize().x;
-    float Bottom = TargetView->GetCenter().y + TargetView->GetHalfSize().y;
+    // First, convert from viewport coordinates to homogeneous coordinates:
+    // --> [0, Width]  to [-1, 1]
+    // --> [0, Height] to [1, -1]
+    Vector2f Coords;
+    Coords.x = -1.f + 2.f * WindowX / GetWidth();
+    Coords.y =  1.f - 2.f * WindowY / GetHeight();
 
-    return sf::Vector2f(Left + WindowX * (Right - Left) / GetWidth(),
-                        Top  + WindowY * (Bottom - Top) / GetHeight());
+    // Then transform by the inverse of the view matrix
+    return TargetView->GetInverseMatrix().Transform(Coords);
 }
 
 
diff --git a/src/SFML/Graphics/Sprite.cpp b/src/SFML/Graphics/Sprite.cpp
index 278b1daf..2b969a30 100644
--- a/src/SFML/Graphics/Sprite.cpp
+++ b/src/SFML/Graphics/Sprite.cpp
@@ -88,8 +88,8 @@ void Sprite::SetSubRect(const IntRect& SubRect)
 ////////////////////////////////////////////////////////////
 void Sprite::Resize(float Width, float Height)
 {
-    int LocalWidth  = mySubRect.GetWidth();
-    int LocalHeight = mySubRect.GetHeight();
+    int LocalWidth  = mySubRect.GetSize().x;
+    int LocalHeight = mySubRect.GetSize().y;
 
     if ((LocalWidth > 0) && (LocalHeight > 0))
         SetScale(Width / LocalWidth, Height / LocalHeight);
@@ -147,7 +147,7 @@ const IntRect& Sprite::GetSubRect() const
 ////////////////////////////////////////////////////////////
 Vector2f Sprite::GetSize() const
 {
-    return Vector2f(mySubRect.GetWidth() * GetScale().x, mySubRect.GetHeight() * GetScale().y);
+    return Vector2f(mySubRect.GetSize().x * GetScale().x, mySubRect.GetSize().y * GetScale().y);
 }
 
 
@@ -162,8 +162,8 @@ Color Sprite::GetPixel(unsigned int X, unsigned int Y) const
         unsigned int ImageX = mySubRect.Left + X;
         unsigned int ImageY = mySubRect.Top  + Y;
 
-        if (myIsFlippedX) ImageX = mySubRect.GetWidth()  - ImageX - 1;
-        if (myIsFlippedY) ImageY = mySubRect.GetHeight() - ImageY - 1;
+        if (myIsFlippedX) ImageX = mySubRect.GetSize().x - ImageX - 1;
+        if (myIsFlippedY) ImageY = mySubRect.GetSize().y - ImageY - 1;
 
         return myImage->GetPixel(ImageX, ImageY) * GetColor();
     }
@@ -180,8 +180,8 @@ Color Sprite::GetPixel(unsigned int X, unsigned int Y) const
 void Sprite::Render(RenderTarget&) const
 {
     // Get the sprite size
-    float Width  = static_cast<float>(mySubRect.GetWidth());
-    float Height = static_cast<float>(mySubRect.GetHeight());
+    float Width  = static_cast<float>(mySubRect.GetSize().x);
+    float Height = static_cast<float>(mySubRect.GetSize().y);
 
     // Check if the image is valid
     if (myImage && (myImage->GetWidth() > 0) && (myImage->GetHeight() > 0))
diff --git a/src/SFML/Graphics/View.cpp b/src/SFML/Graphics/View.cpp
index 0b2fb66a..9143b282 100644
--- a/src/SFML/Graphics/View.cpp
+++ b/src/SFML/Graphics/View.cpp
@@ -26,7 +26,6 @@
 // Headers
 ////////////////////////////////////////////////////////////
 #include <SFML/Graphics/View.hpp>
-#include <algorithm>
 
 
 namespace sf
@@ -34,102 +33,116 @@ namespace sf
 ////////////////////////////////////////////////////////////
 /// Construct the view from a rectangle
 ////////////////////////////////////////////////////////////
-View::View(const FloatRect& ViewRect)
+View::View(const FloatRect& Rect)
 {
-    SetFromRect(ViewRect);
+    SetRect(Rect);
 }
 
 
 ////////////////////////////////////////////////////////////
-/// Construct the view from its center and half-size
+/// Construct the view from its center and size
 ////////////////////////////////////////////////////////////
-View::View(const sf::Vector2f& Center, const sf::Vector2f& HalfSize) :
-myCenter    (Center),
-myHalfSize  (HalfSize),
-myNeedUpdate(true)
+View::View(const Vector2f& Center, const Vector2f& Size) :
+myCenter       (Center),
+mySize         (Size),
+myNeedUpdate   (true),
+myNeedInvUpdate(true)
 {
 
 }
 
 
+////////////////////////////////////////////////////////////
+/// Set the rectangle defining the view by its center and size
+////////////////////////////////////////////////////////////
+void View::SetRect(const Vector2f& Center, const Vector2f& Size)
+{
+    myCenter        = Center;
+    mySize          = Size;
+    myNeedUpdate    = true;
+    myNeedInvUpdate = true;
+}
+
+
+////////////////////////////////////////////////////////////
+/// Set the rectangle defining the view
+////////////////////////////////////////////////////////////
+void View::SetRect(const FloatRect& Rect)
+{
+    SetRect(Rect.GetCenter(), Rect.GetSize());
+}
+
+
 ////////////////////////////////////////////////////////////
 /// Change the center of the view (take 2 values)
 ////////////////////////////////////////////////////////////
 void View::SetCenter(float X, float Y)
 {
-    myCenter.x   = X;
-    myCenter.y   = Y;
-    myNeedUpdate = true;
+    myCenter.x      = X;
+    myCenter.y      = Y;
+    myNeedUpdate    = true;
+    myNeedInvUpdate = true;
 }
 
 
 ////////////////////////////////////////////////////////////
 /// Change the center of the view (take a vector)
 ////////////////////////////////////////////////////////////
-void View::SetCenter(const sf::Vector2f& Center)
+void View::SetCenter(const Vector2f& Center)
 {
     SetCenter(Center.x, Center.y);
 }
 
 
 ////////////////////////////////////////////////////////////
-/// Change the half-size of the view (take 2 values)
+/// Change the size of the view (take 2 values)
 ////////////////////////////////////////////////////////////
-void View::SetHalfSize(float HalfWidth, float HalfHeight)
+void View::SetSize(float Width, float Height)
 {
-    myHalfSize.x = HalfWidth;
-    myHalfSize.y = HalfHeight;
-    myNeedUpdate = true;
+    mySize.x        = Width;
+    mySize.y        = Height;
+    myNeedUpdate    = true;
+    myNeedInvUpdate = true;
 }
 
 
 ////////////////////////////////////////////////////////////
-/// Change the half-size of the view (take a vector)
+/// Change the size of the view (take a vector)
 ////////////////////////////////////////////////////////////
-void View::SetHalfSize(const sf::Vector2f& HalfSize)
+void View::SetSize(const Vector2f& Size)
 {
-    SetHalfSize(HalfSize.x, HalfSize.y);
+    SetSize(Size.x, Size.y);
 }
 
 
 ////////////////////////////////////////////////////////////
-/// Rebuild the view from a rectangle
+/// Get the rectangle defining the view,
+/// which is the combined center and size.
 ////////////////////////////////////////////////////////////
-void View::SetFromRect(const FloatRect& ViewRect)
+FloatRect View::GetRect() const
 {
-    SetCenter(  (ViewRect.Right + ViewRect.Left) / 2, (ViewRect.Bottom + ViewRect.Top) / 2);
-    SetHalfSize((ViewRect.Right - ViewRect.Left) / 2, (ViewRect.Bottom - ViewRect.Top) / 2);
+    return FloatRect(myCenter.x - mySize.x / 2,
+                     myCenter.y - mySize.y / 2,
+                     myCenter.x + mySize.x / 2,
+                     myCenter.y + mySize.y / 2);
 }
 
 
 ////////////////////////////////////////////////////////////
 /// Get the center of the view
 ////////////////////////////////////////////////////////////
-const sf::Vector2f& View::GetCenter() const
+const Vector2f& View::GetCenter() const
 {
     return myCenter;
 }
 
 
 ////////////////////////////////////////////////////////////
-/// Get the half-size of the view
+/// Get the size of the view
 ////////////////////////////////////////////////////////////
-const sf::Vector2f& View::GetHalfSize() const
+const Vector2f& View::GetSize() const
 {
-    return myHalfSize;
-}
-
-
-////////////////////////////////////////////////////////////
-/// Get the bounding rectangle of the view
-////////////////////////////////////////////////////////////
-const sf::FloatRect& View::GetRect() const
-{
-    // Recompute it if needed
-    if (myNeedUpdate)
-        const_cast<View*>(this)->RecomputeMatrix();
-
-    return myRect;
+    return mySize;
 }
 
 
@@ -138,16 +151,17 @@ const sf::FloatRect& View::GetRect() const
 ////////////////////////////////////////////////////////////
 void View::Move(float OffsetX, float OffsetY)
 {
-    myCenter.x  += OffsetX;
-    myCenter.y  += OffsetY;
-    myNeedUpdate = true;
+    myCenter.x     += OffsetX;
+    myCenter.y     += OffsetY;
+    myNeedUpdate    = true;
+    myNeedInvUpdate = true;
 }
 
 
 ////////////////////////////////////////////////////////////
 /// Move the view (take a vector)
 ////////////////////////////////////////////////////////////
-void View::Move(const sf::Vector2f& Offset)
+void View::Move(const Vector2f& Offset)
 {
     Move(Offset.x, Offset.y);
 }
@@ -160,8 +174,9 @@ void View::Zoom(float Factor)
 {
     if (Factor != 0)
     {
-        myHalfSize  /= Factor;
-        myNeedUpdate = true;
+        mySize /= Factor;
+        myNeedUpdate    = true;
+        myNeedInvUpdate = true;
     }
 }
 
@@ -173,36 +188,28 @@ const Matrix3& View::GetMatrix() const
 {
     // Recompute the matrix if needed
     if (myNeedUpdate)
-        const_cast<View*>(this)->RecomputeMatrix();
+    {
+        myMatrix.SetFromProjection(GetRect());
+        myNeedUpdate = false;
+    }
 
     return myMatrix;
 }
 
 
 ////////////////////////////////////////////////////////////
-/// Recompute the view rectangle and the projection matrix
+/// Get the inverse projection matrix of the view
 ////////////////////////////////////////////////////////////
-void View::RecomputeMatrix()
+const Matrix3& View::GetInverseMatrix() const
 {
-    // Compute the 4 corners of the view
-    float Left   = myCenter.x - myHalfSize.x;
-    float Top    = myCenter.y - myHalfSize.y;
-    float Right  = myCenter.x + myHalfSize.x;
-    float Bottom = myCenter.y + myHalfSize.y;
+    // Recompute the matrix if needed
+    if (myNeedInvUpdate)
+    {
+        myInverseMatrix = GetMatrix().GetInverse();
+        myNeedInvUpdate = false;
+    }
 
-    // Update the view rectangle - be careful, reversed views are allowed !
-    myRect.Left   = std::min(Left, Right);
-    myRect.Top    = std::min(Top, Bottom);
-    myRect.Right  = std::max(Left, Right);
-    myRect.Bottom = std::max(Top, Bottom);
-
-    // Update the projection matrix
-    myMatrix(0, 0) = 2.f / (Right - Left);
-    myMatrix(1, 1) = 2.f / (Top - Bottom);
-    myMatrix(0, 2) = (Left + Right) / (Left - Right);
-    myMatrix(1, 2) = (Bottom + Top) / (Bottom - Top);
-
-    myNeedUpdate = false;
+    return myInverseMatrix;
 }
 
 } // namespace sf