Tizen 2.1 base
[framework/osp/uifw.git] / src / graphics / effect / FGrp_EffectRotate.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
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
8 //
9 //     http://floralicense.org/license/
10 //
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.
16 //
17
18 /*
19  * @file        FGrp_EffectRotate.cpp
20  * @brief       This is the header file for internal utility class.
21  *
22  */
23
24 #include <new>
25 #include <cmath>
26 #include <cstring>
27
28 #include <unique_ptr.h>
29
30 #include <FBaseSysLog.h>
31
32 #include "FGrp_EffectFunc.h"
33 #include "FGrp_Effect.h"
34 #include "../util/FGrp_UtilType.h"
35
36 using namespace Tizen::Graphics;
37
38 ////////////////////////////////////////////////////////////////////////////////
39 // data type
40
41 #if 1
42         // _RealDataType as a floating point
43         typedef float _RealDataType;
44 #else
45         // _RealDataType as a fixed point
46         typedef long _RealDataType;
47 #endif
48
49 ////////////////////////////////////////////////////////////////////////////////
50 // definition
51
52 namespace // unnamed
53 {
54
55 namespace _RealNumber
56 {
57
58 template <typename T>
59 inline T
60 Assign(float f)
61 {
62         // Empty statement
63 }
64
65 template <typename T>
66 inline T
67 AssignShift(int i)
68 {
69         // Empty statement
70 }
71
72 template <typename T>
73 inline int
74 CastInt(T i)
75 {
76         return int(i);
77 }
78
79 template <typename T>
80 inline T
81 MultiplySmall(T first, T second)
82 {
83         // Empty statement
84 }
85
86 template <typename T>
87 inline T
88 MultiplyBig(T first, T second)
89 {
90         // Empty statement
91 }
92
93 template <typename T>
94 inline T
95 DivideSmall(T first, T second)
96 {
97         // Empty statement
98 }
99
100 template <typename T>
101 inline T
102 DivideBig(T first, T second)
103 {
104         // Empty statement
105 }
106
107 template <typename T>
108 inline T
109 Divide3(T first, T second, T third)
110 {
111         // Empty statement
112 }
113
114 template <typename T>
115 inline float
116 Dispatch(T i)
117 {
118         return float(i);
119 }
120
121 template <typename T>
122 inline T
123 Sin(T degree)
124 {
125         // Empty statement
126 }
127
128 template <typename T>
129 inline T
130 Cos(T degree)
131 {
132         // Empty statement
133 }
134
135 } // namespace _RealNumber
136
137 // specialization for float type
138 namespace _RealNumber
139 {
140 const float _FLOAT_PI = 3.141592f;
141
142 template <>
143 inline float
144 Assign<float>(float f)
145 {
146         return f;
147 }
148
149 template <>
150 inline float
151 AssignShift<float>(int i)
152 {
153         return float(i);
154 }
155
156 template <>
157 inline int
158 CastInt<float>(float i)
159 {
160         return int((i > 0.0f) ? (i + 0.5f) : (i - 0.5f));
161 }
162
163 template <>
164 inline float
165 MultiplySmall<float>(float first, float second)
166 {
167         return first * second;
168 }
169
170 template <>
171 inline float
172 MultiplyBig<float>(float first, float second)
173 {
174         return first * second;
175 }
176
177 template <>
178 inline float
179 DivideSmall<float>(float first, float second)
180 {
181         return first / second;
182 }
183
184 template <>
185 inline float
186 DivideBig<float>(float first, float second)
187 {
188         return first / second;
189 }
190
191 template <>
192 inline float
193 Divide3<float>(float first, float second, float third)
194 {
195         return first / second / third;
196 }
197
198 template <>
199 inline float
200 Dispatch<float>(float i)
201 {
202         return i;
203 }
204
205 template <>
206 inline float
207 Sin<float>(float degree)
208 {
209         return float(sinf(degree * _FLOAT_PI / 180.0f));
210 }
211
212 template <>
213 inline float
214 Cos<float>(float degree)
215 {
216         return float(cosf(degree * _FLOAT_PI / 180.0f));
217 }
218
219 } // namespace _RealNumber
220
221 // specialization for long type
222 namespace _RealNumber
223 {
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;
228
229 template <>
230 inline long
231 Assign<long>(float f)
232 {
233         return long((f) * _FPFLOAT_MUL_VALUE);
234 }
235
236 template <>
237 inline long
238 AssignShift<long>(int i)
239 {
240         return long((i) << _FPFLOAT_SHIFT);
241 }
242
243 template <>
244 inline int
245 CastInt<long>(long i)
246 {
247         return (i + (1 << (_FPFLOAT_SHIFT - 1))) >> _FPFLOAT_SHIFT;
248 }
249
250 template <>
251 inline long
252 MultiplySmall<long>(long first, long second)
253 {
254         return (first * second) >> _FPFLOAT_SHIFT;
255 }
256
257 template <>
258 inline long
259 MultiplyBig<long>(long first, long second)
260 {
261         return (first >> _FPFLOAT_SHIFT_HIGH) * (second >> _FPFLOAT_SHIFT_LOW);
262 }
263
264 template <>
265 inline long
266 DivideSmall<long>(long first, long second)
267 {
268         return (first << _FPFLOAT_SHIFT) / second;
269 }
270
271 template <>
272 inline long
273 DivideBig<long>(long first, long second)
274 {
275         return (first << _FPFLOAT_SHIFT_HIGH) / (second >> _FPFLOAT_SHIFT_LOW);
276 }
277
278 template <>
279 inline long
280 Divide3<long>(long first, long second, long third)
281 {
282         return DivideSmall<long>(DivideBig<long>(first, second), third);
283 }
284
285 template <>
286 inline float
287 Dispatch<long>(long i)
288 {
289         return float(i) / float(_FPFLOAT_MUL_VALUE);
290 }
291
292 int SinX16(int degree);
293 int CosX16(int degree);
294
295 template <>
296 inline long
297 Sin<long>(long degree)
298 {
299         // 16 was value that we shifted in a sine table
300         int n = _FPFLOAT_SHIFT - 16;
301
302         return (n >= 0) ? (SinX16(CastInt<long>(degree)) << n) : (SinX16(CastInt<long>(degree)) >> (-n));
303 }
304
305 template <>
306 inline long
307 Cos<long>(long degree)
308 {
309         // 16 was value that we shifted in a sine table
310         int n = _RealNumber::_FPFLOAT_SHIFT - 16;
311
312         return (n >= 0) ? (CosX16(CastInt<long>(degree)) << n) : (CosX16(CastInt<long>(degree)) >> (-n));
313 }
314
315 const int SIN_TABLE_X16[] = // 91 items
316 {
317         0,     // 0.000000
318         1144,  // 0.017452
319         2287,  // 0.034899
320         3430,  // 0.052336
321         4572,  // 0.069756
322         5712,  // 0.087156
323         6850,  // 0.104528
324         7987,  // 0.121869
325         9121,  // 0.139173
326         10252, // 0.156434
327         11380, // 0.173648
328         12505, // 0.190809
329         13626, // 0.207912
330         14742, // 0.224951
331         15855, // 0.241922
332         16962, // 0.258819
333         18064, // 0.275637
334         19161, // 0.292372
335         20252, // 0.309017
336         21336, // 0.325568
337         22415, // 0.342020
338         23486, // 0.358368
339         24550, // 0.374607
340         25607, // 0.390731
341         26656, // 0.406737
342         27697, // 0.422618
343         28729, // 0.438371
344         29753, // 0.453990
345         30767, // 0.469472
346         31772, // 0.484810
347         32768, // 0.500000
348         33754, // 0.515038
349         34729, // 0.529919
350         35693, // 0.544639
351         36647, // 0.559193
352         37590, // 0.573576
353         38521, // 0.587785
354         39441, // 0.601815
355         40348, // 0.615661
356         41243, // 0.629320
357         42126, // 0.642788
358         42995, // 0.656059
359         43852, // 0.669131
360         44695, // 0.681998
361         45525, // 0.694658
362         46341, // 0.707107
363         47143, // 0.719340
364         47930, // 0.731354
365         48703, // 0.743145
366         49461, // 0.754710
367         50203, // 0.766044
368         50931, // 0.777146
369         51643, // 0.788011
370         52339, // 0.798636
371         53020, // 0.809017
372         53684, // 0.819152
373         54332, // 0.829038
374         54963, // 0.838671
375         55578, // 0.848048
376         56175, // 0.857167
377         56756, // 0.866025
378         57319, // 0.874620
379         57865, // 0.882948
380         58393, // 0.891007
381         58903, // 0.898794
382         59396, // 0.906308
383         59870, // 0.913545
384         60326, // 0.920505
385         60764, // 0.927184
386         61183, // 0.933580
387         61584, // 0.939693
388         61966, // 0.945519
389         62328, // 0.951057
390         62672, // 0.956305
391         62997, // 0.961262
392         63303, // 0.965926
393         63589, // 0.970296
394         63856, // 0.974370
395         64104, // 0.978148
396         64332, // 0.981627
397         64540, // 0.984808
398         64729, // 0.987688
399         64898, // 0.990268
400         65048, // 0.992546
401         65177, // 0.994522
402         65287, // 0.996195
403         65376, // 0.997564
404         65446, // 0.998630
405         65496, // 0.999391
406         65526, // 0.999848
407         65536  // 1.000000
408 };
409
410 int
411 SinX16(int degree)
412 {
413         if ((degree %= 360) < 0)
414         {
415                 degree += 360;
416         }
417
418         switch (degree / 90)
419         {
420         case  0:
421                 return SIN_TABLE_X16[degree];
422         case  1:
423                 return SIN_TABLE_X16[180 - degree];
424         case  2:
425                 return -SIN_TABLE_X16[degree - 180];
426         default:
427                 return -SIN_TABLE_X16[360 - degree];
428         }
429 }
430
431 int
432 CosX16(int degree)
433 {
434         return SinX16(degree + 90);
435 }
436
437 } // namespace _RealNumber
438
439
440 template<typename T>
441 inline T
442 _Abs(T a)
443 {
444         return (a >= 0) ? a : -a;
445 }
446
447 template<typename T>
448 inline T
449 _Sign(T a)
450 {
451         return (a >= 0) ? ((a > 0) ? 1 : 0) : -1;
452 }
453
454 struct _Point
455 {
456         int x;
457         int y;
458
459         _Point()
460                 : x(0)
461                 , y(0)
462         {
463         }
464
465         _Point(int _x, int _y)
466                 : x(_x)
467                 , y(_y)
468         {
469         }
470 };
471
472 void
473 _DrawVirtualLineToArray(int x1, int y1, int x2, int y2, long yLineArrayLeft[], long yLineArrayRight[], _Point minPos,
474                                                 _Point maxPos)
475 {
476         _Point delta(_Abs(x2 - x1), _Abs(y2 - y1));
477         _Point increase(_Sign(x2 - x1), _Sign(y2 - y1));
478         _Point pos(0, 0);
479
480         int distance = _Util::Max(delta.x, delta.y);
481
482         for (int i = 0; i <= distance; i++)
483         {
484                 pos.x += delta.x;
485                 pos.y += delta.y;
486
487                 if (pos.x > distance)
488                 {
489                         x1 += increase.x;
490                         pos.x -= distance;
491                 }
492
493                 if (pos.y > distance)
494                 {
495                         y1 += increase.y;
496                         pos.y -= distance;
497                 }
498
499                 if ((y1 < minPos.y) || (y1 > maxPos.y))
500                 {
501                         continue;
502                 }
503
504                 if (x1 < yLineArrayLeft[y1 - minPos.y])
505                 {
506                         yLineArrayLeft[y1 - minPos.y] = (x1 < minPos.x) ? minPos.x : ((x1 > maxPos.x) ? maxPos.x : x1);
507                 }
508
509                 if (x1 > yLineArrayRight[y1 - minPos.y])
510                 {
511                         yLineArrayRight[y1 - minPos.y] = (x1 > maxPos.x) ? maxPos.x : ((x1 < minPos.x) ? minPos.x : x1);
512                 }
513         }
514 }
515
516 template<typename DestPixel, typename SourPixel>
517 bool
518 _RotateImage(_Util::Pixmap& dstImage, long x, long y, const _Util::Pixmap& srcImage, long width, long height,
519                          const _Effect::RotateDesc& rotateDesc, DestPixel opacity,
520                          SourPixel dummy = 0)
521 {
522         _Util::Bounds<int> clipRect = { 0, 0, dstImage.width, dstImage.height };
523
524         long angle = rotateDesc.angle;
525
526         // 'angle' will be between 1 and 360
527         {
528                 angle += 180;
529
530                 while (angle < 0)
531                 {
532                         angle += 360;
533                 }
534
535                 while (angle >= 360)
536                 {
537                         angle -= 360;
538                 }
539
540                 // convert to CCW
541                 angle = 360 - angle;
542         }
543
544         // the converted angle for the input angle becomes as follows
545         //
546         //   0 -> 180
547         //  10 -> 170
548         //  90 ->  90
549         // 100 ->  80
550         // 180 -> 360
551         // 190 -> 350
552         // 270 -> 270
553         // 280 -> 260
554
555         // if (angle == 0) then draw bitmap normally, but...
556
557         _RealDataType sinVal = _RealNumber::Sin(_RealNumber::AssignShift<_RealDataType>(angle));
558         _RealDataType cosVal = _RealNumber::Cos(_RealNumber::AssignShift<_RealDataType>(angle));
559
560         _Point vertex[4];
561
562         // center -> (x,y)
563         {
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);
572
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));
577
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));
582
583                 /* meaning of 'vertex', if 'angle' is 180
584
585                     v[1]      width      v[0]
586                         *---------------*
587                         |               |
588                         |       .       | height
589                         |        (x,y)  |
590                         |               |
591                         *---------------*
592                     v[3]                 v[2]
593
594
595                     if 'xOffset' and 'yOffset' are 0,
596
597                     v[1]                 v[0]
598                         *---------------*
599                         |(x,y)          |
600                         |               |
601                         |               |
602                         |               |
603                         *---------------*
604                     v[3]                 v[2]
605                 */
606         }
607
608         // find a maximum value and minimum value of rotated image on y-axis
609         int left = 0;
610         int right = dstImage.width - 0;
611         int top = vertex[3].y;
612         int bottom = vertex[3].y;
613
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);
621
622         // apply clipping
623         top = _Util::Max(top, clipRect.y1);
624         bottom = _Util::Min(bottom, clipRect.y2 - 0);
625
626         // number of pixels for vertical region
627         int numVerticalPixel = bottom - top + 1;
628
629         // no need to draw
630         if (numVerticalPixel <= 0)
631         {
632                 return true;
633         }
634
635         std::unique_ptr<long[]> tempLeftVertices(new (std::nothrow) long[numVerticalPixel]);
636         std::unique_ptr<long[]> tempRightVertices(new (std::nothrow) long[numVerticalPixel]);
637
638         SysTryReturn(NID_GRP, tempLeftVertices && tempRightVertices, false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
639
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));
643
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));
653
654         // memory buffer pointer & pitch of source
655         SourPixel* pSour = (SourPixel*) (srcImage.pBitmap);
656         int srcPitch = srcImage.bytesPerLine * 8 / srcImage.depth;
657
658         // memory buffer pointer & pitch of destination
659         DestPixel* pDest = (DestPixel*) dstImage.pBitmap;
660         int dstPitch = dstImage.bytesPerLine * 8 / dstImage.depth;
661
662         // scale
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));
665
666         // for clippping of source image
667         int maxSrcWidth = srcImage.width - 1;
668         int maxSrcHeight = srcImage.height - 1;
669
670         // current position to the set of vertical vertices
671         long* pLeftVertices = tempLeftVertices.get();
672         long* pRightVertices = tempRightVertices.get();
673
674         // draw horizontal linetop from top to bottom
675         for (long scanline = top; scanline < bottom; ++scanline)
676         {
677                 // out-of-clip test of 'y'
678                 if (scanline >= clipRect.y2)
679                 {
680                         break;
681                 }
682
683                 // skipping of 'y' for out-of-clip
684                 if (scanline < clipRect.y1)
685                 {
686                         ++pLeftVertices;
687                         ++pRightVertices;
688
689                         continue;
690                 }
691
692                 long leftVertex = *pLeftVertices++;
693                 long rightVertex = *pRightVertices++;
694                 long distVertex = rightVertex - leftVertex;
695
696                 int srcLeftVertexX = _RealNumber::CastInt(-(cosVal * (leftVertex - x)) - (sinVal * (scanline - y)));
697                 int srcLeftVertexY = _RealNumber::CastInt((sinVal * (leftVertex - x)) - (cosVal * (scanline - y)));
698
699                 int srcRightVertexX = _RealNumber::CastInt(-(cosVal * (rightVertex - x)) - (sinVal * (scanline - y)));
700                 int srcRightVertexY = _RealNumber::CastInt((sinVal * (rightVertex - x)) - (cosVal * (scanline - y)));
701
702                 _Point delta((srcRightVertexX - srcLeftVertexX), (srcRightVertexY - srcLeftVertexY));
703
704                 if (distVertex > 0)
705                 {
706                         int rsx, rsy;
707
708                         _RealDataType rdx = delta.x * xScale / distVertex;
709                         _RealDataType rdy = delta.y * yScale / distVertex;
710
711                         int pixel = leftVertex - 1;
712                         int count = distVertex;    // + 1;
713
714                         {
715                                 _RealDataType sx = srcLeftVertexX * xScale + _RealNumber::AssignShift<_RealDataType>(rotateDesc.xOffset);
716                                 _RealDataType sy = srcLeftVertexY * yScale + _RealNumber::AssignShift<_RealDataType>(rotateDesc.yOffset);
717
718                                 sx -= rdx;
719                                 sy -= rdy;
720
721                                 if (srcImage.enableColorKey)
722                                 {
723                                         SourPixel colorKey = (SourPixel) srcImage.colorKey;
724
725                                         while (count--)
726                                         {
727                                                 pixel++;
728
729                                                 sx += rdx;
730                                                 sy += rdy;
731
732                                                 // round off
733                                                 rsx = _RealNumber::CastInt(sx + _RealNumber::Assign<_RealDataType>(0.49f));
734                                                 rsy = _RealNumber::CastInt(sy + _RealNumber::Assign<_RealDataType>(0.49f));
735
736                                                 rsx = _Util::Max(rsx, 0);
737                                                 rsx = _Util::Min(rsx, maxSrcWidth);
738
739                                                 rsy = _Util::Max(rsy, 0);
740                                                 rsy = _Util::Min(rsy, maxSrcHeight);
741
742                                                 if (clipRect.IsInsideX(pixel))
743                                                 {
744                                                         if (colorKey != pSour[rsy * srcPitch + rsx])
745                                                         {
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));
752                                                         }
753                                                 }
754                                         }
755                                 }
756                                 else
757                                 {
758                                         while (count--)
759                                         {
760                                                 pixel++;
761
762                                                 sx += rdx;
763                                                 sy += rdy;
764
765                                                 // round off
766                                                 rsx = _RealNumber::CastInt(sx + _RealNumber::Assign<_RealDataType>(0.49f));
767                                                 rsy = _RealNumber::CastInt(sy + _RealNumber::Assign<_RealDataType>(0.49f));
768
769                                                 rsx = _Util::Max(rsx, 0);
770                                                 rsx = _Util::Min(rsx, maxSrcWidth);
771
772                                                 rsy = _Util::Max(rsy, 0);
773                                                 rsy = _Util::Min(rsy, maxSrcHeight);
774
775                                                 if (clipRect.IsInsideX(pixel))
776                                                 {
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));
783                                                 }
784                                         }
785                                 }
786                         }
787                 }
788         }
789
790         return true;
791 }
792
793 ////////////////////////////////////////////////////////////////////////////
794 // inline wrapper function for VC++ 6.0 compatibility
795
796 inline bool
797 _RotateImage16bitsFrom16bits(_Util::Pixmap& dstImage, long x, long y, const _Util::Pixmap& srcImage, long width, long height,
798                                                          const _Effect::RotateDesc& rotateDesc, short constantAlpha)
799 {
800         return _RotateImage <unsigned short, unsigned short>(dstImage, x, y, srcImage, width, height, rotateDesc, constantAlpha, 0);
801 }
802
803 inline bool
804 _RotateImage16bitsFrom32bits(_Util::Pixmap& dstImage, long x, long y, const _Util::Pixmap& srcImage, long width, long height,
805                                                          const _Effect::RotateDesc& rotateDesc, short constantAlpha)
806 {
807         return _RotateImage <unsigned short, unsigned long>(dstImage, x, y, srcImage, width, height, rotateDesc, constantAlpha, 0);
808 }
809
810 inline bool
811 _RotateImage32bitsFrom16bits(_Util::Pixmap& dstImage, long x, long y, const _Util::Pixmap& srcImage, long width, long height,
812                                                          const _Effect::RotateDesc& rotateDesc, long constantAlpha)
813 {
814         return _RotateImage <unsigned long, unsigned short>(dstImage, x, y, srcImage, width, height, rotateDesc, constantAlpha, 0);
815 }
816
817 inline bool
818 _RotateImage32bitsFrom32bits(_Util::Pixmap& dstImage, long x, long y, const _Util::Pixmap& srcImage, long width, long height,
819                                                          const _Effect::RotateDesc& rotateDesc, long constantAlpha)
820 {
821         return _RotateImage <unsigned long, unsigned long>(dstImage, x, y, srcImage, width, height, rotateDesc, constantAlpha, 0);
822 }
823
824 } // namespce
825
826 ////////////////////////////////////////////////////////////////////////////////
827 // public
828
829 bool
830 Tizen::Graphics::_Effect::RotateImage(_Util::Pixmap& dstImage, long xDest, long yDest, const _Util::Pixmap& srcImage,
831                                                                         const _Effect::RotateDesc& rotateDesc,
832                                                                         long constantAlpha)
833 {
834         // verifiy the spcified parameters
835         {
836                 if ((srcImage.width < 0) || (srcImage.height < 0) || (srcImage.pBitmap == null))
837                 {
838                         return false;
839                 }
840
841                 if ((dstImage.width < 0) || (dstImage.height < 0) || (dstImage.pBitmap == null))
842                 {
843                         return false;
844                 }
845
846                 switch (dstImage.depth)
847                 {
848                 case 16:
849                 case 32:
850                         break;
851                 default:
852                         return false;
853                 }
854
855                 // no need to draw
856                 if (constantAlpha <= 0)
857                 {
858                         return true;
859                 }
860
861                 if (constantAlpha > 255)
862                 {
863                         constantAlpha = 255;
864                 }
865
866                 if (srcImage.pBitmap == dstImage.pBitmap)
867                 {
868                         return false;
869                 }
870         }
871
872         // clipping test
873         {
874                 if ((srcImage.width == 0) || (srcImage.height == 0))
875                 {
876                         return true;
877                 }
878
879                 if ((dstImage.width == 0) || (dstImage.height == 0))
880                 {
881                         return true;
882                 }
883         }
884
885         if (dstImage.depth == 16 && srcImage.depth == 16)
886         {
887                 return _RotateImage16bitsFrom16bits(dstImage, xDest, yDest, srcImage, srcImage.width, srcImage.height, rotateDesc,
888                                                                                         short(constantAlpha));
889         }
890         else if (dstImage.depth == 16 && srcImage.depth == 32)
891         {
892                 return _RotateImage16bitsFrom32bits(dstImage, xDest, yDest, srcImage, srcImage.width, srcImage.height, rotateDesc,
893                                                                                         short(constantAlpha));
894         }
895         else if (dstImage.depth == 32 && srcImage.depth == 16)
896         {
897                 return _RotateImage32bitsFrom16bits(dstImage, xDest, yDest, srcImage, srcImage.width, srcImage.height, rotateDesc,
898                                                                                         constantAlpha);
899         }
900         else if (dstImage.depth == 32 && srcImage.depth == 32)
901         {
902                 return _RotateImage32bitsFrom32bits(dstImage, xDest, yDest, srcImage, srcImage.width, srcImage.height, rotateDesc,
903                                                                                         constantAlpha);
904         }
905
906         // assert(false);
907
908         return false;
909 }