2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
5 // Licensed under the Flora License, Version 1.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://floralicense.org/license/
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an AS IS BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
19 * @file FGrp_EffectRotate.cpp
20 * @brief This is the header file for internal utility class.
28 #include <unique_ptr.h>
30 #include <FBaseSysLog.h>
32 #include "FGrp_EffectFunc.h"
33 #include "FGrp_Effect.h"
34 #include "../util/FGrp_UtilType.h"
36 using namespace Tizen::Graphics;
38 ////////////////////////////////////////////////////////////////////////////////
42 // _RealDataType as a floating point
43 typedef float _RealDataType;
45 // _RealDataType as a fixed point
46 typedef long _RealDataType;
49 ////////////////////////////////////////////////////////////////////////////////
81 MultiplySmall(T first, T second)
88 MultiplyBig(T first, T second)
95 DivideSmall(T first, T second)
100 template <typename T>
102 DivideBig(T first, T second)
107 template <typename T>
109 Divide3(T first, T second, T third)
114 template <typename T>
121 template <typename T>
128 template <typename T>
135 } // namespace _RealNumber
137 // specialization for float type
138 namespace _RealNumber
140 const float _FLOAT_PI = 3.141592f;
144 Assign<float>(float f)
151 AssignShift<float>(int i)
158 CastInt<float>(float i)
160 return int((i > 0.0f) ? (i + 0.5f) : (i - 0.5f));
165 MultiplySmall<float>(float first, float second)
167 return first * second;
172 MultiplyBig<float>(float first, float second)
174 return first * second;
179 DivideSmall<float>(float first, float second)
181 return first / second;
186 DivideBig<float>(float first, float second)
188 return first / second;
193 Divide3<float>(float first, float second, float third)
195 return first / second / third;
200 Dispatch<float>(float i)
207 Sin<float>(float degree)
209 return float(sinf(degree * _FLOAT_PI / 180.0f));
214 Cos<float>(float degree)
216 return float(cosf(degree * _FLOAT_PI / 180.0f));
219 } // namespace _RealNumber
221 // specialization for long type
222 namespace _RealNumber
224 const int _FPFLOAT_SHIFT = 10;
225 const int _FPFLOAT_SHIFT_HIGH = 5;
226 const int _FPFLOAT_SHIFT_LOW = 5;
227 const int _FPFLOAT_MUL_VALUE = 1024;
231 Assign<long>(float f)
233 return long((f) * _FPFLOAT_MUL_VALUE);
238 AssignShift<long>(int i)
240 return long((i) << _FPFLOAT_SHIFT);
245 CastInt<long>(long i)
247 return (i + (1 << (_FPFLOAT_SHIFT - 1))) >> _FPFLOAT_SHIFT;
252 MultiplySmall<long>(long first, long second)
254 return (first * second) >> _FPFLOAT_SHIFT;
259 MultiplyBig<long>(long first, long second)
261 return (first >> _FPFLOAT_SHIFT_HIGH) * (second >> _FPFLOAT_SHIFT_LOW);
266 DivideSmall<long>(long first, long second)
268 return (first << _FPFLOAT_SHIFT) / second;
273 DivideBig<long>(long first, long second)
275 return (first << _FPFLOAT_SHIFT_HIGH) / (second >> _FPFLOAT_SHIFT_LOW);
280 Divide3<long>(long first, long second, long third)
282 return DivideSmall<long>(DivideBig<long>(first, second), third);
287 Dispatch<long>(long i)
289 return float(i) / float(_FPFLOAT_MUL_VALUE);
292 int SinX16(int degree);
293 int CosX16(int degree);
297 Sin<long>(long degree)
299 // 16 was value that we shifted in a sine table
300 int n = _FPFLOAT_SHIFT - 16;
302 return (n >= 0) ? (SinX16(CastInt<long>(degree)) << n) : (SinX16(CastInt<long>(degree)) >> (-n));
307 Cos<long>(long degree)
309 // 16 was value that we shifted in a sine table
310 int n = _RealNumber::_FPFLOAT_SHIFT - 16;
312 return (n >= 0) ? (CosX16(CastInt<long>(degree)) << n) : (CosX16(CastInt<long>(degree)) >> (-n));
315 const int SIN_TABLE_X16[] = // 91 items
413 if ((degree %= 360) < 0)
421 return SIN_TABLE_X16[degree];
423 return SIN_TABLE_X16[180 - degree];
425 return -SIN_TABLE_X16[degree - 180];
427 return -SIN_TABLE_X16[360 - degree];
434 return SinX16(degree + 90);
437 } // namespace _RealNumber
444 return (a >= 0) ? a : -a;
451 return (a >= 0) ? ((a > 0) ? 1 : 0) : -1;
465 _Point(int _x, int _y)
473 _DrawVirtualLineToArray(int x1, int y1, int x2, int y2, long yLineArrayLeft[], long yLineArrayRight[], _Point minPos,
476 _Point delta(_Abs(x2 - x1), _Abs(y2 - y1));
477 _Point increase(_Sign(x2 - x1), _Sign(y2 - y1));
480 int distance = _Util::Max(delta.x, delta.y);
482 for (int i = 0; i <= distance; i++)
487 if (pos.x > distance)
493 if (pos.y > distance)
499 if ((y1 < minPos.y) || (y1 > maxPos.y))
504 if (x1 < yLineArrayLeft[y1 - minPos.y])
506 yLineArrayLeft[y1 - minPos.y] = (x1 < minPos.x) ? minPos.x : ((x1 > maxPos.x) ? maxPos.x : x1);
509 if (x1 > yLineArrayRight[y1 - minPos.y])
511 yLineArrayRight[y1 - minPos.y] = (x1 > maxPos.x) ? maxPos.x : ((x1 < minPos.x) ? minPos.x : x1);
516 template<typename DestPixel, typename SourPixel>
518 _RotateImage(_Util::Pixmap& dstImage, long x, long y, const _Util::Pixmap& srcImage, long width, long height,
519 const _Effect::RotateDesc& rotateDesc, DestPixel opacity,
522 _Util::Bounds<int> clipRect = { 0, 0, dstImage.width, dstImage.height };
524 long angle = rotateDesc.angle;
526 // 'angle' will be between 1 and 360
544 // the converted angle for the input angle becomes as follows
555 // if (angle == 0) then draw bitmap normally, but...
557 _RealDataType sinVal = _RealNumber::Sin(_RealNumber::AssignShift<_RealDataType>(angle));
558 _RealDataType cosVal = _RealNumber::Cos(_RealNumber::AssignShift<_RealDataType>(angle));
564 _RealDataType wSinP = sinVal * (-rotateDesc.xOffset);
565 _RealDataType wCosP = cosVal * (-rotateDesc.xOffset);
566 _RealDataType hSinP = sinVal * (-rotateDesc.yOffset);
567 _RealDataType hCosP = cosVal * (-rotateDesc.yOffset);
568 _RealDataType wSinM = sinVal * (width - rotateDesc.xOffset);
569 _RealDataType wCosM = cosVal * (width - rotateDesc.xOffset);
570 _RealDataType hSinM = sinVal * (height - rotateDesc.yOffset);
571 _RealDataType hCosM = cosVal * (height - rotateDesc.yOffset);
573 vertex[0].x = x - _RealNumber::CastInt((wCosM) - (hSinP));
574 vertex[1].x = x - _RealNumber::CastInt((wCosP) - (hSinP));
575 vertex[2].x = x - _RealNumber::CastInt((wCosM) - (hSinM));
576 vertex[3].x = x - _RealNumber::CastInt((wCosP) - (hSinM));
578 vertex[0].y = y - _RealNumber::CastInt((wSinM) + (hCosP));
579 vertex[1].y = y - _RealNumber::CastInt((wSinP) + (hCosP));
580 vertex[2].y = y - _RealNumber::CastInt((wSinM) + (hCosM));
581 vertex[3].y = y - _RealNumber::CastInt((wSinP) + (hCosM));
583 /* meaning of 'vertex', if 'angle' is 180
595 if 'xOffset' and 'yOffset' are 0,
608 // find a maximum value and minimum value of rotated image on y-axis
610 int right = dstImage.width - 0;
611 int top = vertex[3].y;
612 int bottom = vertex[3].y;
614 // find a maximum value and minimum value for all vertices
615 top = _Util::Min(top, vertex[2].y);
616 bottom = _Util::Max(bottom, vertex[2].y);
617 top = _Util::Min(top, vertex[1].y);
618 bottom = _Util::Max(bottom, vertex[1].y);
619 top = _Util::Min(top, vertex[0].y);
620 bottom = _Util::Max(bottom, vertex[0].y);
623 top = _Util::Max(top, clipRect.y1);
624 bottom = _Util::Min(bottom, clipRect.y2 - 0);
626 // number of pixels for vertical region
627 int numVerticalPixel = bottom - top + 1;
630 if (numVerticalPixel <= 0)
635 std::unique_ptr<long[]> tempLeftVertices(new (std::nothrow) long[numVerticalPixel]);
636 std::unique_ptr<long[]> tempRightVertices(new (std::nothrow) long[numVerticalPixel]);
638 SysTryReturn(NID_GRP, tempLeftVertices && tempRightVertices, false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
640 // left <- max value of 'x', right <- min value of 'x'
641 memset(tempRightVertices.get(), 0x80, numVerticalPixel * sizeof(long));
642 memset(tempLeftVertices.get(), 0x7F, numVerticalPixel * sizeof(long));
644 // prepare to draw horizontal lines. 4 lines as input
645 _DrawVirtualLineToArray(vertex[0].x, vertex[0].y, vertex[1].x, vertex[1].y, tempLeftVertices.get(),
646 tempRightVertices.get(), _Point(left, top), _Point(right, bottom));
647 _DrawVirtualLineToArray(vertex[0].x, vertex[0].y, vertex[2].x, vertex[2].y, tempLeftVertices.get(),
648 tempRightVertices.get(), _Point(left, top), _Point(right, bottom));
649 _DrawVirtualLineToArray(vertex[1].x, vertex[1].y, vertex[3].x, vertex[3].y, tempLeftVertices.get(),
650 tempRightVertices.get(), _Point(left, top), _Point(right, bottom));
651 _DrawVirtualLineToArray(vertex[3].x, vertex[3].y, vertex[2].x, vertex[2].y, tempLeftVertices.get(),
652 tempRightVertices.get(), _Point(left, top), _Point(right, bottom));
654 // memory buffer pointer & pitch of source
655 SourPixel* pSour = (SourPixel*) (srcImage.pBitmap);
656 int srcPitch = srcImage.bytesPerLine * 8 / srcImage.depth;
658 // memory buffer pointer & pitch of destination
659 DestPixel* pDest = (DestPixel*) dstImage.pBitmap;
660 int dstPitch = dstImage.bytesPerLine * 8 / dstImage.depth;
663 _RealDataType xScale = _RealNumber::DivideBig(_RealNumber::AssignShift<_RealDataType>(srcImage.width), _RealNumber::AssignShift<_RealDataType>(width));
664 _RealDataType yScale = _RealNumber::DivideBig(_RealNumber::AssignShift<_RealDataType>(srcImage.height), _RealNumber::AssignShift<_RealDataType>(height));
666 // for clippping of source image
667 int maxSrcWidth = srcImage.width - 1;
668 int maxSrcHeight = srcImage.height - 1;
670 // current position to the set of vertical vertices
671 long* pLeftVertices = tempLeftVertices.get();
672 long* pRightVertices = tempRightVertices.get();
674 // draw horizontal linetop from top to bottom
675 for (long scanline = top; scanline < bottom; ++scanline)
677 // out-of-clip test of 'y'
678 if (scanline >= clipRect.y2)
683 // skipping of 'y' for out-of-clip
684 if (scanline < clipRect.y1)
692 long leftVertex = *pLeftVertices++;
693 long rightVertex = *pRightVertices++;
694 long distVertex = rightVertex - leftVertex;
696 int srcLeftVertexX = _RealNumber::CastInt(-(cosVal * (leftVertex - x)) - (sinVal * (scanline - y)));
697 int srcLeftVertexY = _RealNumber::CastInt((sinVal * (leftVertex - x)) - (cosVal * (scanline - y)));
699 int srcRightVertexX = _RealNumber::CastInt(-(cosVal * (rightVertex - x)) - (sinVal * (scanline - y)));
700 int srcRightVertexY = _RealNumber::CastInt((sinVal * (rightVertex - x)) - (cosVal * (scanline - y)));
702 _Point delta((srcRightVertexX - srcLeftVertexX), (srcRightVertexY - srcLeftVertexY));
708 _RealDataType rdx = delta.x * xScale / distVertex;
709 _RealDataType rdy = delta.y * yScale / distVertex;
711 int pixel = leftVertex - 1;
712 int count = distVertex; // + 1;
715 _RealDataType sx = srcLeftVertexX * xScale + _RealNumber::AssignShift<_RealDataType>(rotateDesc.xOffset);
716 _RealDataType sy = srcLeftVertexY * yScale + _RealNumber::AssignShift<_RealDataType>(rotateDesc.yOffset);
721 if (srcImage.enableColorKey)
723 SourPixel colorKey = (SourPixel) srcImage.colorKey;
733 rsx = _RealNumber::CastInt(sx + _RealNumber::Assign<_RealDataType>(0.49f));
734 rsy = _RealNumber::CastInt(sy + _RealNumber::Assign<_RealDataType>(0.49f));
736 rsx = _Util::Max(rsx, 0);
737 rsx = _Util::Min(rsx, maxSrcWidth);
739 rsy = _Util::Max(rsy, 0);
740 rsy = _Util::Min(rsy, maxSrcHeight);
742 if (clipRect.IsInsideX(pixel))
744 if (colorKey != pSour[rsy * srcPitch + rsx])
746 // pDest[scanline * dstPitch + pixel] = pSour[rsy * srcPitch + rsx];
747 pDest[scanline * dstPitch + pixel] =
748 _Effect::Func::AlphaBlending<DestPixel, SourPixel>
749 (pDest[scanline * dstPitch + pixel]
750 , pSour[rsy * srcPitch + rsx]
751 , DestPixel(opacity));
766 rsx = _RealNumber::CastInt(sx + _RealNumber::Assign<_RealDataType>(0.49f));
767 rsy = _RealNumber::CastInt(sy + _RealNumber::Assign<_RealDataType>(0.49f));
769 rsx = _Util::Max(rsx, 0);
770 rsx = _Util::Min(rsx, maxSrcWidth);
772 rsy = _Util::Max(rsy, 0);
773 rsy = _Util::Min(rsy, maxSrcHeight);
775 if (clipRect.IsInsideX(pixel))
777 // pDest[scanline * dstPitch + pixel] = pSour[rsy * srcPitch + rsx];
778 pDest[scanline * dstPitch + pixel] =
779 _Effect::Func::AlphaBlending<DestPixel, SourPixel>
780 (pDest[scanline * dstPitch + pixel]
781 , pSour[rsy * srcPitch + rsx]
782 , DestPixel(opacity));
793 ////////////////////////////////////////////////////////////////////////////
794 // inline wrapper function for VC++ 6.0 compatibility
797 _RotateImage16bitsFrom16bits(_Util::Pixmap& dstImage, long x, long y, const _Util::Pixmap& srcImage, long width, long height,
798 const _Effect::RotateDesc& rotateDesc, short constantAlpha)
800 return _RotateImage <unsigned short, unsigned short>(dstImage, x, y, srcImage, width, height, rotateDesc, constantAlpha, 0);
804 _RotateImage16bitsFrom32bits(_Util::Pixmap& dstImage, long x, long y, const _Util::Pixmap& srcImage, long width, long height,
805 const _Effect::RotateDesc& rotateDesc, short constantAlpha)
807 return _RotateImage <unsigned short, unsigned long>(dstImage, x, y, srcImage, width, height, rotateDesc, constantAlpha, 0);
811 _RotateImage32bitsFrom16bits(_Util::Pixmap& dstImage, long x, long y, const _Util::Pixmap& srcImage, long width, long height,
812 const _Effect::RotateDesc& rotateDesc, long constantAlpha)
814 return _RotateImage <unsigned long, unsigned short>(dstImage, x, y, srcImage, width, height, rotateDesc, constantAlpha, 0);
818 _RotateImage32bitsFrom32bits(_Util::Pixmap& dstImage, long x, long y, const _Util::Pixmap& srcImage, long width, long height,
819 const _Effect::RotateDesc& rotateDesc, long constantAlpha)
821 return _RotateImage <unsigned long, unsigned long>(dstImage, x, y, srcImage, width, height, rotateDesc, constantAlpha, 0);
826 ////////////////////////////////////////////////////////////////////////////////
830 Tizen::Graphics::_Effect::RotateImage(_Util::Pixmap& dstImage, long xDest, long yDest, const _Util::Pixmap& srcImage,
831 const _Effect::RotateDesc& rotateDesc,
834 // verifiy the spcified parameters
836 if ((srcImage.width < 0) || (srcImage.height < 0) || (srcImage.pBitmap == null))
841 if ((dstImage.width < 0) || (dstImage.height < 0) || (dstImage.pBitmap == null))
846 switch (dstImage.depth)
856 if (constantAlpha <= 0)
861 if (constantAlpha > 255)
866 if (srcImage.pBitmap == dstImage.pBitmap)
874 if ((srcImage.width == 0) || (srcImage.height == 0))
879 if ((dstImage.width == 0) || (dstImage.height == 0))
885 if (dstImage.depth == 16 && srcImage.depth == 16)
887 return _RotateImage16bitsFrom16bits(dstImage, xDest, yDest, srcImage, srcImage.width, srcImage.height, rotateDesc,
888 short(constantAlpha));
890 else if (dstImage.depth == 16 && srcImage.depth == 32)
892 return _RotateImage16bitsFrom32bits(dstImage, xDest, yDest, srcImage, srcImage.width, srcImage.height, rotateDesc,
893 short(constantAlpha));
895 else if (dstImage.depth == 32 && srcImage.depth == 16)
897 return _RotateImage32bitsFrom16bits(dstImage, xDest, yDest, srcImage, srcImage.width, srcImage.height, rotateDesc,
900 else if (dstImage.depth == 32 && srcImage.depth == 32)
902 return _RotateImage32bitsFrom32bits(dstImage, xDest, yDest, srcImage, srcImage.width, srcImage.height, rotateDesc,