瀏覽代碼

Add shear transformation and transform object (issue #152).
Add origin parameters to love.graphics.print.

New shear parameters kx,ky for:
- love.graphics.draw,
- love.graphics.drawq,
- love.graphics.print,
- SpriteBatch:add,
- SpriteBatch:addq.

Transform objects apply to:
- love.graphics.draw,
- love.graphics.drawq,
- love.graphics.print.

vrld 14 年之前
父節點
當前提交
d420d68048

+ 26 - 12
src/common/Matrix.cpp

@@ -116,23 +116,30 @@ namespace love
 		e[5] = sy;
 		e[5] = sy;
 	}
 	}
 
 
-	void Matrix::setTransformation(float x, float y, float angle, float sx, float sy, float ox, float oy)
+	void Matrix::setShear(float kx, float ky)
+	{
+		setIdentity();
+		e[1] = ky;
+		e[4] = kx;
+	}
+
+	void Matrix::setTransformation(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky)
 	{
 	{
 		memset(e, 0, sizeof(float)*16); // zero out matrix
 		memset(e, 0, sizeof(float)*16); // zero out matrix
 		float c = cos(angle), s = sin(angle);
 		float c = cos(angle), s = sin(angle);
 		// matrix multiplication carried out on paper:
 		// matrix multiplication carried out on paper:
-		// |1     x| |c -s    | |sx       | |1     -ox|
-		// |  1   y| |s  c    | |   sy    | |  1   -oy|
-		// |    1  | |     1  | |      1  | |    1    |
-		// |      1| |       1| |        1| |       1 |
-		//   move      rotate      scale       origin
+		// |1     x| |c -s    | |sx       | | 1 ky    | |1     -ox|
+		// |  1   y| |s  c    | |   sy    | |kx  1    | |  1   -oy|
+		// |    1  | |     1  | |      1  | |      1  | |    1    |
+		// |      1| |       1| |        1| |        1| |       1 |
+		//   move      rotate      scale       skew       origin
 		e[10] = e[15] = 1.0f;
 		e[10] = e[15] = 1.0f;
-		e[0] = sx * c;
-		e[1] = sx * s;
-		e[4] = -sy * s;
-		e[5] = sy * c;
-		e[12] = -ox * e[0] - oy * e[4] + x;
-		e[13] = -ox * e[1] - oy * e[5] + y;
+		e[0]  = c * sx - ky * s * sy; // = a
+		e[1]  = s * sx + ky * c * sy; // = b
+		e[4]  = kx * c * sx - s * sy; // = c
+		e[5]  = kx * s * sx + c * sy; // = d
+		e[12] = x - ox * e[0] - oy * e[4];
+		e[13] = y - ox * e[1] - oy * e[5];
 	}
 	}
 
 
 	void Matrix::translate(float x, float y)
 	void Matrix::translate(float x, float y)
@@ -156,6 +163,13 @@ namespace love
 		this->operator *=(t);
 		this->operator *=(t);
 	}
 	}
 
 
+	void Matrix::shear(float kx, float ky)
+	{
+		Matrix t;
+		t.setShear(kx,ky);
+		this->operator *=(t);
+	}
+
 	//                 | x |
 	//                 | x |
 	//                 | y |
 	//                 | y |
 	//                 | 0 |
 	//                 | 0 |

+ 19 - 3
src/common/Matrix.h

@@ -87,7 +87,7 @@ namespace love
 		void setTranslation(float x, float y);
 		void setTranslation(float x, float y);
 
 
 		/**
 		/**
-		* Resets this Matrix to a rotaion.
+		* Resets this Matrix to a rotation.
 		* @param r The angle in radians.
 		* @param r The angle in radians.
 		**/
 		**/
 		void setRotation(float r);
 		void setRotation(float r);
@@ -99,6 +99,13 @@ namespace love
 		**/
 		**/
 		void setScale(float sx, float sy);
 		void setScale(float sx, float sy);
 
 
+		/**
+		* Resets this Matrix to a shear transformation.
+		* @param kx Shear along x-axis.
+		* @param ky Shear along y-axis.
+		**/
+		void setShear(float kx, float ky);
+
 		/**
 		/**
 		* Creates a transformation with a certain position, orientation, scale
 		* Creates a transformation with a certain position, orientation, scale
 		* and offset. Perfect for Drawables -- what a coincidence!
 		* and offset. Perfect for Drawables -- what a coincidence!
@@ -110,8 +117,10 @@ namespace love
 		* @param sy Scale along y-axis.
 		* @param sy Scale along y-axis.
 		* @param ox The offset for rotation along the x-axis.
 		* @param ox The offset for rotation along the x-axis.
 		* @param oy The offset for rotation along the y-axis.
 		* @param oy The offset for rotation along the y-axis.
+		* @param kx Shear along x-axis
+		* @param ky Shear along y-axis
 		**/
 		**/
-		void setTransformation(float x, float y, float angle, float sx, float sy, float ox, float oy);
+		void setTransformation(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky);
 
 
 		/**
 		/**
 		* Multiplies this Matrix with a translation.
 		* Multiplies this Matrix with a translation.
@@ -132,7 +141,14 @@ namespace love
 		* @param sy Scale factor along the y-axis.
 		* @param sy Scale factor along the y-axis.
 		**/
 		**/
 		void scale(float sx, float sy);
 		void scale(float sx, float sy);
-		
+
+		/**
+		* Multiplies this Matrix with a shear transformation.
+		* @param kx Shear along the x-axis.
+		* @param ky Shear along the y-axis.
+		**/
+		void shear(float kx, float ky);
+
 		/**
 		/**
 		* Transforms an array of vertices by this Matrix. The sources and
 		* Transforms an array of vertices by this Matrix. The sources and
 		* destination arrays may be the same. 
 		* destination arrays may be the same. 

+ 3 - 1
src/modules/graphics/Drawable.h

@@ -51,8 +51,10 @@ namespace graphics
 		* @param sy The scale factor along the y-axis.
 		* @param sy The scale factor along the y-axis.
 		* @param ox The origin offset along the x-axis.
 		* @param ox The origin offset along the x-axis.
 		* @param oy The origin offset along the y-axis.
 		* @param oy The origin offset along the y-axis.
+		* @param kx Shear along the x-axis.
+		* @param ky Shear along the y-axis.
 		**/
 		**/
-		virtual void draw(float x, float y, float angle, float sx, float sy, float ox, float oy) const = 0;
+		virtual void draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const = 0;
 	};
 	};
 
 
 } // graphics
 } // graphics

+ 5 - 4
src/modules/graphics/opengl/Font.cpp

@@ -25,6 +25,7 @@
 #include <libraries/utf8/utf8.h>
 #include <libraries/utf8/utf8.h>
 
 
 #include <common/math.h>
 #include <common/math.h>
+#include <common/Matrix.h>
 #include <math.h>
 #include <math.h>
 
 
 #include <algorithm> // for max
 #include <algorithm> // for max
@@ -141,14 +142,14 @@ namespace opengl
 		return static_cast<float>(height);
 		return static_cast<float>(height);
 	}
 	}
 
 
-	void Font::print(std::string text, float x, float y, float angle, float sx, float sy)
+	void Font::print(std::string text, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky)
 	{
 	{
 		float dx = 0.0f; // spacing counter for newline handling
 		float dx = 0.0f; // spacing counter for newline handling
 		glPushMatrix();
 		glPushMatrix();
 
 
-		glTranslatef(ceil(x), ceil(y), 0.0f);
-		glRotatef(LOVE_TODEG(angle), 0, 0, 1.0f);
-		glScalef(sx, sy, 1.0f);
+		Matrix t;
+		t.setTransformation(ceil(x), ceil(y), angle, sx, sy, ox, oy, kx, ky);
+		glMultMatrixf((const GLfloat*)t.getElements());
 		try
 		try
 		{
 		{
 			utf8::iterator<std::string::iterator> i (text.begin(), text.begin(), text.end());
 			utf8::iterator<std::string::iterator> i (text.begin(), text.begin(), text.end());

+ 7 - 1
src/modules/graphics/opengl/Font.h

@@ -93,8 +93,14 @@ namespace opengl
 		* @param x The x-coordinate.
 		* @param x The x-coordinate.
 		* @param y The y-coordinate.
 		* @param y The y-coordinate.
 		* @param angle The amount of rotation.
 		* @param angle The amount of rotation.
+		* @param sx Scale along the x axis.
+		* @param sy Scale along the y axis.
+		* @param ox The origin offset along the x-axis.
+		* @param oy The origin offset along the y-axis.
+		* @param kx Shear along the x axis.
+		* @param ky Shear along the y axis.
 		**/
 		**/
-		void print(std::string text, float x, float y, float angle = 0.0f, float sx = 1.0f, float sy = 1.0f);
+		void print(std::string text, float x, float y, float angle = 0.0f, float sx = 1.0f, float sy = 1.0f, float ox = 0.0f, float oy = 0.0f, float kx = 0.0f, float ky = 0.0f);
 
 
 		/**
 		/**
 		* Prints the character at the designated position.
 		* Prints the character at the designated position.

+ 2 - 2
src/modules/graphics/opengl/Framebuffer.cpp

@@ -250,10 +250,10 @@ namespace opengl
 		strategy->bindFBO(previous);
 		strategy->bindFBO(previous);
 	}
 	}
 
 
-	void Framebuffer::draw(float x, float y, float angle, float sx, float sy, float ox, float oy) const
+	void Framebuffer::draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const
 	{
 	{
 		static Matrix t;
 		static Matrix t;
-		t.setTransformation(x, y, angle, sx, sy, ox, oy);
+		t.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
 
 
 		glPushMatrix();
 		glPushMatrix();
 		glMultMatrixf((const GLfloat*)t.getElements());
 		glMultMatrixf((const GLfloat*)t.getElements());

+ 1 - 1
src/modules/graphics/opengl/Framebuffer.h

@@ -32,7 +32,7 @@ namespace opengl
 
 
 		void clear(const Color& c);
 		void clear(const Color& c);
 
 
-		virtual void draw(float x, float y, float angle, float sx, float sy, float ox, float oy) const;
+		virtual void draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const;
 		love::image::ImageData * getImageData(love::image::Image * image);
 		love::image::ImageData * getImageData(love::image::Image * image);
 
 
 		void setFilter(const Image::Filter &f);
 		void setFilter(const Image::Filter &f);

+ 9 - 2
src/modules/graphics/opengl/Graphics.cpp

@@ -715,12 +715,12 @@ namespace opengl
 		return (int)max;
 		return (int)max;
 	}
 	}
 
 
-	void Graphics::print( const char * str, float x, float y , float angle, float sx, float sy)
+	void Graphics::print( const char * str, float x, float y , float angle, float sx, float sy, float ox, float oy, float kx, float ky)
 	{
 	{
 		if(currentFont != 0)
 		if(currentFont != 0)
 		{
 		{
 			std::string text(str);
 			std::string text(str);
-			currentFont->print(text, x, y, angle, sx, sy);
+			currentFont->print(text, x, y, angle, sx, sy, ox, oy, kx, ky);
 		}
 		}
 	}
 	}
 
 
@@ -1025,6 +1025,13 @@ namespace opengl
 		glTranslatef(x, y, 0);
 		glTranslatef(x, y, 0);
 	}
 	}
 
 
+	void Graphics::shear(float kx, float ky)
+	{
+		Matrix t;
+		t.setShear(kx, ky);
+		glMultMatrixf((const GLfloat*)t.getElements());
+	}
+
 	void Graphics::drawTest(Image * image, float x, float y, float a, float sx, float sy, float ox, float oy)
 	void Graphics::drawTest(Image * image, float x, float y, float a, float sx, float sy, float ox, float oy)
 	{
 	{
 		image->bind();
 		image->bind();

+ 6 - 1
src/modules/graphics/opengl/Graphics.h

@@ -397,8 +397,12 @@ namespace opengl
 		* @param angle The amount of rotation.
 		* @param angle The amount of rotation.
 		* @param sx The scale factor along the x-axis. (1 = normal).
 		* @param sx The scale factor along the x-axis. (1 = normal).
 		* @param sy The scale factor along the y-axis. (1 = normal).
 		* @param sy The scale factor along the y-axis. (1 = normal).
+		* @param ox The origin offset along the x-axis.
+		* @param oy The origin offset along the y-axis.
+		* @param kx Shear along the x-axis.
+		* @param ky Shear along the y-axis.
 		**/
 		**/
-		void print(const char * str, float x, float y , float angle = 0.0f, float sx = 1.0f, float sy = 1.0f);
+		void print(const char * str, float x, float y , float angle, float sx, float sy, float ox, float oy, float kx, float ky);
 
 
 		/**
 		/**
 		* Draw formatted text on screen at the specified coordinates.
 		* Draw formatted text on screen at the specified coordinates.
@@ -502,6 +506,7 @@ namespace opengl
 		void rotate(float r);
 		void rotate(float r);
 		void scale(float x, float y = 1.0f);
 		void scale(float x, float y = 1.0f);
 		void translate(float x, float y);
 		void translate(float x, float y);
+		void shear(float kx, float ky);
 
 
 		void drawTest(Image * image, float x, float y, float a, float sx, float sy, float ox, float oy);
 		void drawTest(Image * image, float x, float y, float a, float sx, float sy, float ox, float oy);
 
 

+ 4 - 4
src/modules/graphics/opengl/Image.cpp

@@ -102,20 +102,20 @@ namespace opengl
 		vertices[3].s = tx+tw; vertices[3].t = ty;
 		vertices[3].s = tx+tw; vertices[3].t = ty;
 	}
 	}
 
 
-	void Image::draw(float x, float y, float angle, float sx, float sy, float ox, float oy) const
+	void Image::draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const
 	{
 	{
 		static Matrix t;
 		static Matrix t;
 
 
-		t.setTransformation(x, y, angle, sx, sy, ox, oy);
+		t.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
 		drawv(t, vertices);
 		drawv(t, vertices);
 	}
 	}
 
 
-	void Image::drawq(Quad * quad, float x, float y, float angle, float sx, float sy, float ox, float oy) const
+	void Image::drawq(Quad * quad, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const
 	{
 	{
 		static Matrix t;
 		static Matrix t;
 		const vertex * v = quad->getVertices();
 		const vertex * v = quad->getVertices();
 
 
-		t.setTransformation(x, y, angle, sx, sy, ox, oy);
+		t.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
 		drawv(t, v);
 		drawv(t, v);
 	}
 	}
 
 

+ 2 - 2
src/modules/graphics/opengl/Image.h

@@ -111,7 +111,7 @@ namespace opengl
 		/**
 		/**
 		* @copydoc Drawable::draw()
 		* @copydoc Drawable::draw()
 		**/
 		**/
-		void draw(float x, float y, float angle, float sx, float sy, float ox, float oy) const;
+		void draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const;
 
 
 		/**
 		/**
 		* This function draws a section of the image using a Quad object.
 		* This function draws a section of the image using a Quad object.
@@ -119,7 +119,7 @@ namespace opengl
 		* @copydetails Image::draws()
 		* @copydetails Image::draws()
 		* @param frame Represents the region of the Image to draw.
 		* @param frame Represents the region of the Image to draw.
 		**/
 		**/
-		void drawq(Quad * quad, float x, float y, float angle, float sx, float sy, float ox, float oy) const;
+		void drawq(Quad * quad, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const;
 
 
 		/**
 		/**
 		* Sets the filter mode.
 		* Sets the filter mode.

+ 5 - 6
src/modules/graphics/opengl/ParticleSystem.cpp

@@ -383,17 +383,16 @@ namespace opengl
 		return pLast == pEnd;
 		return pLast == pEnd;
 	}
 	}
 
 
-	void ParticleSystem::draw(float x, float y, float angle, float sx, float sy, float ox, float oy) const
+	void ParticleSystem::draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const
 	{
 	{
 		if(sprite == 0) return; // just in case of failure
 		if(sprite == 0) return; // just in case of failure
 
 
 		glPushMatrix();
 		glPushMatrix();
 		glPushAttrib(GL_CURRENT_BIT);
 		glPushAttrib(GL_CURRENT_BIT);
 
 
-		glTranslatef(x, y, 0);
-		glRotatef(LOVE_TODEG(angle), 0, 0, 1.0f);
-		glScalef(sx, sy, 1.0f);
-		glTranslatef( ox, oy, 0);
+		Matrix t;
+		t.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
+		glMultMatrixf((const GLfloat*)t.getElements());
 
 
 		particle * p = pStart;
 		particle * p = pStart;
 		while(p != pLast)
 		while(p != pLast)
@@ -401,7 +400,7 @@ namespace opengl
 			glPushMatrix();
 			glPushMatrix();
 
 
 			glColor4f(p->color.r, p->color.g, p->color.b, p->color.a);
 			glColor4f(p->color.r, p->color.g, p->color.b, p->color.a);
-			sprite->draw(p->position[0], p->position[1], p->rotation, p->size, p->size, offsetX, offsetY);
+			sprite->draw(p->position[0], p->position[1], p->rotation, p->size, p->size, offsetX, offsetY, 0.0f, 0.0f);
 
 
 			glPopMatrix();
 			glPopMatrix();
 			p++;
 			p++;

+ 1 - 1
src/modules/graphics/opengl/ParticleSystem.h

@@ -425,7 +425,7 @@ namespace opengl
 		* @param x The x-coordinate.
 		* @param x The x-coordinate.
 		* @param y The y-coordinate.
 		* @param y The y-coordinate.
 		**/
 		**/
-		virtual void draw(float x, float y, float angle, float sx, float sy, float ox, float oy) const;
+		virtual void draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const;
 
 
 		/**
 		/**
 		* Updates the particle system.
 		* Updates the particle system.

+ 6 - 6
src/modules/graphics/opengl/SpriteBatch.cpp

@@ -101,7 +101,7 @@ namespace opengl
 			glDeleteBuffers(2, vbo);
 			glDeleteBuffers(2, vbo);
 	}
 	}
 
 
-	void SpriteBatch::add(float x, float y, float a, float sx, float sy, float ox, float oy)
+	void SpriteBatch::add(float x, float y, float a, float sx, float sy, float ox, float oy, float kx, float ky)
 	{
 	{
 		// Only do this if there's a free slot.
 		// Only do this if there's a free slot.
 		if(next < size)
 		if(next < size)
@@ -114,7 +114,7 @@ namespace opengl
 
 
 			// Transform.
 			// Transform.
 			Matrix t;
 			Matrix t;
-			t.setTransformation(x, y, a, sx, sy, ox, oy);
+			t.setTransformation(x, y, a, sx, sy, ox, oy, kx, ky);
 			t.transform(v, v, 4);
 			t.transform(v, v, 4);
 
 
 			addv(v);
 			addv(v);
@@ -124,7 +124,7 @@ namespace opengl
 		}
 		}
 	}
 	}
 
 
-	void SpriteBatch::addq(Quad * quad, float x, float y, float a, float sx, float sy, float ox, float oy)
+	void SpriteBatch::addq(Quad * quad, float x, float y, float a, float sx, float sy, float ox, float oy, float kx, float ky)
 	{
 	{
 		// Only do this if there's a free slot.
 		// Only do this if there's a free slot.
 		if(next < size)
 		if(next < size)
@@ -137,7 +137,7 @@ namespace opengl
 
 
 			// Transform.
 			// Transform.
 			Matrix t;
 			Matrix t;
-			t.setTransformation(x, y, a, sx, sy, ox, oy);
+			t.setTransformation(x, y, a, sx, sy, ox, oy, kx, ky);
 			t.transform(v, v, 4);
 			t.transform(v, v, 4);
 
 
 			addv(v);
 			addv(v);
@@ -180,13 +180,13 @@ namespace opengl
 		image->retain();
 		image->retain();
 	}
 	}
 
 
-	void SpriteBatch::draw(float x, float y, float angle, float sx, float sy, float ox, float oy) const
+	void SpriteBatch::draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const
 	{
 	{
 		static Matrix t;
 		static Matrix t;
 
 
 		glPushMatrix();
 		glPushMatrix();
 
 
-		t.setTransformation(x, y, angle, sx, sy, ox, oy);
+		t.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
 		glMultMatrixf((const GLfloat*)t.getElements());
 		glMultMatrixf((const GLfloat*)t.getElements());
 
 
 		image->bind();
 		image->bind();

+ 3 - 3
src/modules/graphics/opengl/SpriteBatch.h

@@ -89,8 +89,8 @@ namespace opengl
 		bool loadVolatile();
 		bool loadVolatile();
 		void unloadVolatile();
 		void unloadVolatile();
 
 
-		void add(float x, float y, float a, float sx, float sy, float ox, float oy);
-		void addq(Quad * quad, float x, float y, float a, float sx, float sy, float ox, float oy);
+		void add(float x, float y, float a, float sx, float sy, float ox, float oy, float kx, float ky);
+		void addq(Quad * quad, float x, float y, float a, float sx, float sy, float ox, float oy, float kx, float ky);
 		void clear();
 		void clear();
 
 
 		void * lock();
 		void * lock();
@@ -99,7 +99,7 @@ namespace opengl
 		void setImage(Image * newimage);
 		void setImage(Image * newimage);
 
 
 		// Implements Drawable.
 		// Implements Drawable.
-		void draw(float x, float y, float angle, float sx, float sy, float ox, float oy) const;
+		void draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const;
 
 
 	private:
 	private:
 
 

+ 24 - 4
src/modules/graphics/opengl/wrap_Graphics.cpp

@@ -694,6 +694,8 @@ namespace opengl
 	* @param sy The scale factor along the y-axis. (1 = normal).
 	* @param sy The scale factor along the y-axis. (1 = normal).
 	* @param ox The offset along the x-axis.
 	* @param ox The offset along the x-axis.
 	* @param oy The offset along the y-axis.
 	* @param oy The offset along the y-axis.
+	* @param kx Shear along the x-axis.
+	* @param ky Shear along the y-axis.
 	**/
 	**/
 	int w_draw(lua_State * L)
 	int w_draw(lua_State * L)
 	{
 	{
@@ -705,7 +707,9 @@ namespace opengl
 		float sy = (float)luaL_optnumber(L, 6, sx);
 		float sy = (float)luaL_optnumber(L, 6, sx);
 		float ox = (float)luaL_optnumber(L, 7, 0);
 		float ox = (float)luaL_optnumber(L, 7, 0);
 		float oy = (float)luaL_optnumber(L, 8, 0);
 		float oy = (float)luaL_optnumber(L, 8, 0);
-		drawable->draw(x, y, angle, sx, sy, ox, oy);
+		float kx = (float)luaL_optnumber(L, 9, 0);
+		float ky = (float)luaL_optnumber(L, 10, 0);
+		drawable->draw(x, y, angle, sx, sy, ox, oy, kx, ky);
 		return 0;
 		return 0;
 	}
 	}
 
 
@@ -721,6 +725,8 @@ namespace opengl
 	* @param sy The scale factor along the y-axis. (1 = normal).
 	* @param sy The scale factor along the y-axis. (1 = normal).
 	* @param ox The offset along the x-axis.
 	* @param ox The offset along the x-axis.
 	* @param oy The offset along the y-axis.
 	* @param oy The offset along the y-axis.
+	* @param kx Shear along the x-axis.
+	* @param ky Shear along the y-axis.
 	**/
 	**/
 	int w_drawq(lua_State * L)
 	int w_drawq(lua_State * L)
 	{
 	{
@@ -733,7 +739,9 @@ namespace opengl
 		float sy = (float)luaL_optnumber(L, 7, sx);
 		float sy = (float)luaL_optnumber(L, 7, sx);
 		float ox = (float)luaL_optnumber(L, 8, 0);
 		float ox = (float)luaL_optnumber(L, 8, 0);
 		float oy = (float)luaL_optnumber(L, 9, 0);
 		float oy = (float)luaL_optnumber(L, 9, 0);
-		image->drawq(q, x, y, angle, sx, sy, ox, oy);
+		float kx = (float)luaL_optnumber(L, 9, 0);
+		float ky = (float)luaL_optnumber(L, 10, 0);
+		image->drawq(q, x, y, angle, sx, sy, ox, oy, kx, ky);
 		return 0;
 		return 0;
 	}
 	}
 
 
@@ -759,9 +767,13 @@ namespace opengl
 		float angle = (float)luaL_optnumber(L, 4, 0.0f);
 		float angle = (float)luaL_optnumber(L, 4, 0.0f);
 		float sx = (float)luaL_optnumber(L, 5, 1.0f);
 		float sx = (float)luaL_optnumber(L, 5, 1.0f);
 		float sy = (float)luaL_optnumber(L, 6, sx);
 		float sy = (float)luaL_optnumber(L, 6, sx);
+		float ox = (float)luaL_optnumber(L, 7, 0.0f);
+		float oy = (float)luaL_optnumber(L, 8, 0.0f);
+		float kx = (float)luaL_optnumber(L, 9, 0.0f);
+		float ky = (float)luaL_optnumber(L, 10, 0.0f);
 		try
 		try
 		{
 		{
-			instance->print(str, x, y, angle, sx, sy);
+			instance->print(str, x, y, angle, sx, sy, ox, oy, kx,ky);
 		}
 		}
 		catch (love::Exception e)
 		catch (love::Exception e)
 		{
 		{
@@ -1013,6 +1025,14 @@ namespace opengl
 		return 0;
 		return 0;
 	}
 	}
 
 
+	int w_shear(lua_State * L)
+	{
+		float kx = (float)luaL_checknumber(L, 1);
+		float ky = (float)luaL_checknumber(L, 2);
+		instance->shear(kx, ky);
+		return 0;
+	}
+
 	int w_hasFocus(lua_State * L)
 	int w_hasFocus(lua_State * L)
 	{
 	{
 		luax_pushboolean(L, instance->hasFocus());
 		luax_pushboolean(L, instance->hasFocus());
@@ -1103,8 +1123,8 @@ namespace opengl
 		{ "pop", w_pop },
 		{ "pop", w_pop },
 		{ "rotate", w_rotate },
 		{ "rotate", w_rotate },
 		{ "scale", w_scale },
 		{ "scale", w_scale },
-
 		{ "translate", w_translate },
 		{ "translate", w_translate },
+		{ "shear", w_shear },
 
 
 		{ "hasFocus", w_hasFocus },
 		{ "hasFocus", w_hasFocus },
 
 

+ 1 - 0
src/modules/graphics/opengl/wrap_Graphics.h

@@ -102,6 +102,7 @@ namespace opengl
 	int w_rotate(lua_State * L);
 	int w_rotate(lua_State * L);
 	int w_scale(lua_State * L);
 	int w_scale(lua_State * L);
 	int w_translate(lua_State * L);
 	int w_translate(lua_State * L);
+	int w_shear(lua_State * L);
 	int w_hasFocus(lua_State * L);
 	int w_hasFocus(lua_State * L);
 	extern "C" LOVE_EXPORT int luaopen_love_graphics(lua_State * L);
 	extern "C" LOVE_EXPORT int luaopen_love_graphics(lua_State * L);
 
 

+ 6 - 2
src/modules/graphics/opengl/wrap_SpriteBatch.cpp

@@ -41,7 +41,9 @@ namespace opengl
 		float sy = (float)luaL_optnumber(L, 6, sx);
 		float sy = (float)luaL_optnumber(L, 6, sx);
 		float ox = (float)luaL_optnumber(L, 7, 0);
 		float ox = (float)luaL_optnumber(L, 7, 0);
 		float oy = (float)luaL_optnumber(L, 8, 0);
 		float oy = (float)luaL_optnumber(L, 8, 0);
-		t->add(x, y, angle, sx, sy, ox, oy);
+		float kx = (float)luaL_optnumber(L, 10, 0);
+		float ky = (float)luaL_optnumber(L, 11, 0);
+		t->add(x, y, angle, sx, sy, ox, oy, kx, ky);
 		return 0;
 		return 0;
 	}
 	}
 
 
@@ -56,7 +58,9 @@ namespace opengl
 		float sy = (float)luaL_optnumber(L, 7, sx);
 		float sy = (float)luaL_optnumber(L, 7, sx);
 		float ox = (float)luaL_optnumber(L, 8, 0);
 		float ox = (float)luaL_optnumber(L, 8, 0);
 		float oy = (float)luaL_optnumber(L, 9, 0);
 		float oy = (float)luaL_optnumber(L, 9, 0);
-		t->addq(q, x, y, angle, sx, sy, ox, oy);
+		float kx = (float)luaL_optnumber(L, 10, 0);
+		float ky = (float)luaL_optnumber(L, 11, 0);
+		t->addq(q, x, y, angle, sx, sy, ox, oy, kx, ky);
 		return 0;
 		return 0;
 	}
 	}
 
 

+ 29 - 0
src/scripts/graphics.lua

@@ -1276,4 +1276,33 @@ AAIAAAxQCuxfDzz1AB8IAAAAAAC6ufC4AAAAALrCZ5H+if4dCkwHbQAAAAgAAQAAAAAAAA==
 		love.graphics.printf = love.graphics.printf1
 		love.graphics.printf = love.graphics.printf1
 	end
 	end
 
 
+
+	local function unpack_transform(transform, ...)
+		if type(transform) ~= "table" then
+			return transform, ...
+		end
+
+		local r = transform.rot or transform.r or 0
+		local sx = transform.sx or transform.scale or 1
+		local sy = transform.sy or transform.scale or 1
+		local ox, oy = transform.ox or 0, transform.oy or 0
+		local kx, ky = transform.kx or 0, transform.ky or 0
+
+		return r,sx,sy,ox,oy,kx,ky
+	end
+
+	local draw = love.graphics.draw
+	function love.graphics.draw(drawable, x, y, ...)
+		draw(drawable, x, y, unpack_transform(...))
+	end
+
+	local drawq = love.graphics.drawq
+	function love.graphics.drawq(img, quad, x, y, ...)
+		drawq(img, quad, x, y, unpack_transform(...))
+	end
+
+	local lgprint = love.graphics.print1 -- << notice the 1
+	function love.graphics.print(text, x,y, ...)
+		lgprint(text, x,y, unpack_transform(...))
+	end
 end
 end

+ 55 - 0
src/scripts/graphics.lua.h

@@ -5030,7 +5030,62 @@ const unsigned char graphics_lua[] =
 	0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 
 	0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 
 	0x69, 0x6e, 0x74, 0x66, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 
 	0x69, 0x6e, 0x74, 0x66, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 
 	0x63, 0x73, 0x2e, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x31, 0x0a,
 	0x63, 0x73, 0x2e, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x31, 0x0a,
+	0x09, 0x65, 0x6e, 0x64, 0x0a,0x0a,0x0a,
+	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x75, 0x6e, 
+	0x70, 0x61, 0x63, 0x6b, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x28, 0x74, 0x72, 0x61, 
+	0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x2c, 0x20, 0x2e, 0x2e, 0x2e, 0x29, 0x0a,
+	0x09, 0x09, 0x69, 0x66, 0x20, 0x74, 0x79, 0x70, 0x65, 0x28, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 
+	0x6d, 0x29, 0x20, 0x7e, 0x3d, 0x20, 0x22, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
+	0x09, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 
+	0x6d, 0x2c, 0x20, 0x2e, 0x2e, 0x2e, 0x0a,
+	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,0x0a,
+	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x72, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 
+	0x6f, 0x72, 0x6d, 0x2e, 0x72, 0x6f, 0x74, 0x20, 0x6f, 0x72, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 
+	0x72, 0x6d, 0x2e, 0x72, 0x20, 0x6f, 0x72, 0x20, 0x30, 0x0a,
+	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, 0x78, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 
+	0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x73, 0x78, 0x20, 0x6f, 0x72, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 
+	0x72, 0x6d, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x31, 0x0a,
+	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, 0x79, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 
+	0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x73, 0x79, 0x20, 0x6f, 0x72, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 
+	0x72, 0x6d, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x31, 0x0a,
+	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6f, 0x78, 0x2c, 0x20, 0x6f, 0x79, 0x20, 0x3d, 0x20, 0x74, 
+	0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x6f, 0x78, 0x20, 0x6f, 0x72, 0x20, 0x30, 0x2c, 0x20, 
+	0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x6f, 0x79, 0x20, 0x6f, 0x72, 0x20, 0x30, 0x0a,
+	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6b, 0x78, 0x2c, 0x20, 0x6b, 0x79, 0x20, 0x3d, 0x20, 0x74, 
+	0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x6b, 0x78, 0x20, 0x6f, 0x72, 0x20, 0x30, 0x2c, 0x20, 
+	0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x6b, 0x79, 0x20, 0x6f, 0x72, 0x20, 0x30, 0x0a,0x0a,
+	0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x2c, 0x73, 0x78, 0x2c, 0x73, 0x79, 0x2c, 0x6f, 
+	0x78, 0x2c, 0x6f, 0x79, 0x2c, 0x6b, 0x78, 0x2c, 0x6b, 0x79, 0x0a,
 	0x09, 0x65, 0x6e, 0x64, 0x0a,0x0a,
 	0x09, 0x65, 0x6e, 0x64, 0x0a,0x0a,
+	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x72, 0x61, 0x77, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x65, 
+	0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x64, 0x72, 0x61, 0x77, 0x0a,
+	0x09, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 
+	0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x64, 0x72, 0x61, 0x77, 0x28, 0x64, 0x72, 0x61, 0x77, 0x61, 0x62, 0x6c, 
+	0x65, 0x2c, 0x20, 0x78, 0x2c, 0x20, 0x79, 0x2c, 0x20, 0x2e, 0x2e, 0x2e, 0x29, 0x0a,
+	0x09, 0x09, 0x64, 0x72, 0x61, 0x77, 0x28, 0x64, 0x72, 0x61, 0x77, 0x61, 0x62, 0x6c, 0x65, 0x2c, 0x20, 0x78, 
+	0x2c, 0x20, 0x79, 0x2c, 0x20, 0x75, 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 
+	0x6f, 0x72, 0x6d, 0x28, 0x2e, 0x2e, 0x2e, 0x29, 0x29, 0x0a,
+	0x09, 0x65, 0x6e, 0x64, 0x0a,0x0a,
+	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x72, 0x61, 0x77, 0x71, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 
+	0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x64, 0x72, 0x61, 0x77, 0x71, 0x0a,
+	0x09, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 
+	0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x64, 0x72, 0x61, 0x77, 0x71, 0x28, 0x69, 0x6d, 0x67, 0x2c, 0x20, 0x71, 
+	0x75, 0x61, 0x64, 0x2c, 0x20, 0x78, 0x2c, 0x20, 0x79, 0x2c, 0x20, 0x2e, 0x2e, 0x2e, 0x29, 0x0a,
+	0x09, 0x09, 0x64, 0x72, 0x61, 0x77, 0x71, 0x28, 0x69, 0x6d, 0x67, 0x2c, 0x20, 0x71, 0x75, 0x61, 0x64, 0x2c, 
+	0x20, 0x78, 0x2c, 0x20, 0x79, 0x2c, 0x20, 0x75, 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x74, 0x72, 0x61, 0x6e, 
+	0x73, 0x66, 0x6f, 0x72, 0x6d, 0x28, 0x2e, 0x2e, 0x2e, 0x29, 0x29, 0x0a,
+	0x09, 0x65, 0x6e, 0x64, 0x0a,0x0a,
+	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6c, 0x67, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x6c, 
+	0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x69, 0x6e, 0x74, 
+	0x31, 0x20, 0x2d, 0x2d, 0x20, 0x3c, 0x3c, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x20, 0x74, 0x68, 0x65, 
+	0x20, 0x31, 0x0a,
+	0x09, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 
+	0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x28, 0x74, 0x65, 0x78, 0x74, 0x2c, 0x20, 
+	0x78, 0x2c, 0x79, 0x2c, 0x20, 0x2e, 0x2e, 0x2e, 0x29, 0x0a,
+	0x09, 0x09, 0x6c, 0x67, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x28, 0x74, 0x65, 0x78, 0x74, 0x2c, 0x20, 0x78, 0x2c, 
+	0x79, 0x2c, 0x20, 0x75, 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 
+	0x6d, 0x28, 0x2e, 0x2e, 0x2e, 0x29, 0x29, 0x0a,
+	0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x65, 0x6e, 0x64, 0x0a,
 	0x65, 0x6e, 0x64, 0x0a,
 }; // [graphics.lua]
 }; // [graphics.lua]
 } // love
 } // love