GitHub PullRequestReviewCommentEvent at 2014-07-16 19:08:32
Repository: residualvm
Actor: aquadran
Payload: {"action":"created","comment":{"url":"https://api.github.com/repos/residualvm/residualvm/pulls/comments/15020499","id":15020499,"diff_hunk":"@@ -0,0 +1,509 @@\n+#include \"graphics/tinygl/zblit.h\"\n+#include \"graphics/tinygl/zgl.h\"\n+#include \"graphics/pixelbuffer.h\"\n+#include \"common/array.h\"\n+#include <math.h>\n+\n+namespace Graphics {\n+\n+Common::Point transformPoint(float x, float y, int rotation);\n+Common::Rect rotateRectangle(int x, int y, int width, int height, int rotation, int originX, int originY);\n+\n+struct BlitImage {\n+public:\n+\tBlitImage() { }\n+\n+\tvoid loadData(const Graphics::Surface &surface, uint32 colorKey, bool applyColorKey) {\n+\t\tGraphics::PixelFormat textureFormat(4, 8, 8, 8, 8, 0, 8, 16, 24);\n+\t\t_surface.create(surface.w, surface.h, textureFormat);\n+\t\tGraphics::PixelBuffer buffer(surface.format, (byte *)const_cast<void *>(surface.getPixels()));\n+\t\tGraphics::PixelBuffer dataBuffer(textureFormat, (byte *)const_cast<void *>(_surface.getPixels()));\n+\t\tdataBuffer.copyBuffer(0, 0, surface.w * surface.h, buffer);\n+\t\tif (applyColorKey) {\n+\t\t\tfor (int x = 0;  x < surface.w; x++) {\n+\t\t\t\tfor (int y = 0; y < surface.h; y++) {\n+\t\t\t\t\tuint32 pixel = dataBuffer.getValueAt(y * surface.w + x);\n+\t\t\t\t\tif (pixel == colorKey) {\n+\t\t\t\t\t\tdataBuffer.setPixelAt(y * surface.w + x, 0, 255, 255, 255); // Color keyed pixels become transparent white.\n+\t\t\t\t\t}\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\n+\t\t// Create opaque lines data.\n+\t\t// A line of pixels can not wrap more that one line of the image, since it would break\n+\t\t// blitting of bitmaps with a non-zero x position.\n+\t\tGraphics::PixelBuffer srcBuf = dataBuffer;\n+\t\t_lines.clear();\n+\t\tfor (int y = 0; y < surface.h; y++) {\n+\t\t\tint start = -1;\n+\t\t\tfor (int x = 0; x < surface.w; ++x) {\n+\t\t\t\t// We found a transparent pixel, so save a line from 'start' to the pixel before this.\n+\t\t\t\tuint8 r, g, b, a;\n+\t\t\t\tsrcBuf.getARGBAt(x, a, r, g, b);\n+\t\t\t\tif (a == 0 && start >= 0) {\n+\t\t\t\t\t_lines.push_back(Line(start, y, x - start, srcBuf.getRawBuffer(start)));\n+\t\t\t\t\tstart = -1;\n+\t\t\t\t} else if (a != 0 && start == -1) {\n+\t\t\t\t\tstart = x;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\t// end of the bitmap line. if start is an actual pixel save the line.\n+\t\t\tif (start >= 0) {\n+\t\t\t\t_lines.push_back(Line(start, y, surface.w- start, srcBuf.getRawBuffer(start)));\n+\t\t\t}\n+\t\t\tsrcBuf.shiftBy(surface.w);\n+\t\t}\n+\t}\n+\n+\t~BlitImage() {\n+\t\t_surface.free();\n+\t}\n+\n+\tstruct Line {\n+\t\tint _x;\n+\t\tint _y;\n+\t\tint _length;\n+\t\tbyte *_pixels;\n+\t\tGraphics::PixelBuffer _buf; // This is needed for the conversion.\n+\n+\t\tLine() { }\n+\t\tLine(int x, int y, int length, byte *pixels) : _buf(TinyGL::gl_get_context()->fb->cmode, length * TinyGL::gl_get_context()->fb->cmode.bytesPerPixel, DisposeAfterUse::NO) {\n+\t\t\t_x = x;\n+\t\t\t_y = y;\n+\t\t\t_length = length;\n+\t\t\t// Performing texture to screen conversion.\n+\t\t\tGraphics::PixelFormat textureFormat(4, 8, 8, 8, 8, 0, 8, 16, 24);\n+\t\t\tGraphics::PixelBuffer srcBuf(textureFormat, pixels);\n+\t\t\t_buf.copyBuffer(0, 0, length, srcBuf);\n+\t\t\t_pixels = _buf.getRawBuffer();\n+\t\t}\n+\n+\t\tLine(const Line& other) : _buf(TinyGL::gl_get_context()->fb->cmode, other._length * TinyGL::gl_get_context()->fb->cmode.bytesPerPixel, DisposeAfterUse::NO) {\n+\t\t\t_x = other._x;\n+\t\t\t_y = other._y;\n+\t\t\t_length = other._length;\n+\t\t\t_buf.copyBuffer(0, 0, _length, other._buf);\n+\t\t\t_pixels = _buf.getRawBuffer();\n+\t\t}\n+\n+\t\t~Line() {\n+\t\t\t_buf.free();\n+\t\t}\n+\t};\n+\n+\tFORCEINLINE bool clipBlitImage(TinyGL::GLContext *c, int &srcWidth, int &srcHeight, int &width, int &height, int &dstX, int &dstY, int &clampWidth, int &clampHeight) {\n+\t\tif (srcWidth == 0 || srcHeight == 0) {\n+\t\t\tsrcWidth = _surface.w;\n+\t\t\tsrcHeight = _surface.h;\n+\t\t}\n+\n+\t\tif (width == 0 && height == 0) {\n+\t\t\twidth = srcWidth;\n+\t\t\theight = srcHeight;\n+\t\t}\n+\n+\t\tif (dstX >= c->fb->xsize|| dstY >= c->fb->ysize)\n+\t\t\treturn false;\n+\n+\t\tif (dstX + width > c->fb->xsize)\n+\t\t\tclampWidth = c->fb->xsize - dstX;\n+\t\telse\n+\t\t\tclampWidth = width;\n+\n+\t\tif (dstY + height > c->fb->ysize)\n+\t\t\tclampHeight = c->fb->ysize - dstY;\n+\t\telse\n+\t\t\tclampHeight = height;\n+\n+\t\tif (dstX < 0) \n+\t\t\tdstX = 0;\n+\t\tif (dstY < 0)\n+\t\t\tdstY = 0;\n+\n+\t\treturn true;\n+\t}\n+\n+\ttemplate <bool disableColoring>\n+\tvoid tglBlitRLE(int dstX, int dstY, int srcX, int srcY, int srcWidth, int srcHeight, float aTint, float rTint, float gTint, float bTint);\n+\n+\ttemplate <bool disableBlending, bool disableColoring, bool flipVertical, bool flipHorizontal>\n+\tvoid tglBlitSimple(int dstX, int dstY, int srcX, int srcY, int srcWidth, int srcHeight, float aTint, float rTint, float gTint, float bTint);\n+\n+\ttemplate <bool disableBlending, bool disableColoring, bool flipVertical, bool flipHorizontal>\n+\tvoid tglBlitScale(int dstX, int dstY, int width, int height, int srcX, int srcY, int srcWidth, int srcHeight, float aTint, float rTint, float gTint, float bTint);\n+\n+\ttemplate <bool disableBlending, bool disableColoring, bool flipVertical, bool flipHorizontal>\n+\tvoid tglBlitRotoScale(int dstX, int dstY, int width, int height, int srcX, int srcY, int srcWidth, int srcHeight, int rotation,\n+\t\tint originX, int originY, float aTint, float rTint, float gTint, float bTint);\n+\n+\t//Utility function.\n+\ttemplate <bool disableBlending, bool disableColoring, bool disableTransform, bool flipVertical, bool flipHorizontal>\n+\tFORCEINLINE void tglBlitGeneric(const BlitTransform &transform) {\n+\t\tif (disableTransform) {\n+\t\t\tif (disableBlending && flipVertical == false && flipHorizontal == false) {\n+\t\t\t\ttglBlitRLE<disableColoring>(transform._destinationRectangle.left, transform._destinationRectangle.top,\n+\t\t\t\t\ttransform._sourceRectangle.left, transform._sourceRectangle.top, transform._sourceRectangle.width() , transform._sourceRectangle.height(),\n+\t\t\t\t\ttransform._aTint, transform._rTint, transform._gTint, transform._bTint);\n+\t\t\t} else {\n+\t\t\t\ttglBlitSimple<disableBlending, disableColoring, flipVertical, flipHorizontal>(transform._destinationRectangle.left, transform._destinationRectangle.top,\n+\t\t\t\t\ttransform._sourceRectangle.left, transform._sourceRectangle.top, transform._sourceRectangle.width() , transform._sourceRectangle.height(),\n+\t\t\t\t\ttransform._aTint, transform._rTint, transform._gTint, transform._bTint);\n+\t\t\t}\n+\t\t} else {\n+\t\t\tif (transform._rotation == 0) {\n+\t\t\t\ttglBlitScale<disableBlending, disableColoring, flipVertical, flipHorizontal>(transform._destinationRectangle.left, transform._destinationRectangle.top,\n+\t\t\t\t\ttransform._destinationRectangle.width(), transform._destinationRectangle.height(), transform._sourceRectangle.left, transform._sourceRectangle.top, transform._sourceRectangle.width() , transform._sourceRectangle.height(), transform._aTint, transform._rTint, transform._gTint, transform._bTint);\n+\t\t\t} else {\n+\t\t\t\ttglBlitRotoScale<disableBlending, disableColoring, flipVertical, flipHorizontal>(transform._destinationRectangle.left, transform._destinationRectangle.top,\n+\t\t\t\t\ttransform._destinationRectangle.width(), transform._destinationRectangle.height(), transform._sourceRectangle.left, transform._sourceRectangle.top, transform._sourceRectangle.width() , transform._sourceRectangle.height(), transform._rotation, \n+\t\t\t\t\ttransform._originX, transform._originY, transform._aTint, transform._rTint, transform._gTint, transform._bTint);\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tCommon::Array<Line> _lines;\n+\tGraphics::Surface _surface;\n+};\n+\n+BlitImage *tglGenBlitImage() {\n+\tTinyGL::GLContext *c = TinyGL::gl_get_context();\n+\tBlitImage *image = new BlitImage();\n+\tc->blitImages.push_back(image);\n+\treturn image;\n+}\n+\n+void tglUploadBlitImage(BlitImage *blitImage, const Graphics::Surface& surface, uint32 colorKey, bool applyColorKey) {\n+\tif (blitImage != nullptr) {\n+\t\tblitImage->loadData(surface, colorKey, applyColorKey);\n+\t}\n+}\n+\n+void tglDeleteBlitImage(BlitImage *blitImage) {\n+\tif (blitImage != nullptr) {\n+\t\tTinyGL::GLContext *c = TinyGL::gl_get_context();\n+\t\tfor (uint32 i = 0; i < c->blitImages.size(); i++) {\n+\t\t\tif (c->blitImages[i] == blitImage) {\n+\t\t\t\tc->blitImages.remove_at(i);\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t\tdelete blitImage;\n+\t}\n+}\n+\n+template <bool disableColoring>\n+void BlitImage::tglBlitRLE(int dstX, int dstY, int srcX, int srcY, int srcWidth, int srcHeight, float aTint, float rTint, float gTint, float bTint) {\n+\tTinyGL::GLContext *c = TinyGL::gl_get_context();\n+\n+\tint clampWidth, clampHeight;\n+\tint width = srcWidth, height = srcHeight;\n+\tif (clipBlitImage(c, srcWidth, srcHeight, width, height, dstX, dstY, clampWidth, clampHeight) == false)\n+\t\treturn;\n+\n+\tGraphics::PixelBuffer srcBuf(_surface.format, (byte *)_surface.getPixels());\n+\tsrcBuf.shiftBy(srcX + (srcY * _surface.w));\n+\n+\tGraphics::PixelBuffer dstBuf(c->fb->cmode, c->fb->getPixelBuffer());\n+\tdstBuf.shiftBy(dstY * c->fb->xsize + dstX);\n+\n+\tconst int kBytesPerPixel = 2;\n+\n+\tuint32 lineIndex = 0;\n+\tint maxY = srcY + clampHeight;\n+\tint maxX = srcX + clampWidth;\n+\twhile (lineIndex < _lines.size() && _lines[lineIndex]._y < srcY) {\n+\t\tlineIndex++;\n+\t}\n+\twhile (lineIndex < _lines.size() && _lines[lineIndex]._y < maxY) {\n+\t\tconst BlitImage::Line &l = _lines[lineIndex];\n+\t\tif (l._x < maxX && l._x + l._length > srcX) {\n+\t\t\tint length = l._length;\n+\t\t\tint skipStart = (l._x < srcX) ? (srcX - l._x) : 0;\n+\t\t\tlength -= skipStart;\n+\t\t\tint skipEnd   = (l._x + l._length > maxX) ? (l._x + l._length - maxX) : 0;\n+\t\t\tlength -= skipEnd;\n+\t\t\tif (disableColoring) {\n+\t\t\t\tmemcpy(dstBuf.getRawBuffer((l._y - srcY) * c->fb->xsize + MAX(l._x - srcX, 0)),\n+\t\t\t\t\tl._pixels + skipStart * kBytesPerPixel, length * kBytesPerPixel);\n+\t\t\t} else {\n+\t\t\t\tint xStart = MAX(l._x - srcX, 0);\n+\t\t\t\tfor(int x = xStart; x < xStart + length; x++) {\n+\t\t\t\t\tbyte aDst, rDst, gDst, bDst;\n+\t\t\t\t\tsrcBuf.getARGBAt((l._y - srcY) *c->fb->xsize + x, aDst, rDst, gDst, bDst);\n+\t\t\t\t\tc->fb->writePixel((dstX + x) + (dstY + (l._y - srcY)) * c->fb->xsize, aDst * aTint, rDst * rTint, gDst * gTint, bDst * bTint);\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t\tlineIndex++;\n+\t}\n+}\n+\n+template <bool disableBlending, bool disableColoring, bool flipVertical, bool flipHorizontal>\n+void BlitImage::tglBlitSimple(int dstX, int dstY, int srcX, int srcY, int srcWidth, int srcHeight, float aTint, float rTint, float gTint, float bTint) {\n+\tTinyGL::GLContext *c = TinyGL::gl_get_context();\n+\n+\tint clampWidth, clampHeight;\n+\tint width = srcWidth, height = srcHeight;\n+\tif (clipBlitImage(c, srcWidth, srcHeight, width, height, dstX, dstY, clampWidth, clampHeight) == false)\n+\t\treturn;\n+\n+\tGraphics::PixelBuffer srcBuf(_surface.format, (byte *)_surface.getPixels());\n+\n+\tif (flipVertical) {\n+\t\tsrcBuf.shiftBy(srcX + ((srcY + srcHeight - 1) * _surface.w));\n+\t} else {\n+\t\tsrcBuf.shiftBy(srcX + (srcY * _surface.w));\n+\t}\n+\n+\tGraphics::PixelBuffer dstBuf(c->fb->cmode, c->fb->getPixelBuffer());\n+\n+\tfor (int l = 0; l < clampHeight; l++) {\n+\t\tfor (int r = 0; r < clampWidth; ++r) {\n+\t\t\tbyte aDst, rDst, gDst, bDst;\n+\t\t\tif (flipHorizontal) {\n+\t\t\t\tsrcBuf.getARGBAt(clampWidth - r, aDst, rDst, gDst, bDst);\n+\t\t\t} else {\n+\t\t\t\tsrcBuf.getARGBAt(r, aDst, rDst, gDst, bDst);\n+\t\t\t}\n+\t\t\tif (disableColoring) {\n+\t\t\t\tif (disableBlending && aDst != 0) {\n+\t\t\t\t\tdstBuf.setPixelAt((dstX + r) + (dstY + l) * c->fb->xsize, aDst, rDst, gDst, bDst);\n+\t\t\t\t} else {\n+\t\t\t\t\tc->fb->writePixel((dstX + r) + (dstY + l) * c->fb->xsize, aDst, rDst, gDst, bDst);\n+\t\t\t\t}\n+\t\t\t} else {\n+\t\t\t\tif (disableBlending && aDst * aTint != 0) {\n+\t\t\t\t\tdstBuf.setPixelAt((dstX + r) + (dstY + l) * c->fb->xsize, aDst * aTint, rDst * rTint, gDst * gTint, bDst * bTint);\n+\t\t\t\t} else {\n+\t\t\t\t\tc->fb->writePixel((dstX + r) + (dstY + l) * c->fb->xsize, aDst * aTint, rDst * rTint, gDst * gTint, bDst * bTint);\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t\tif (flipVertical) {\n+\t\t\tsrcBuf.shiftBy(-_surface.w);\n+\t\t} else {\n+\t\t\tsrcBuf.shiftBy(_surface.w);\n+\t\t}\n+\t}\n+}\n+\n+template <bool disableBlending, bool disableColoring, bool flipVertical, bool flipHorizontal>\n+void BlitImage::tglBlitScale(int dstX, int dstY, int width, int height, int srcX, int srcY, int srcWidth, int srcHeight,\n+\t\t\t\t\t float aTint, float rTint, float gTint, float bTint) {\n+\tTinyGL::GLContext *c = TinyGL::gl_get_context();\n+\n+\tint clampWidth, clampHeight;\n+\tif (clipBlitImage(c, srcWidth, srcHeight, width, height, dstX, dstY, clampWidth, clampHeight) == false)\n+\t\treturn;\n+\n+\tGraphics::PixelBuffer srcBuf(_surface.format, (byte *)_surface.getPixels());\n+\tsrcBuf.shiftBy(srcX + (srcY * _surface.w));\n+\n+\tGraphics::PixelBuffer dstBuf(c->fb->cmode, c->fb->getPixelBuffer());\n+\n+\tfor (int l = 0; l < clampHeight; l++) {\n+\t\tfor (int r = 0; r < clampWidth; ++r) {\n+\t\t\tbyte aDst, rDst, gDst, bDst;\n+\t\t\tint xSource, ySource;\n+\t\t\tif (flipVertical) {\n+\t\t\t\tySource = clampHeight - l - 1;\n+\t\t\t} else {\n+\t\t\t\tySource = l;\n+\t\t\t}\n+\n+\t\t\tif (flipHorizontal) {\n+\t\t\t\txSource = clampWidth - r - 1;\n+\t\t\t} else {\n+\t\t\t\txSource = r;\n+\t\t\t}\n+\n+\t\t\tsrcBuf.getARGBAt(((ySource * srcHeight) / height) * _surface.w + ((xSource * srcWidth) / width), aDst, rDst, gDst, bDst);\n+\n+\t\t\tif (disableColoring) {\n+\t\t\t\tif (disableBlending && aDst != 0) {\n+\t\t\t\t\tdstBuf.setPixelAt((dstX + r) + (dstY + l) * c->fb->xsize, aDst, rDst, gDst, bDst);\n+\t\t\t\t} else {\n+\t\t\t\t\tc->fb->writePixel((dstX + r) + (dstY + l) * c->fb->xsize, aDst, rDst, gDst, bDst);\n+\t\t\t\t}\n+\t\t\t} else {\n+\t\t\t\tif (disableBlending && aDst * aTint != 0) {\n+\t\t\t\t\tdstBuf.setPixelAt((dstX + r) + (dstY + l) * c->fb->xsize, aDst * aTint, rDst * rTint, gDst * gTint, bDst * bTint);\n+\t\t\t\t} else {\n+\t\t\t\t\tc->fb->writePixel((dstX + r) + (dstY + l) * c->fb->xsize, aDst * aTint, rDst * rTint, gDst * gTint, bDst * bTint);\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t}\n+}\n+\n+template <bool disableBlending, bool disableColoring, bool flipVertical, bool flipHorizontal>\n+void BlitImage::tglBlitRotoScale(int dstX, int dstY, int width, int height, int srcX, int srcY, int srcWidth, int srcHeight, int rotation,\n+\t\t\t\t\t\t\t int originX, int originY, float aTint, float rTint, float gTint, float bTint) {\n+\tTinyGL::GLContext *c = TinyGL::gl_get_context();\n+\t\n+\tint clampWidth, clampHeight;\n+\tif (clipBlitImage(c, srcWidth, srcHeight, width, height, dstX, dstY, clampWidth, clampHeight) == false)\n+\t\treturn;\n+\t\n+\tGraphics::PixelBuffer srcBuf(_surface.format, (byte *)_surface.getPixels());\n+\tsrcBuf.shiftBy(srcX + (srcY * _surface.w));\n+\t\n+\tGraphics::PixelBuffer dstBuf(c->fb->cmode, c->fb->getPixelBuffer());\n+\t\n+\t// Transform destination rectangle accordingly.\n+\tCommon::Rect destinationRectangle = rotateRectangle(dstX, dstY, width, height, rotation, originX, originY);\n+\t\n+\tif (dstX + destinationRectangle.width() > c->fb->xsize)\n+\t\tclampWidth = c->fb->xsize - dstX;\n+\telse\n+\t\tclampWidth = destinationRectangle.width();\n+\tif (dstY + destinationRectangle.height() > c->fb->ysize)\n+\t\tclampHeight = c->fb->ysize - dstY;\n+\telse\n+\t\tclampHeight = destinationRectangle.height();\n+\t\n+\tuint32 invAngle = 360 - (rotation % 360);\n+\tfloat invCos = cos(invAngle * M_PI / 180.0f);\n+\tfloat invSin = sin(invAngle * M_PI / 180.0f);\n+\t\n+\tint icosx = (int)(invCos * (65536.0f * srcWidth / width));\n+\tint isinx = (int)(invSin * (65536.0f * srcWidth / width));\n+\tint icosy = (int)(invCos * (65536.0f * srcHeight / height));\n+\tint isiny = (int)(invSin * (65536.0f * srcHeight / height));\n+\t\n+\tint xd = (srcX + originX) << 16;\n+\tint yd = (srcY + originY) << 16;\n+\tint cx = originX * ((float)width / srcWidth);\n+\tint cy = originY * ((float)height / srcHeight);\n+\t\n+\tint ax = -icosx * cx;\n+\tint ay = -isiny * cx;\n+\tint sw = width - 1;\n+\tint sh = height - 1;\n+\t\n+\tfor (int l = 0; l < clampHeight; l++) {\n+\t\tint t = cy - l;\n+\t\tint sdx = ax + (isinx * t) + xd;\n+\t\tint sdy = ay - (icosy * t) + yd;\n+\t\tfor (int r = 0; r < clampWidth; ++r) {\n+\t\t\tbyte aDst, rDst, gDst, bDst;\n+\t\t\t\n+\t\t\tint dx = (sdx >> 16);\n+\t\t\tint dy = (sdy >> 16);\n+\t\t\t\n+\t\t\tif (flipHorizontal)\n+\t\t\t\tdx = sw - dx;\n+\t\t\tif (flipVertical)\n+\t\t\t\tdy = sh - dy;\n+\t\t\t\n+\t\t\tif ((dx >= 0) && (dy >= 0) && (dx < srcWidth) && (dy < srcHeight)) {\n+\t\t\t\tsrcBuf.getARGBAt(dy * _surface.w + dx, aDst, rDst, gDst, bDst);\n+\t\t\t\tif (disableColoring) {\n+\t\t\t\t\tif (disableBlending && aDst != 0) {\n+\t\t\t\t\t\tdstBuf.setPixelAt((dstX + r) + (dstY + l) * c->fb->xsize, aDst, rDst, gDst, bDst);\n+\t\t\t\t\t} else {\n+\t\t\t\t\t\tc->fb->writePixel((dstX + r) + (dstY + l) * c->fb->xsize, aDst, rDst, gDst, bDst);\n+\t\t\t\t\t}\n+\t\t\t\t} else {\n+\t\t\t\t\tif (disableBlending && aDst * aTint != 0) {\n+\t\t\t\t\t\tdstBuf.setPixelAt((dstX + r) + (dstY + l) * c->fb->xsize, aDst * aTint, rDst * rTint, gDst * gTint, bDst * bTint);\n+\t\t\t\t\t} else {\n+\t\t\t\t\t\tc->fb->writePixel((dstX + r) + (dstY + l) * c->fb->xsize, aDst * aTint, rDst * rTint, gDst * gTint, bDst * bTint);\n+\t\t\t\t\t}\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tsdx += icosx;\n+\t\t\tsdy += isiny;\n+\t\t}\n+\t}\n+}\n+\n+void tglBlit(BlitImage *blitImage, int x, int y) {\n+\tBlitTransform transform(x, y);\n+\ttglBlit(blitImage, transform);\n+}\n+\n+void tglBlit(BlitImage *blitImage, const BlitTransform &transform) {\n+\tTinyGL::GLContext *c =TinyGL::gl_get_context();\n+\tbool disableColor = transform._aTint == 1.0f && transform._bTint == 1.0f && transform._gTint == 1.0f && transform._rTint == 1.0f;\n+\tbool disableTransform = transform._destinationRectangle.width() == 0 && transform._destinationRectangle.height() == 0 && transform._rotation == 0;\n+\tbool disableBlend = c->enableBlend == false;\n+\tif (transform._flipHorizontally == false && transform._flipVertically == false) {\n+\t\tif (disableColor && disableTransform && disableBlend) {\n+\t\t\tblitImage->tglBlitGeneric<true, true, true, false, false>(transform);\n+\t\t} else if (disableColor && disableTransform) {\n+\t\t\tblitImage->tglBlitGeneric<false, true, true, false, false>(transform);\n+\t\t} else if (disableTransform) {\n+\t\t\tblitImage->tglBlitGeneric<false, false, true, false, false>(transform);\n+\t\t} else {\n+\t\t\tblitImage->tglBlitGeneric<false, false, false, false, false>(transform);\n+\t\t}\n+\t} else if (transform._flipHorizontally == false) {\n+\t\tif (disableColor && disableTransform && disableBlend) {\n+\t\t\tblitImage->tglBlitGeneric<true, true, true, true, false>(transform);\n+\t\t} else if (disableColor && disableTransform) {\n+\t\t\tblitImage->tglBlitGeneric<false, true, true, true, false>(transform);\n+\t\t} else if (disableTransform) {\n+\t\t\tblitImage->tglBlitGeneric<false, false, true, true, false>(transform);\n+\t\t} else {\n+\t\t\tblitImage->tglBlitGeneric<false, false, false, true, false>(transform);\n+\t\t}\n+\t} else {\n+\t\tif (disableColor && disableTransform && disableBlend) {\n+\t\t\tblitImage->tglBlitGeneric<true, true, true, false, true>(transform);\n+\t\t} else if (disableColor && disableTransform) {\n+\t\t\tblitImage->tglBlitGeneric<false, true, true, false, true>(transform);\n+\t\t} else if (disableTransform) {\n+\t\t\tblitImage->tglBlitGeneric<false, false, true, false, true>(transform);\n+\t\t} else {\n+\t\t\tblitImage->tglBlitGeneric<false, false, false, false, true>(transform);\n+\t\t}\n+\t}\n+}\n+\n+void tglBlitNoBlend(BlitImage *blitImage, const BlitTransform &transform) {\n+\tif (transform._flipHorizontally == false && transform._flipVertically == false) {\n+\t\tblitImage->tglBlitGeneric<true, false, false, false, false>(transform);\n+\t} else if(transform._flipHorizontally == false) {\n+\t\tblitImage->tglBlitGeneric<true, false, false, true, false>(transform);\n+\t} else {\n+\t\tblitImage->tglBlitGeneric<true, false, false, false, true>(transform);\n+\t}\n+}\n+\n+void tglBlitFast(BlitImage *blitImage, int x, int y) {\n+\tBlitTransform transform(x, y);\n+\tblitImage->tglBlitGeneric<true, true, true, false, false>(transform);\n+}\n+\n+Common::Point transformPoint(float x, float y, int rotation) {\n+\tfloat rotateRad = rotation * M_PI / 180.0f;\n+\tCommon::Point newPoint;\n+\tnewPoint.x = x * cos(rotateRad) - y * sin(rotateRad);\n+\tnewPoint.y = x * sin(rotateRad) + y * cos(rotateRad);\n+\treturn newPoint;\n+}\n+\n+Common::Rect rotateRectangle(int x, int y, int width, int height, int rotation, int originX, int originY) {\n+\tCommon::Point nw, ne, sw, se;\n+\tnw = transformPoint(x - originX, y - originY, rotation);\n+\tne = transformPoint(x + width - originX, y - originY, rotation);\n+\tsw = transformPoint(x + width - originX, y + height -\t originY, rotation);","path":"graphics/tinygl/zblit.cpp","position":492,"original_position":492,"commit_id":"fc96ada123049a0b1f101fe2df178e69bb906594","original_commit_id":"fc96ada123049a0b1f101fe2df178e69bb906594","user":{"login":"aquadran","id":406926,"avatar_url":"https://avatars.githubusercontent.com/u/406926?","gravatar_id":"fec2ac83e5f5de5e96b20a2d665a2c18","url":"https://api.github.com/users/aquadran","html_url":"https://github.com/aquadran","followers_url":"https://api.github.com/users/aquadran/followers","following_url":"https://api.github.com/users/aquadran/following{/other_user}","gists_url":"https://api.github.com/users/aquadran/gists{/gist_id}","starred_url":"https://api.github.com/users/aquadran/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aquadran/subscriptions","organizations_url":"https://api.github.com/users/aquadran/orgs","repos_url":"https://api.github.com/users/aquadran/repos","events_url":"https://api.github.com/users/aquadran/events{/privacy}","received_events_url":"https://api.github.com/users/aquadran/received_events","type":"User","site_admin":false},"body":"remove no needed additional spaces","created_at":"2014-07-16T19:08:32Z","updated_at":"2014-07-16T19:08:32Z","html_url":"https://github.com/residualvm/residualvm/pull/966#discussion_r15020499","pull_request_url":"https://api.github.com/repos/residualvm/residualvm/pulls/966","_links":{"self":{"href":"https://api.github.com/repos/residualvm/residualvm/pulls/comments/15020499"},"html":{"href":"https://github.com/residualvm/residualvm/pull/966#discussion_r15020499"},"pull_request":{"href":"https://api.github.com/repos/residualvm/residualvm/pulls/966"}}},"pull_request":{"url":"https://api.github.com/repos/residualvm/residualvm/pulls/966","id":18444285,"html_url":"https://github.com/residualvm/residualvm/pull/966","diff_url":"https://github.com/residualvm/residualvm/pull/966.diff","patch_url":"https://github.com/residualvm/residualvm/pull/966.patch","issue_url":"https://api.github.com/repos/residualvm/residualvm/issues/966","number":966,"state":"open","title":"TinyGL 2D Blitting API","user":{"login":"subr3v","id":5153412,"avatar_url":"https://avatars.githubusercontent.com/u/5153412?","gravatar_id":"76c3bbee0e912b0afd37d1d3c7ffbcdc","url":"https://api.github.com/users/subr3v","html_url":"https://github.com/subr3v","followers_url":"https://api.github.com/users/subr3v/followers","following_url":"https://api.github.com/users/subr3v/following{/other_user}","gists_url":"https://api.github.com/users/subr3v/gists{/gist_id}","starred_url":"https://api.github.com/users/subr3v/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/subr3v/subscriptions","organizations_url":"https://api.github.com/users/subr3v/orgs","repos_url":"https://api.github.com/users/subr3v/repos","events_url":"https://api.github.com/users/subr3v/events{/privacy}","received_events_url":"https://api.github.com/users/subr3v/received_events","type":"User","site_admin":false},"body":"This PR contains an implementation of a common blitting API for TinyGL, the API supports the following features:\r\n- Alpha/Additive/Subtractive Blending\r\n- Fast Binary Transparency\r\n- Sprite Tinting\r\n- Rotation\r\n- Scaling","created_at":"2014-07-16T00:44:44Z","updated_at":"2014-07-16T19:08:32Z","closed_at":null,"merged_at":null,"merge_commit_sha":"281d28155bf3ab6998b6f2af77178e890df5905b","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/residualvm/residualvm/pulls/966/commits","review_comments_url":"https://api.github.com/repos/residualvm/residualvm/pulls/966/comments","review_comment_url":"https://api.github.com/repos/residualvm/residualvm/pulls/comments/{number}","comments_url":"https://api.github.com/repos/residualvm/residualvm/issues/966/comments","statuses_url":"https://api.github.com/repos/residualvm/residualvm/statuses/fc96ada123049a0b1f101fe2df178e69bb906594","head":{"label":"subr3v:tinygl-blit-final","ref":"tinygl-blit-final","sha":"fc96ada123049a0b1f101fe2df178e69bb906594","user":{"login":"subr3v","id":5153412,"avatar_url":"https://avatars.githubusercontent.com/u/5153412?","gravatar_id":"76c3bbee0e912b0afd37d1d3c7ffbcdc","url":"https://api.github.com/users/subr3v","html_url":"https://github.com/subr3v","followers_url":"https://api.github.com/users/subr3v/followers","following_url":"https://api.github.com/users/subr3v/following{/other_user}","gists_url":"https://api.github.com/users/subr3v/gists{/gist_id}","starred_url":"https://api.github.com/users/subr3v/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/subr3v/subscriptions","organizations_url":"https://api.github.com/users/subr3v/orgs","repos_url":"https://api.github.com/users/subr3v/repos","events_url":"https://api.github.com/users/subr3v/events{/privacy}","received_events_url":"https://api.github.com/users/subr3v/received_events","type":"User","site_admin":false},"repo":{"id":19983316,"name":"residualvm","full_name":"subr3v/residualvm","owner":{"login":"subr3v","id":5153412,"avatar_url":"https://avatars.githubusercontent.com/u/5153412?","gravatar_id":"76c3bbee0e912b0afd37d1d3c7ffbcdc","url":"https://api.github.com/users/subr3v","html_url":"https://github.com/subr3v","followers_url":"https://api.github.com/users/subr3v/followers","following_url":"https://api.github.com/users/subr3v/following{/other_user}","gists_url":"https://api.github.com/users/subr3v/gists{/gist_id}","starred_url":"https://api.github.com/users/subr3v/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/subr3v/subscriptions","organizations_url":"https://api.github.com/users/subr3v/orgs","repos_url":"https://api.github.com/users/subr3v/repos","events_url":"https://api.github.com/users/subr3v/events{/privacy}","received_events_url":"https://api.github.com/users/subr3v/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/subr3v/residualvm","description":"ResidualVM main repository","fork":true,"url":"https://api.github.com/repos/subr3v/residualvm","forks_url":"https://api.github.com/repos/subr3v/residualvm/forks","keys_url":"https://api.github.com/repos/subr3v/residualvm/keys{/key_id}","collaborators_url":"https://api.github.com/repos/subr3v/residualvm/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/subr3v/residualvm/teams","hooks_url":"https://api.github.com/repos/subr3v/residualvm/hooks","issue_events_url":"https://api.github.com/repos/subr3v/residualvm/issues/events{/number}","events_url":"https://api.github.com/repos/subr3v/residualvm/events","assignees_url":"https://api.github.com/repos/subr3v/residualvm/assignees{/user}","branches_url":"https://api.github.com/repos/subr3v/residualvm/branches{/branch}","tags_url":"https://api.github.com/repos/subr3v/residualvm/tags","blobs_url":"https://api.github.com/repos/subr3v/residualvm/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/subr3v/residualvm/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/subr3v/residualvm/git/refs{/sha}","trees_url":"https://api.github.com/repos/subr3v/residualvm/git/trees{/sha}","statuses_url":"https://api.github.com/repos/subr3v/residualvm/statuses/{sha}","languages_url":"https://api.github.com/repos/subr3v/residualvm/languages","stargazers_url":"https://api.github.com/repos/subr3v/residualvm/stargazers","contributors_url":"https://api.github.com/repos/subr3v/residualvm/contributors","subscribers_url":"https://api.github.com/repos/subr3v/residualvm/subscribers","subscription_url":"https://api.github.com/repos/subr3v/residualvm/subscription","commits_url":"https://api.github.com/repos/subr3v/residualvm/commits{/sha}","git_commits_url":"https://api.github.com/repos/subr3v/residualvm/git/commits{/sha}","comments_url":"https://api.github.com/repos/subr3v/residualvm/comments{/number}","issue_comment_url":"https://api.github.com/repos/subr3v/residualvm/issues/comments/{number}","contents_url":"https://api.github.com/repos/subr3v/residualvm/contents/{+path}","compare_url":"https://api.github.com/repos/subr3v/residualvm/compare/{base}...{head}","merges_url":"https://api.github.com/repos/subr3v/residualvm/merges","archive_url":"https://api.github.com/repos/subr3v/residualvm/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/subr3v/residualvm/downloads","issues_url":"https://api.github.com/repos/subr3v/residualvm/issues{/number}","pulls_url":"https://api.github.com/repos/subr3v/residualvm/pulls{/number}","milestones_url":"https://api.github.com/repos/subr3v/residualvm/milestones{/number}","notifications_url":"https://api.github.com/repos/subr3v/residualvm/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/subr3v/residualvm/labels{/name}","releases_url":"https://api.github.com/repos/subr3v/residualvm/releases{/id}","created_at":"2014-05-20T14:07:24Z","updated_at":"2014-06-28T16:54:22Z","pushed_at":"2014-07-16T14:51:36Z","git_url":"git://github.com/subr3v/residualvm.git","ssh_url":"git@github.com:subr3v/residualvm.git","clone_url":"https://github.com/subr3v/residualvm.git","svn_url":"https://github.com/subr3v/residualvm","homepage":"http://residualvm.org","size":19983,"stargazers_count":0,"watchers_count":0,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"residualvm:master","ref":"master","sha":"81745bfe6202a26f0469d5f9be4db3fd0a9e4277","user":{"login":"residualvm","id":679821,"avatar_url":"https://avatars.githubusercontent.com/u/679821?","gravatar_id":"7761a5514fdb424dc90679c290363355","url":"https://api.github.com/users/residualvm","html_url":"https://github.com/residualvm","followers_url":"https://api.github.com/users/residualvm/followers","following_url":"https://api.github.com/users/residualvm/following{/other_user}","gists_url":"https://api.github.com/users/residualvm/gists{/gist_id}","starred_url":"https://api.github.com/users/residualvm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/residualvm/subscriptions","organizations_url":"https://api.github.com/users/residualvm/orgs","repos_url":"https://api.github.com/users/residualvm/repos","events_url":"https://api.github.com/users/residualvm/events{/privacy}","received_events_url":"https://api.github.com/users/residualvm/received_events","type":"Organization","site_admin":false},"repo":{"id":1503443,"name":"residualvm","full_name":"residualvm/residualvm","owner":{"login":"residualvm","id":679821,"avatar_url":"https://avatars.githubusercontent.com/u/679821?","gravatar_id":"7761a5514fdb424dc90679c290363355","url":"https://api.github.com/users/residualvm","html_url":"https://github.com/residualvm","followers_url":"https://api.github.com/users/residualvm/followers","following_url":"https://api.github.com/users/residualvm/following{/other_user}","gists_url":"https://api.github.com/users/residualvm/gists{/gist_id}","starred_url":"https://api.github.com/users/residualvm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/residualvm/subscriptions","organizations_url":"https://api.github.com/users/residualvm/orgs","repos_url":"https://api.github.com/users/residualvm/repos","events_url":"https://api.github.com/users/residualvm/events{/privacy}","received_events_url":"https://api.github.com/users/residualvm/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/residualvm/residualvm","description":"ResidualVM main repository","fork":false,"url":"https://api.github.com/repos/residualvm/residualvm","forks_url":"https://api.github.com/repos/residualvm/residualvm/forks","keys_url":"https://api.github.com/repos/residualvm/residualvm/keys{/key_id}","collaborators_url":"https://api.github.com/repos/residualvm/residualvm/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/residualvm/residualvm/teams","hooks_url":"https://api.github.com/repos/residualvm/residualvm/hooks","issue_events_url":"https://api.github.com/repos/residualvm/residualvm/issues/events{/number}","events_url":"https://api.github.com/repos/residualvm/residualvm/events","assignees_url":"https://api.github.com/repos/residualvm/residualvm/assignees{/user}","branches_url":"https://api.github.com/repos/residualvm/residualvm/branches{/branch}","tags_url":"https://api.github.com/repos/residualvm/residualvm/tags","blobs_url":"https://api.github.com/repos/residualvm/residualvm/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/residualvm/residualvm/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/residualvm/residualvm/git/refs{/sha}","trees_url":"https://api.github.com/repos/residualvm/residualvm/git/trees{/sha}","statuses_url":"https://api.github.com/repos/residualvm/residualvm/statuses/{sha}","languages_url":"https://api.github.com/repos/residualvm/residualvm/languages","stargazers_url":"https://api.github.com/repos/residualvm/residualvm/stargazers","contributors_url":"https://api.github.com/repos/residualvm/residualvm/contributors","subscribers_url":"https://api.github.com/repos/residualvm/residualvm/subscribers","subscription_url":"https://api.github.com/repos/residualvm/residualvm/subscription","commits_url":"https://api.github.com/repos/residualvm/residualvm/commits{/sha}","git_commits_url":"https://api.github.com/repos/residualvm/residualvm/git/commits{/sha}","comments_url":"https://api.github.com/repos/residualvm/residualvm/comments{/number}","issue_comment_url":"https://api.github.com/repos/residualvm/residualvm/issues/comments/{number}","contents_url":"https://api.github.com/repos/residualvm/residualvm/contents/{+path}","compare_url":"https://api.github.com/repos/residualvm/residualvm/compare/{base}...{head}","merges_url":"https://api.github.com/repos/residualvm/residualvm/merges","archive_url":"https://api.github.com/repos/residualvm/residualvm/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/residualvm/residualvm/downloads","issues_url":"https://api.github.com/repos/residualvm/residualvm/issues{/number}","pulls_url":"https://api.github.com/repos/residualvm/residualvm/pulls{/number}","milestones_url":"https://api.github.com/repos/residualvm/residualvm/milestones{/number}","notifications_url":"https://api.github.com/repos/residualvm/residualvm/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/residualvm/residualvm/labels{/name}","releases_url":"https://api.github.com/repos/residualvm/residualvm/releases{/id}","created_at":"2011-03-20T15:50:51Z","updated_at":"2014-07-04T23:25:12Z","pushed_at":"2014-07-15T18:49:25Z","git_url":"git://github.com/residualvm/residualvm.git","ssh_url":"git@github.com:residualvm/residualvm.git","clone_url":"https://github.com/residualvm/residualvm.git","svn_url":"https://github.com/residualvm/residualvm","homepage":"http://residualvm.org","size":27994,"stargazers_count":143,"watchers_count":143,"language":"C++","has_issues":true,"has_downloads":true,"has_wiki":false,"forks_count":61,"mirror_url":null,"open_issues_count":107,"forks":61,"open_issues":107,"watchers":143,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/residualvm/residualvm/pulls/966"},"html":{"href":"https://github.com/residualvm/residualvm/pull/966"},"issue":{"href":"https://api.github.com/repos/residualvm/residualvm/issues/966"},"comments":{"href":"https://api.github.com/repos/residualvm/residualvm/issues/966/comments"},"review_comments":{"href":"https://api.github.com/repos/residualvm/residualvm/pulls/966/comments"},"review_comment":{"href":"https://api.github.com/repos/residualvm/residualvm/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/residualvm/residualvm/pulls/966/commits"},"statuses":{"href":"https://api.github.com/repos/residualvm/residualvm/statuses/fc96ada123049a0b1f101fe2df178e69bb906594"}}}}