Tizen 2.1 base
[framework/osp/uifw.git] / src / graphics / effect / FGrp_EffectScale.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_EffectScale.cpp
20  * @brief       This is the header file for internal utility class.
21  *
22  */
23
24 #include <new>
25
26 #include <FBaseSysLog.h>
27
28 #include "FGrp_EffectFunc.h"
29 #include "FGrp_Effect.h"
30 #include "../util/FGrp_Util.h"
31
32 using namespace Tizen::Graphics;
33
34
35 namespace // unnamed
36 {
37
38 template<typename Pixel>
39 class _GenericBufferPixmap
40         : public _Util::GenericBufferBase <Pixel>
41 {
42 public:
43         inline _GenericBufferPixmap(const _Util::PixmapBase& buffer, const _Util::Rectangle<int>* pRect)
44                 : _Util::GenericBufferBase <Pixel>()
45                 , __buffer(buffer)
46         {
47                 this->_pBuffer = (Pixel*) __buffer.pBitmap;
48                 this->_pitch = __buffer.bytesPerLine / sizeof(Pixel);
49
50                 if (pRect)
51                 {
52                         this->_padding = this->_pitch - pRect->w;
53                         this->_pBuffer += (this->_pitch * pRect->y + pRect->x);
54                         this->_rect.x = pRect->x;
55                         this->_rect.y = pRect->y;
56                         this->_rect.w = pRect->w;
57                         this->_rect.h = pRect->h;
58                 }
59                 else
60                 {
61                         this->_padding = this->_pitch - __buffer.width;
62                         this->_rect.x = 0;
63                         this->_rect.y = 0;
64                         this->_rect.w = __buffer.width;
65                         this->_rect.h = __buffer.height;
66                 }
67         }
68
69         inline virtual ~_GenericBufferPixmap(void)
70         {
71         }
72
73 private:
74         const _Util::PixmapBase& __buffer;
75 };
76
77 typedef unsigned long FIXED16x16;
78
79 template<typename Pixel>
80 bool
81 _ScaleImageUnclipped(_Util::PixmapBase* pRetImage, _Util::PixmapBase* pSrcImage, Pixel dummy = 0)
82 {
83         if (pRetImage == null || pSrcImage == null)
84         {
85                 return false;
86         }
87
88         if ((pSrcImage->width <= 0) || (pSrcImage->height <= 0)
89                 || (pRetImage->width <= 0) || (pRetImage->height <= 0))
90         {
91                 return true;
92         }
93
94         _Util::GenericBuffer <Pixel> srcBuffer(new (std::nothrow) _GenericBufferPixmap <Pixel>(*pSrcImage, null));
95         _Util::GenericBuffer <Pixel> dstBuffer(new (std::nothrow) _GenericBufferPixmap <Pixel>(*pRetImage, null));
96
97         SysTryReturn(NID_GRP, srcBuffer.IsValid() && dstBuffer.IsValid(), false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
98
99         FIXED16x16 xSour = 0;
100         FIXED16x16 ySour = 0;
101         FIXED16x16 wScale = FIXED16x16(srcBuffer.GetWidth() * 0x10000 / dstBuffer.GetWidth());
102         FIXED16x16 hScale = FIXED16x16(srcBuffer.GetHeight() * 0x10000 / dstBuffer.GetHeight());
103         FIXED16x16 temp;
104
105         Pixel* pSour;
106         Pixel* pDest = dstBuffer.GetBufferAddr();
107
108         int wCopy;
109         int hCopy = dstBuffer.GetHeight();
110
111         while (--hCopy >= 0)
112         {
113                 xSour = 0;
114                 pSour = srcBuffer.GetBufferAddr() + int(ySour >> 16) * srcBuffer.GetPitch();
115                 wCopy = dstBuffer.GetWidth();
116
117                 while (--wCopy >= 0)
118                 {
119                         *pDest++ = *pSour;
120
121                         temp = xSour;
122                         xSour += wScale;
123                         pSour += (int(xSour >> 16) - int(temp >> 16));
124                 }
125
126                 pDest += dstBuffer.GetPadding();
127                 ySour += hScale;
128         }
129
130         return true;
131 }
132
133 template<typename DestPixel, typename SourPixel>
134 bool
135 _ScaleImageCopyClipped(_Util::PixmapBase* pRetImage, _Util::PixmapBase* pSrcImage, const _Util::Rectangle<int>& validRect,
136                                            DestPixel dummy1 = 0,
137                                            SourPixel dummy2 = 0)
138 {
139         if (pRetImage == null || pSrcImage == null)
140         {
141                 return false;
142         }
143
144         if ((pSrcImage->width <= 0) || (pSrcImage->height <= 0)
145                 || (pRetImage->width <= 0) || (pRetImage->height <= 0))
146         {
147                 return true;
148         }
149
150         _Util::GenericBuffer <SourPixel> srcBuffer(new (std::nothrow) _GenericBufferPixmap <SourPixel>(*pSrcImage, null));
151         _Util::GenericBuffer <DestPixel> dstBuffer(new (std::nothrow) _GenericBufferPixmap <DestPixel>(*pRetImage, null));
152
153         SysTryReturn(NID_GRP, srcBuffer.IsValid() && dstBuffer.IsValid(), false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
154
155         FIXED16x16 xSour = 0;
156         FIXED16x16 ySour = 0;
157         FIXED16x16 wScale = FIXED16x16(srcBuffer.GetWidth() * 0x10000 / dstBuffer.GetWidth());
158         FIXED16x16 hScale = FIXED16x16(srcBuffer.GetHeight() * 0x10000 / dstBuffer.GetHeight());
159         FIXED16x16 temp;
160
161         SourPixel* pSour;
162         DestPixel* pDest = dstBuffer.GetBufferAddr();
163
164         int wCopy = validRect.x + validRect.w;
165         int hCopy = validRect.y + validRect.h;
166
167         for (int yDest = 0; yDest < hCopy; ++yDest)
168         {
169                 if (yDest < validRect.y)
170                 {
171                         int jump = (validRect.y - yDest);
172
173                         pDest += (dstBuffer.GetPitch() * jump);
174                         ySour += (hScale * jump);
175                         yDest = validRect.y;
176                 }
177
178                 xSour = 0;
179                 pSour = srcBuffer.GetBufferAddr() + int(ySour >> 16) * srcBuffer.GetPitch();
180
181                 {
182                         int jump = validRect.x;
183
184                         pDest += jump;
185                         xSour += (wScale * jump);
186                         pSour += (int(xSour >> 16));
187                 }
188
189                 if (!pSrcImage->enableColorKey)
190                 {
191                         for (int xDest = validRect.x; xDest < wCopy; xDest++)
192                         {
193                                 _Effect::Func::ConvertColorFormatFast <DestPixel, SourPixel>(pDest, pSour);
194                                 ++pDest;
195
196                                 temp = xSour;
197                                 xSour += wScale;
198                                 pSour += (int(xSour >> 16) - int(temp >> 16));
199                         }
200                 }
201                 else
202                 {
203                         SourPixel colorKey = (SourPixel) pSrcImage->colorKey;
204
205                         for (int xDest = validRect.x; xDest < wCopy; xDest++)
206                         {
207                                 if (*pSour != colorKey)
208                                 {
209                                         _Effect::Func::ConvertColorFormatFast <DestPixel, SourPixel>(pDest, pSour);
210                                 }
211
212                                 ++pDest;
213
214                                 temp = xSour;
215                                 xSour += wScale;
216                                 pSour += (int(xSour >> 16) - int(temp >> 16));
217                         }
218                 }
219
220                 pDest += (dstBuffer.GetWidth() - wCopy);
221                 pDest += dstBuffer.GetPadding();
222
223                 ySour += hScale;
224         }
225
226         return true;
227 }
228
229 template<typename DestPixel, typename SourPixel>
230 bool
231 _ScaleImageClipped(_Util::PixmapBase* pRetImage, _Util::PixmapBase* pSrcImage, const _Util::Rectangle<int>& validRect,
232                    DestPixel dummy1 = 0, SourPixel dummy2 = 0)
233 {
234         if (pRetImage == null || pSrcImage == null)
235         {
236                 return false;
237         }
238
239         if ((pSrcImage->width <= 0) || (pSrcImage->height <= 0)
240                 || (pRetImage->width <= 0) || (pRetImage->height <= 0))
241         {
242                 return true;
243         }
244
245         _Util::GenericBuffer <SourPixel> srcBuffer(new (std::nothrow) _GenericBufferPixmap <SourPixel>(*pSrcImage, null));
246         _Util::GenericBuffer <DestPixel> dstBuffer(new (std::nothrow) _GenericBufferPixmap <DestPixel>(*pRetImage, null));
247
248         SysTryReturn(NID_GRP, srcBuffer.IsValid() && dstBuffer.IsValid(), false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
249
250         FIXED16x16 xSour = 0;
251         FIXED16x16 ySour = 0;
252         FIXED16x16 wScale = FIXED16x16(srcBuffer.GetWidth() * 0x10000 / dstBuffer.GetWidth());
253         FIXED16x16 hScale = FIXED16x16(srcBuffer.GetHeight() * 0x10000 / dstBuffer.GetHeight());
254         FIXED16x16 temp;
255
256         SourPixel* pSour = 0;
257         DestPixel* pDest = dstBuffer.GetBufferAddr();
258
259         int wCopy = validRect.x + validRect.w;
260         int hCopy = validRect.y + validRect.h;
261
262         for (int yDest = 0; yDest < hCopy; ++yDest)
263         {
264                 if (yDest < validRect.y)
265                 {
266                         int jump = (validRect.y - yDest);
267
268                         pDest += (dstBuffer.GetPitch() * jump);
269                         ySour += (hScale * jump);
270                         yDest = validRect.y;
271                 }
272
273                 xSour = 0;
274                 pSour = srcBuffer.GetBufferAddr() + int(ySour >> 16) * srcBuffer.GetPitch();
275
276                 {
277                         int jump = validRect.x;
278
279                         pDest += jump;
280                         xSour += (wScale * jump);
281                         pSour += (int(xSour >> 16));
282                 }
283
284                 if (!pSrcImage->enableColorKey)
285                 {
286                         for (int xDest = validRect.x; xDest < wCopy; xDest++)
287                         {
288                                 // _Effect::Func::ConvertColorFormatFast<DestPixel, SourPixel>(pDest, pSour);
289                                 *pDest = _Effect::Func::AlphaBlendingFast <DestPixel, SourPixel>(*pDest, *pSour);
290                                 ++pDest;
291
292                                 temp = xSour;
293                                 xSour += wScale;
294                                 pSour += (int(xSour >> 16) - int(temp >> 16));
295                         }
296                 }
297                 else
298                 {
299                         SourPixel colorKey = (SourPixel) pSrcImage->colorKey;
300
301                         for (int xDest = validRect.x; xDest < wCopy; xDest++)
302                         {
303                                 if (*pSour != colorKey)
304                                 {
305                                         *pDest = _Effect::Func::AlphaBlendingFast <DestPixel, SourPixel>(*pDest, *pSour);
306                                 }
307
308                                 ++pDest;
309
310                                 temp = xSour;
311                                 xSour += wScale;
312                                 pSour += (int(xSour >> 16) - int(temp >> 16));
313                         }
314                 }
315
316                 pDest += (dstBuffer.GetWidth() - wCopy);
317                 pDest += dstBuffer.GetPadding();
318
319                 ySour += hScale;
320         }
321
322         return true;
323 }
324
325 bool
326 _ScaleImage(const _Util::Pixmap& retImage, long xDest, long yDest, long wDest, long hDest, const _Util::Pixmap& srcImage,
327                         _Effect::Rop rop)
328 {
329         _Util::Rectangle<int> outRect = {0, 0, -1, -1};
330
331         {
332                 _Util::Rectangle<int> dstRect = { 0, 0, retImage.width, retImage.height };
333                 _Util::Rectangle<int> tgtRect = { xDest, yDest, wDest, hDest };
334
335 #if 0
336                 {
337                         bool hasRegion = IntersectRect(outRect, tgtRect, dstRect);
338
339                         SM_ASSERT(hasRegion);
340                 }
341 #else
342                 IntersectRect(outRect, tgtRect, dstRect);
343 #endif
344
345                 // workaround 2010/3/6
346                 // variable: bool isUnclipped = false;
347                 // isUnclipped = (tgtRect == outRect);
348         }
349
350         {
351 #if 0 // isUnclipped is always false
352                 if (isUnclipped)
353                 {
354                         _Util::PixmapBase dstImage = retImage.GetSubBitmap(xDest, yDest, wDest, hDest);
355
356                         switch (retImage.depth)
357                         {
358                         case 32:
359                                 return _ScaleImageUnclipped <unsigned long>((_Util::PixmapBase*) &dstImage, (_Util::PixmapBase*) &srcImage);
360
361                         case 16:
362                                 return _ScaleImageUnclipped <unsigned short>((_Util::PixmapBase*) &dstImage, (_Util::PixmapBase*) &srcImage);
363
364                         default:
365                                 return false;
366                         }
367                 }
368                 else
369 #endif
370                 {
371                         _Util::PixmapBase dstImage = retImage.GetSubBitmapUnsafe(xDest, yDest, wDest, hDest);
372                         _Util::Rectangle<int> validRect = outRect;
373
374                         validRect.x -= xDest;
375                         validRect.y -= yDest;
376
377                         switch (rop)
378                         {
379                         case Tizen::Graphics::_Effect::ROP_COPY:
380                                 switch (retImage.depth)
381                                 {
382                                 case 32:
383                                         if (srcImage.depth == 32)
384                                         {
385                                                 return _ScaleImageCopyClipped <unsigned long, unsigned long>((_Util::PixmapBase*) &dstImage,
386                                                                                                                                                                          (_Util::PixmapBase*) &srcImage, validRect,
387                                                                                                                                                                          (unsigned long) 0, (unsigned long) 0);
388                                         }
389                                         else if (srcImage.depth == 16)
390                                         {
391                                                 return _ScaleImageCopyClipped <unsigned long, unsigned short>((_Util::PixmapBase*) &dstImage,
392                                                                                                                                                                           (_Util::PixmapBase*) &srcImage, validRect,
393                                                                                                                                                                           (unsigned long) 0, (unsigned short) 0);
394                                         }
395                                         else
396                                         {
397                                                 return false;
398                                         }
399                                 case 16:
400                                         if (srcImage.depth == 32)
401                                         {
402                                                 return _ScaleImageCopyClipped <unsigned short, unsigned long>((_Util::PixmapBase*) &dstImage,
403                                                                                                                                                                           (_Util::PixmapBase*) &srcImage, validRect,
404                                                                                                                                                                           (unsigned short) 0, (unsigned long) 0);
405                                         }
406                                         else if (srcImage.depth == 16)
407                                         {
408                                                 return _ScaleImageCopyClipped <unsigned short, unsigned short>((_Util::PixmapBase*) &dstImage,
409                                                                                                                                                                            (_Util::PixmapBase*) &srcImage, validRect,
410                                                                                                                                                                            (unsigned short) 0, (unsigned short) 0);
411                                         }
412                                         else
413                                         {
414                                                 return false;
415                                         }
416                                 default:
417                                         return false;
418                                 }
419                                 break;
420                         case Tizen::Graphics::_Effect::ROP_ALPHABLEND:
421                                 switch (retImage.depth)
422                                 {
423                                 case 32:
424                                         if (srcImage.depth == 32)
425                                         {
426                                                 return _ScaleImageClipped <unsigned long, unsigned long>((_Util::PixmapBase*) &dstImage,
427                                                                                                                                                                  (_Util::PixmapBase*) &srcImage, validRect,
428                                                                                                                                                                  (unsigned long) 0, (unsigned long) 0);
429                                         }
430                                         else if (srcImage.depth == 16)
431                                         {
432                                                 return _ScaleImageClipped <unsigned long, unsigned short>((_Util::PixmapBase*) &dstImage,
433                                                                                                                                                                   (_Util::PixmapBase*) &srcImage, validRect,
434                                                                                                                                                                   (unsigned long) 0, (unsigned short) 0);
435                                         }
436                                         else
437                                         {
438                                                 return false;
439                                         }
440                                 case 16:
441                                         if (srcImage.depth == 32)
442                                         {
443                                                 return _ScaleImageClipped <unsigned short, unsigned long>((_Util::PixmapBase*) &dstImage,
444                                                                                                                                                                   (_Util::PixmapBase*) &srcImage, validRect,
445                                                                                                                                                                   (unsigned short) 0, (unsigned long) 0);
446                                         }
447                                         else if (srcImage.depth == 16)
448                                         {
449                                                 return _ScaleImageClipped <unsigned short, unsigned short>((_Util::PixmapBase*) &dstImage,
450                                                                                                                                                                    (_Util::PixmapBase*) &srcImage, validRect,
451                                                                                                                                                                    (unsigned short) 0, (unsigned short) 0);
452                                         }
453                                         else
454                                         {
455                                                 return false;
456                                         }
457                                 default:
458                                         return false;
459                                 }
460                                 break;
461                         default:
462                                 return false;
463                         }
464                 }
465         }
466 }
467
468 }
469
470
471 bool
472 Tizen::Graphics::_Effect::ScaleImage(_Util::Pixmap& dstImage, long xDest, long yDest, long wDest, long hDest,
473                                                                    const _Util::Pixmap& srcImage,
474                                                                    Rop rop)
475 {
476         // verifiy the spcified parameters
477         {
478                 if ((srcImage.width < 0) || (srcImage.height < 0) || (srcImage.pBitmap == null))
479                 {
480                         return false;
481                 }
482
483                 if ((dstImage.width < 0) || (dstImage.height < 0) || (dstImage.pBitmap == null))
484                 {
485                         return false;
486                 }
487
488                 if ((wDest < 0) || (hDest < 0))
489                 {
490                         return false;
491                 }
492
493                 if (srcImage.pBitmap == dstImage.pBitmap)
494                 {
495                         return false;
496                 }
497
498                 if (!(rop == ROP_COPY || rop == ROP_ALPHABLEND))
499                 {
500                         return false;
501                 }
502         }
503
504         {
505                 if ((srcImage.width == 0) || (srcImage.height == 0))
506                 {
507                         return true;
508                 }
509
510                 if ((dstImage.width == 0) || (dstImage.height == 0))
511                 {
512                         return true;
513                 }
514
515                 if ((wDest == 0) || (hDest == 0))
516                 {
517                         return true;
518                 }
519
520                 {
521                         _Util::Rectangle<int> dstRect = { 0, 0, dstImage.width, dstImage.height };
522                         _Util::Rectangle<int> tgtRect = { xDest, yDest, wDest, hDest };
523                         _Util::Rectangle<int> outRect;
524
525                         if (!IntersectRect(outRect, tgtRect, dstRect))
526                         {
527                                 return true;
528                         }
529                 }
530         }
531
532         return _ScaleImage(dstImage, xDest, yDest, wDest, hDest, srcImage, rop);
533 }