Tizen 2.1 base
[framework/osp/uifw.git] / src / graphics / FGrp_Bitmap.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_Bitmap.cpp
20  * @brief       This is the implementation file for _Bitmap class.
21  *
22  */
23
24 #include <new>
25 #include <memory>
26
27 #include <unique_ptr.h>
28
29 #include <FGrpPoint.h>
30 #include <FGrpDimension.h>
31 #include <FGrpBufferInfo.h>
32
33 #include <FBaseSysLog.h>
34
35 #include "FGrp_BufferInfoImpl.h"
36 #include "FGrp_Bitmap.h"
37 #include "FGrp_Canvas.h"
38 #include "FGrp_CanvasPixman.h"
39 #include "FGrp_Screen.h"
40 #include "util/FGrp_UtilTemplate.h"
41 #include "effect/FGrp_Effect.h"
42
43 ////////////////////////////////////////////////////////////////////////////////
44
45 using namespace Tizen::Base;
46 using namespace Tizen::Graphics;
47
48 namespace // unnamed
49 {
50
51 bool
52 _CheckValidityOfRectangle(const Tizen::Graphics::Rectangle& rect)
53 {
54         return ((rect.width > 0) && (rect.height > 0));
55 }
56
57 bool
58 _CheckValidity(const Tizen::Graphics::Rectangle& rtSrc, const Tizen::Graphics::Rectangle& rtDest)
59 {
60         // check 1. is width/height less or equal than 0?
61         if (rtSrc.width <= 0 || rtSrc.height <= 0 || rtDest.width <= 0 || rtDest.height <= 0)
62         {
63                 return false;     // "[E_OUT_OF_RANGE] The argument is out of range. (src(w:%d,h:%d), dst(w:%d,h:%d))\n", rtSrc.width, rtSrc.height, rtDest.width, rtDest.height);
64         }
65
66         // check 2.     is src exiting outside of dest entirely?
67         if (rtSrc.x > rtDest.x + rtDest.width - 1 || rtSrc.x + rtSrc.width - 1 < rtDest.x)
68         {
69                 return false;     // "[E_OUT_OF_RANGE] The argument is out of range. (src(x:%d,y:%d,w:%d,h:%d), dst(x:%d,y:%d,w:%d,h:%d))\n", rtSrc.x, rtSrc.y, rtSrc.width, rtSrc.height, rtDest.x, rtDest.y, rtDest.width, rtDest.height);
70         }
71
72         if (rtSrc.y > rtDest.y + rtDest.height - 1 || rtSrc.y + rtSrc.height - 1 < rtDest.y)
73         {
74                 return false;     // "[E_OUT_OF_RANGE] The argument is out of range. (src(x:%d,y:%d,w:%d,h:%d), dst(x:%d,y:%d,w:%d,h:%d))\n", rtSrc.x, rtSrc.y, rtSrc.width, rtSrc.height, rtDest.x, rtDest.y, rtDest.width, rtDest.height);
75         }
76
77         return true;
78 }
79
80 bool
81 _IsOpaqueAllOver(Tizen::Graphics::_Bitmap* pBitmap)
82 {
83         bool ret = false;
84
85         if (pBitmap == null)
86         {
87                 return ret;
88         }
89
90         Tizen::Graphics::BufferInfo dstBufferInfo;
91
92         if (pBitmap->Lock(dstBufferInfo) == E_SUCCESS)
93         {
94                 const Tizen::Graphics::_Util::Pixmap dstImage(dstBufferInfo.width, dstBufferInfo.height, dstBufferInfo.bitsPerPixel, dstBufferInfo.pPixels, dstBufferInfo.pitch);
95                 ret = Tizen::Graphics::_Effect::IsOpaqueAllOver(dstImage);
96
97                 pBitmap->Unlock();
98         }
99
100         return ret;
101 }
102
103 typedef result (::Tizen::Graphics::_Bitmap::* _FnLock)(Tizen::Graphics::BufferInfo&, long);
104 typedef result (::Tizen::Graphics::_Bitmap::* _FnUnlock)(void);
105
106 bool
107 _IsOpaqueAllOver(Tizen::Graphics::_Bitmap* pBitmap, _FnLock fnLock, _FnUnlock fnUnlock)
108 {
109         bool ret = false;
110
111         if (pBitmap == null)
112         {
113                 return ret;
114         }
115
116         Tizen::Graphics::BufferInfo dstBufferInfo;
117         if ((pBitmap->*fnLock)(dstBufferInfo, INFINITE) == E_SUCCESS)
118         {
119                 const Tizen::Graphics::_Util::Pixmap dstImage(dstBufferInfo.width, dstBufferInfo.height, dstBufferInfo.bitsPerPixel, dstBufferInfo.pPixels, dstBufferInfo.pitch);
120                 ret = Tizen::Graphics::_Effect::IsOpaqueAllOver(dstImage);
121
122                 (pBitmap->*fnUnlock)();
123         }
124
125         return ret;
126 }
127
128 class _BitmapImplExHack
129         : public _Bitmap
130 {
131 public:
132         void SetOwnership(bool ownership)
133         {
134                 this->_SetOwnership(ownership);
135         }
136
137         void ChangeBuffer(bool ownership, unsigned char* pBuffer)
138         {
139                 this->_ChangeBuffer(ownership, pBuffer);
140         }
141 };     // _BitmapImplExHack
142
143 template<typename Pixel>
144 result
145 _CreateBitmapFromBufferInfo(_Bitmap* thiz, BufferInfo& sourBufferInfo, int x, int y, int width, int height)
146 {
147         std::unique_ptr<unsigned char[]> pDestBuffer(new (std::nothrow) unsigned char[width * height * sizeof(Pixel)]);
148
149         if (pDestBuffer == null)
150         {
151                 return E_OUT_OF_MEMORY;
152         }
153
154         std::auto_ptr<_Util::ScratchPad<Pixel> > pSourScratchPadAuto(new (std::nothrow) _Util::ScratchPad<Pixel>((Pixel*) sourBufferInfo.pPixels, sourBufferInfo.width, sourBufferInfo.height, sourBufferInfo.pitch / sizeof(Pixel)));
155         std::auto_ptr<_Util::ScratchPad<Pixel> > pDestScratchPadAuto(new (std::nothrow) _Util::ScratchPad<Pixel>((Pixel*) pDestBuffer.get(), width, height, width));
156
157         _Util::ScratchPad<Pixel>* pSourScratchPad = pSourScratchPadAuto.get();
158         _Util::ScratchPad<Pixel>* pDestScratchPad = pDestScratchPadAuto.get();
159
160         if (pSourScratchPad == null || pDestScratchPad == null)
161         {
162                 return E_OUT_OF_MEMORY;
163         }
164
165         pDestScratchPad->BitBlt(0, 0, pSourScratchPad, x, y, width, height);
166
167         result r = thiz->Construct((void*) pDestBuffer.get(), width, height, sizeof(Pixel) * 8);
168
169         if (r != E_SUCCESS)
170         {
171                 return r;
172         }
173
174         pDestBuffer.release();
175
176         static_cast<_BitmapImplExHack*>(thiz)->SetOwnership(true);
177
178         return E_SUCCESS;
179 }
180
181 template<typename Pixel>
182 result
183 _Resize(_Bitmap* thiz, _Util::ScratchPad<Pixel>*& pScratchPad, int width, int height, BitmapScalingQuality quality = BITMAP_SCALING_QUALITY_LOW)
184 {
185         std::unique_ptr<unsigned char[]> pDestBuffer(new (std::nothrow) unsigned char[width * height * sizeof(Pixel)]);
186
187         if (pDestBuffer == null)
188         {
189                 return E_OUT_OF_MEMORY;
190         }
191
192         memset(pDestBuffer.get(), 0, width * height * sizeof(Pixel));
193
194         Pixel* pAddr;
195         int pitch;
196
197         pScratchPad->GetBuffer(pAddr, pitch);
198
199         _Util::Pixmap srcImageEx(pScratchPad->GetWidth(), pScratchPad->GetHeight(), sizeof(Pixel) * 8, pAddr, pitch * sizeof(Pixel));
200         _Util::Pixmap dstImageEx(width, height, sizeof(Pixel) * 8, pDestBuffer.get(), width * sizeof(Pixel));
201
202         bool isDone = Tizen::Graphics::_Pixman::ResizePixmap(dstImageEx, srcImageEx, quality);
203
204         if (!isDone)
205         {
206                 switch (quality)
207                 {
208                 case BITMAP_SCALING_QUALITY_LOW:
209                         isDone = Tizen::Graphics::_Effect::ScaleImage(dstImageEx, 0, 0, width, height, srcImageEx, Tizen::Graphics::_Effect::ROP_COPY);
210                         break;
211                 case BITMAP_SCALING_QUALITY_MID:
212                         isDone = Tizen::Graphics::_Effect::ScaleImageInterpolation(dstImageEx, 0, 0, width, height, srcImageEx, Tizen::Graphics::_Effect::DEFAULT_FILTER_GOOD);
213                         break;
214                 case BITMAP_SCALING_QUALITY_HIGH:
215                         isDone = Tizen::Graphics::_Effect::ScaleImageInterpolation(dstImageEx, 0, 0, width, height, srcImageEx, Tizen::Graphics::_Effect::DEFAULT_FILTER_BEST);
216                         break;
217                 }
218         }
219
220         if (!isDone)
221         {
222                 return E_SYSTEM;
223         }
224
225         _Util::ScratchPad<Pixel>* pTempScratchPad = new (std::nothrow) _Util::ScratchPad<Pixel>((Pixel*) pDestBuffer.get(), width, height, width);
226
227         if (pTempScratchPad == null)
228         {
229                 return E_OUT_OF_MEMORY;
230         }
231
232         // swap them.
233         delete pScratchPad;
234         pScratchPad = pTempScratchPad;
235
236         //?? need to be verified again for clearing
237         static_cast<_BitmapImplExHack*>(thiz)->ChangeBuffer(true, (unsigned char*) pDestBuffer.release());
238
239         return E_SUCCESS;
240 }
241
242 template<typename DestPixel, typename SourPixel>
243 result
244 _MergeWithConversion(_Util::ScratchPad<DestPixel>* pDestScratchPad, int destX, int destY, _Util::ScratchPad<SourPixel>* pSourScratchPad, int srcX, int srcY, int srcWidth, int srcHeight)
245 {
246         _Util::Pixmap* pSrcImageEx = null;
247
248         {
249                 _Util::ScratchPad<SourPixel>& srcScratchPad = *pSourScratchPad;
250
251                 SourPixel* pAddr;
252                 int pitch;
253
254                 srcScratchPad.GetBuffer(pAddr, pitch);
255
256                 {
257                         _Util::Pixmap srcImageEx(srcScratchPad.GetWidth(), srcScratchPad.GetHeight(), sizeof(SourPixel) * 8, pAddr, pitch * sizeof(SourPixel));
258
259                         pSrcImageEx = srcImageEx.GetClone(sizeof(DestPixel) * 8);
260                 }
261
262                 if (pSrcImageEx == null)
263                 {
264                         return E_SYSTEM;
265                 }
266         }
267
268         _Util::ScratchPad<DestPixel> srcScratchPad((DestPixel*) pSrcImageEx->pBitmap, pSrcImageEx->width, pSrcImageEx->height, pSrcImageEx->bytesPerLine / sizeof(DestPixel));
269
270         pDestScratchPad->BitBlt(destX, destY, &srcScratchPad, srcX, srcY, srcWidth, srcHeight);
271
272         delete pSrcImageEx;
273
274         return E_SUCCESS;
275 }
276
277 }
278
279 namespace Tizen { namespace Graphics
280 {
281
282 bool _GetScreenShot(int depth, unsigned char*& pOutBuffer, int& screenWidth, int& screenHeight);
283
284 _Bitmap::_Bitmap(void)
285         : __timeStamp(0)
286         , __opacity(255)
287         , __isOpaqueAllOver(0)
288         , __hasOwnership(true)
289         , __pBuffer(null)
290         , __isPremultiplied(false)
291         , __hasMaskingColor(false)
292         , __maskingColor(0)
293         , __bitmapPixelFormat(BITMAP_PIXEL_FORMAT_MIN)
294         , __scalingQuality(BITMAP_SCALING_QUALITY_LOW)
295         , __pScratchPad32(null)
296         , __pScratchPad16(null)
297         , __pLockCallbackFunc(null)
298         , __pLockCallbackParam(null)
299         , __pUnlockCallbackFunc(null)
300         , __pUnlockCallbackParam(null)
301 {
302 }
303
304 _Bitmap::~_Bitmap(void)
305 {
306         delete __pScratchPad32;
307         delete __pScratchPad16;
308
309         if (__hasOwnership)
310         {
311                 delete[] __pBuffer;
312         }
313 }
314
315 result
316 _Bitmap::Construct(const Rectangle& rect)
317 {
318         //?? what do you do in the case of 16-bit?
319         const int systemBpp = _Screen::GetBytesPerPixel();
320
321         SysTryReturnResult(NID_GRP, (systemBpp == 32) || (systemBpp == 16), E_SYSTEM, "Screen depth is not available.");
322
323         int x = rect.x;
324         int y = rect.y;
325         int width = rect.width;
326         int height = rect.height;
327
328         {
329                 size_t allocSize = width * height * systemBpp;
330
331                 std::unique_ptr<unsigned char[]> pAllocated(new (std::nothrow) unsigned char[allocSize]);
332
333                 SysTryReturnResult(NID_GRP, pAllocated, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The bitmap memory is insufficient");
334
335                 result r = this->Construct((void*) pAllocated.get(), width, height, systemBpp);
336
337                 SysTryReturnResult(NID_GRP, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
338
339                 // copy contents from the current screen
340                 {
341                         unsigned char* pCapturedBuffer = null;
342                         int bufferWidth = 0;
343                         int bufferHeight = 0;
344
345                         if (_GetScreenShot(systemBpp, pCapturedBuffer, bufferWidth, bufferHeight))
346                         {
347                                 switch (systemBpp)
348                                 {
349                                 case 32:
350                                         if (__pScratchPad32)
351                                         {
352                                                 _Util::ScratchPad<unsigned long> capturedScratchPad((unsigned long*) pCapturedBuffer, bufferWidth, bufferHeight, bufferWidth);
353                                                 __pScratchPad32->BitBlt(0, 0, &capturedScratchPad, x, y, width, height);
354                                         }
355                                         break;
356                                 case 16:
357                                         if (__pScratchPad16)
358                                         {
359                                                 _Util::ScratchPad<unsigned short> capturedScratchPad((unsigned short*) pCapturedBuffer, bufferWidth, bufferHeight, bufferWidth);
360                                                 __pScratchPad16->BitBlt(0, 0, &capturedScratchPad, x, y, width, height);
361                                         }
362                                         break;
363                                 }
364
365                                 delete[] pCapturedBuffer;
366                         }
367                 }
368
369                 this->__hasOwnership = true;
370
371                 this->__isOpaqueAllOver = _IsOpaqueAllOver(this);
372
373                 this->__bitmapPixelFormat = (systemBpp == 32) ? BITMAP_PIXEL_FORMAT_ARGB8888 : BITMAP_PIXEL_FORMAT_RGB565;
374
375                 pAllocated.release();
376
377                 return E_SUCCESS;
378         }
379 }
380
381 result
382 _Bitmap::Construct(const Dimension& dim, BitmapPixelFormat pixelFormat)
383 {
384         int size = dim.width * dim.height;
385         int bytesPerPixel = 0;
386
387         switch (pixelFormat)
388         {
389         case BITMAP_PIXEL_FORMAT_RGB565:
390                 size *= sizeof(unsigned short);
391                 bytesPerPixel = sizeof(unsigned short);
392                 break;
393         case BITMAP_PIXEL_FORMAT_ARGB8888:
394         case BITMAP_PIXEL_FORMAT_R8G8B8A8:
395                 size *= sizeof(unsigned long);
396                 bytesPerPixel = sizeof(unsigned long);
397                 break;
398         default:
399                 SysTryReturnResult(NID_GRP, 0, E_INVALID_ARG, "BitmapPixelFormat(%d) is invalid argument.\n", pixelFormat);
400                 break;
401         }
402
403         int width = dim.width;
404         int height = dim.height;
405
406         {
407                 size_t allocSize = width * height * bytesPerPixel;
408
409                 std::unique_ptr<unsigned char[]> pAllocated(new (std::nothrow) unsigned char[allocSize]);
410
411                 SysTryReturnResult(NID_GRP, pAllocated, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The bitmap memory is insufficient");
412
413                 result r = this->Construct((void*) pAllocated.get(), width, height, bytesPerPixel * 8);
414
415                 SysTryReturnResult(NID_GRP, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
416
417                 memset(pAllocated.get(), 0, allocSize);
418
419                 this->__hasOwnership = true;
420
421                 this->__isOpaqueAllOver = _IsOpaqueAllOver(this);
422
423                 this->__bitmapPixelFormat = pixelFormat;
424
425                 pAllocated.release();
426
427                 return r;
428         }
429 }
430
431 result
432 _Bitmap::Construct(const _Canvas& canvas, const Rectangle& rect)
433 {
434         SysTryReturnResult(NID_GRP, canvas.IsValid(), E_INVALID_ARG, "A canvas is invalid.\n");
435
436         result r = E_SYSTEM;
437
438         int x = rect.x;
439         int y = rect.y;
440         int width = rect.width;
441         int height = rect.height;
442
443         BufferInfo sourBI;
444
445         if (const_cast<_Canvas&>(canvas).Lock(sourBI) == E_SUCCESS)
446         {
447                 switch (sourBI.bitsPerPixel)
448                 {
449                 case 16:
450                         r = _CreateBitmapFromBufferInfo<unsigned short>(this, sourBI, x, y, width, height);
451                         break;
452
453                 case 32:
454                         r = _CreateBitmapFromBufferInfo<unsigned long>(this, sourBI, x, y, width, height);
455                         break;
456
457                 default:
458                         break;
459                 }
460
461                 const_cast<_Canvas&>(canvas).Unlock();
462         }
463
464         this->__isOpaqueAllOver = _IsOpaqueAllOver(this);
465
466         this->__bitmapPixelFormat = (sourBI.bitsPerPixel == 32) ? BITMAP_PIXEL_FORMAT_ARGB8888 : BITMAP_PIXEL_FORMAT_RGB565;
467
468         return r;
469 }
470
471 result
472 _Bitmap::Construct(const _Bitmap& bitmap, const Rectangle& rect)
473 {
474         result r = E_SYSTEM;
475
476         int x = rect.x;
477         int y = rect.y;
478         int width = rect.width;
479         int height = rect.height;
480
481         BufferInfo sourBI;
482
483         if (const_cast<_Bitmap&>(bitmap).Lock(sourBI) == E_SUCCESS)
484         {
485                 switch (bitmap.GetBitsPerPixel())
486                 {
487                 case 16:
488                         r = _CreateBitmapFromBufferInfo<unsigned short>(this, sourBI, x, y, width, height);
489                         break;
490
491                 case 32:
492                         r = _CreateBitmapFromBufferInfo<unsigned long>(this, sourBI, x, y, width, height);
493                         break;
494
495                 default:
496                         break;
497                 }
498
499                 const_cast<_Bitmap&>(bitmap).Unlock();
500         }
501
502         this->__isOpaqueAllOver = _IsOpaqueAllOver(this);
503
504         //?? need to make a versioning for BITMAP_PIXEL_FORMAT_B8G8R8A8
505         this->__bitmapPixelFormat = (bitmap.GetBitsPerPixel() == 32) ? BITMAP_PIXEL_FORMAT_ARGB8888 : BITMAP_PIXEL_FORMAT_RGB565;
506
507         return r;
508 }
509
510 result
511 _Bitmap::Construct(const Tizen::Base::ByteBuffer& buffer, const Dimension& dim, BitmapPixelFormat pixelFormat)
512 {
513         int bytesPerPixel = 0;
514
515         switch (pixelFormat)
516         {
517         case BITMAP_PIXEL_FORMAT_RGB565:
518                 bytesPerPixel = 2;
519                 break;
520         case BITMAP_PIXEL_FORMAT_ARGB8888:
521         case BITMAP_PIXEL_FORMAT_R8G8B8A8:
522                 bytesPerPixel = 4;
523                 break;
524         default:
525                 return E_SYSTEM;
526         }
527
528         // SysAssert(bytesPerPixel > 0);
529
530         int width = dim.width;
531         int height = dim.height;
532
533         {
534                 size_t allocSize = width * height * bytesPerPixel;
535
536                 std::unique_ptr<unsigned char[]> pAllocated(new (std::nothrow) unsigned char[allocSize]);
537
538                 SysTryReturnResult(NID_GRP, pAllocated, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The bitmap memory is insufficient");
539
540                 result r = this->Construct((void*) pAllocated.get(), width, height, bytesPerPixel * 8);
541
542                 SysTryReturnResult(NID_GRP, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
543
544                 memcpy(pAllocated.get(), buffer.GetPointer(), allocSize);
545
546                 this->__hasOwnership = true;
547
548                 this->__isOpaqueAllOver = _IsOpaqueAllOver(this);
549
550                 this->__bitmapPixelFormat = pixelFormat;
551
552                 pAllocated.release();
553
554                 return r;
555         }
556 }
557
558 result
559 _Bitmap::Construct(const byte* pBuffer, int bufSize, const Dimension& dim, BitmapPixelFormat pixelFormat)
560 {
561         // already checks all parameters
562
563         // BitmapInterfaceCreator bitmapInterface(pBuffer, bufSize, dim.width, dim.height, pixelFormat);
564         // result r = bitmapInterface.Result();
565         // __pBitmapInterface = (r == E_SUCCESS) ? bitmapInterface.GetDuplicate() : null;
566
567         int bytesPerPixel = 0;
568
569         switch (pixelFormat)
570         {
571         case BITMAP_PIXEL_FORMAT_RGB565:
572                 bytesPerPixel = 2;
573                 break;
574         case BITMAP_PIXEL_FORMAT_ARGB8888:
575         case BITMAP_PIXEL_FORMAT_R8G8B8A8:
576                 bytesPerPixel = 4;
577                 break;
578         default:
579                 return E_SYSTEM;
580         }
581
582         // SysAssert(bytesPerPixel > 0);
583
584         int width = dim.width;
585         int height = dim.height;
586
587         {
588                 result r = this->Construct((void*) pBuffer, width, height, bytesPerPixel * 8);
589
590                 if (r == E_SUCCESS)
591                 {
592                         __hasOwnership = true;
593                 }
594
595                 this->__isOpaqueAllOver = _IsOpaqueAllOver(this);
596
597                 this->__bitmapPixelFormat = pixelFormat;
598
599                 return r;
600         }
601 }
602
603 result
604 _Bitmap::Construct(const void* pExtBuffer, int width, int height, int bitsPerPixel)
605 {
606         switch (bitsPerPixel)
607         {
608         case 16:
609         {
610                 typedef unsigned short Pixel;
611
612                 __pScratchPad16 = new (std::nothrow) _Util::ScratchPad<Pixel>((Pixel*) pExtBuffer, width, height, width);
613                 __pBuffer = (unsigned char*) pExtBuffer;
614         }
615                 break;
616         case 32:
617         {
618                 typedef unsigned long Pixel;
619
620                 __pScratchPad32 = new (std::nothrow) _Util::ScratchPad<Pixel>((Pixel*) pExtBuffer, width, height, width);
621                 __pBuffer = (unsigned char*) pExtBuffer;
622         }
623                 break;
624         default:
625                 return E_SYSTEM;
626         }
627
628         SysTryReturnResult(NID_GRP, __pScratchPad16 || __pScratchPad32, E_OUT_OF_MEMORY, "The memory is insufficient");
629
630         this->__hasOwnership = false;
631         this->__isOpaqueAllOver = true;
632
633         this->__bitmapPixelFormat = (bitsPerPixel == 32) ? BITMAP_PIXEL_FORMAT_ARGB8888 : BITMAP_PIXEL_FORMAT_RGB565;
634
635         return E_SUCCESS;
636 }
637
638 bool
639 _Bitmap::IsValid(void) const
640 {
641         return (__pScratchPad16 || __pScratchPad32);
642 }
643
644 void
645 _Bitmap::_SetOwnership(bool ownership)
646 {
647         this->__hasOwnership = ownership;
648 }
649
650 void
651 _Bitmap::_ChangeBuffer(bool ownership, unsigned char* pBuffer)
652 {
653         if (this->__hasOwnership)
654         {
655                 delete[] this->__pBuffer;
656         }
657
658         this->__hasOwnership = ownership;
659         this->__pBuffer = pBuffer;
660 }
661
662 result
663 _Bitmap::Scale(const Dimension& dim)
664 {
665         SysTryReturnResult(NID_GRP, this->IsValid(), E_OPERATION_FAILED, "This instance is not constructed yet.\n");
666
667         SysTryReturnResult(NID_GRP, dim.width > 0 && dim.height > 0, E_OUT_OF_RANGE, "Both of width(%d) and height(%d) MUST be greater than 0.\n", dim.width, dim.height);
668
669         switch (this->__scalingQuality)
670         {
671         case BITMAP_SCALING_QUALITY_MID:
672         case BITMAP_SCALING_QUALITY_HIGH:
673                 return this->__ScaleEx(dim.width, dim.height, this->__scalingQuality);
674         default:
675                 return this->__Scale(dim.width, dim.height);
676         }
677 }
678
679 result
680 _Bitmap::ScaleEx(const Dimension& dim, BitmapScalingQuality quality)
681 {
682         SysTryReturnResult(NID_GRP, this->IsValid(), E_OPERATION_FAILED, "This instance is not constructed yet.\n");
683
684         SysTryReturnResult(NID_GRP, dim.width > 0 && dim.height > 0, E_OUT_OF_RANGE, "Both of width(%d) and height(%d) MUST be greater than 0.\n", dim.width, dim.height);
685
686         switch (quality)
687         {
688         case BITMAP_SCALING_QUALITY_HIGH:
689         case BITMAP_SCALING_QUALITY_MID:
690                 return this->__ScaleEx(dim.width, dim.height, quality);
691         case BITMAP_SCALING_QUALITY_LOW:
692         default:
693                 return this->__Scale(dim.width, dim.height);
694         }
695 }
696
697 result
698 _Bitmap::Merge(const Point& dest, const _Bitmap& src, const Rectangle& srcRect)
699 {
700         // check arg.
701         SysTryReturnResult(NID_GRP, this->IsValid(), E_OPERATION_FAILED, "This instance is not constructed yet.\n");
702
703         if ((srcRect.width == 0) || (srcRect.height == 0))
704         {
705                 return E_SUCCESS;
706         }
707
708         Rectangle rtBitmap(0, 0, src.GetWidth(), src.GetHeight());
709
710         if (!_CheckValidity(srcRect, rtBitmap))
711         {
712                 return E_SUCCESS;
713         }
714
715         // TODO, shkim, I'm not sure why it's E_OUT_OF_RANGE?
716         // TryReturnI(NID_GRP, srcRect.x >= 0 && srcRect.y >= 0, E_OUT_OF_RANGE, "the argument is out of range.\n");
717
718         SysTryReturnResult(NID_GRP, src.IsValid(), E_INVALID_ARG, "The specified source bitmap is invalid.\n");
719
720         result r = this->__Merge(dest.x, dest.y, src, srcRect.x, srcRect.y, srcRect.width, srcRect.height);
721
722         if (this->__isOpaqueAllOver != src.__isOpaqueAllOver)
723         {
724                 this->__isOpaqueAllOver = _IsOpaqueAllOver(this, &_Bitmap::__Lock, &_Bitmap::__Unlock);
725         }
726
727         return r;
728 }
729
730 int
731 _Bitmap::GetHeight() const
732 {
733         SysTryReturn(NID_GRP, this->IsValid(), -1, E_OPERATION_FAILED, "[E_OPERATION_FAILED] This instance is not constructed yet.\n");
734
735         if (__pScratchPad16)
736         {
737                 return __pScratchPad16->GetHeight();
738         }
739         else
740         {
741                 return __pScratchPad32->GetHeight();
742         }
743 }
744
745 int
746 _Bitmap::GetWidth() const
747 {
748         SysTryReturn(NID_GRP, this->IsValid(), -1, E_OPERATION_FAILED, "[E_OPERATION_FAILED] This instance is not constructed yet.\n");
749
750         if (__pScratchPad16)
751         {
752                 return __pScratchPad16->GetWidth();
753         }
754         else
755         {
756                 return __pScratchPad32->GetWidth();
757         }
758 }
759
760 int
761 _Bitmap::GetBitsPerPixel() const
762 {
763         SysTryReturn(NID_GRP, this->IsValid(), -1, E_OPERATION_FAILED, "[E_OPERATION_FAILED] This instance is not constructed yet.\n");
764
765         if (__pScratchPad16)
766         {
767                 return 16;
768         }
769         else
770         {
771                 return 32;
772         }
773 }
774
775 BitmapPixelFormat
776 _Bitmap::GetPixelColorFormat() const
777 {
778         SysTryReturn(NID_GRP, this->IsValid(), BITMAP_PIXEL_FORMAT_MAX, E_OPERATION_FAILED, "[E_OPERATION_FAILED] This instance is not constructed yet.\n");
779
780         return this->__bitmapPixelFormat;
781 }
782
783 result
784 _Bitmap::SetMaskingColor(const Color* pColor)
785 {
786         SysTryReturnResult(NID_GRP, this->IsValid(), E_OPERATION_FAILED, "This instance is not constructed yet.\n");
787         SysTryReturnResult(NID_GRP, this->GetPixelColorFormat() == BITMAP_PIXEL_FORMAT_RGB565, E_INVALID_ARG, "Only BitmapPixelFormat::BITMAP_PIXEL_FORMAT_RGB565 is supported\n");
788
789         if (pColor)
790         {
791                 __hasMaskingColor = true;
792                 __maskingColor = pColor->GetRGB32();
793         }
794         else
795         {
796                 __hasMaskingColor = false;
797                 __maskingColor = 0;
798         }
799
800         return E_SUCCESS;
801 }
802
803 result
804 _Bitmap::GetMaskingColor(Color& color) const
805 {
806         SysTryReturnResult(NID_GRP, this->IsValid(), E_OPERATION_FAILED, "This instance is not constructed yet.\n");
807         SysTryReturnResult(NID_GRP, this->GetPixelColorFormat() == BITMAP_PIXEL_FORMAT_RGB565, E_INVALID_DATA, "Only BitmapPixelFormat::BITMAP_PIXEL_FORMAT_RGB565 is supported\n");
808
809         if (!__hasMaskingColor)
810         {
811                 return E_INVALID_DATA;
812         }
813
814         color = Color(__maskingColor);
815
816         return E_SUCCESS;
817 }
818
819 void
820 _Bitmap::SetAlphaConstant(int opacity)
821 {
822         if (opacity < 0)
823         {
824                 opacity = 0;
825         }
826
827         if (opacity > 255)
828         {
829                 opacity = 255;
830         }
831
832         this->__opacity = opacity;
833 }
834
835 int
836 _Bitmap::GetAlphaConstant(void) const
837 {
838         return this->__opacity;
839 }
840
841 void
842 _Bitmap::SetScalingQuality(BitmapScalingQuality quality)
843 {
844         switch (quality)
845         {
846         case BITMAP_SCALING_QUALITY_LOW:
847         case BITMAP_SCALING_QUALITY_MID:
848         case BITMAP_SCALING_QUALITY_HIGH:
849                 this->__scalingQuality = quality;
850                 break;
851         default:
852                 break;
853         }
854 }
855
856 BitmapScalingQuality
857 _Bitmap::GetScalingQuality(void) const
858 {
859         return this->__scalingQuality;
860 }
861
862 bool
863 _Bitmap::IsNinePatchedBitmap(void) const
864 {
865         SysTryReturn(NID_GRP, this->IsValid(), false, E_OPERATION_FAILED, "[E_OPERATION_FAILED] This instance is not constructed yet.\n");
866
867         BufferInfo dstBufferInfo;
868         bool ret = false;
869
870         if (const_cast<_Bitmap*>(this)->Lock(dstBufferInfo) == E_SUCCESS)
871         {
872                 const Tizen::Graphics::_Util::Pixmap dstImage(dstBufferInfo.width, dstBufferInfo.height, dstBufferInfo.bitsPerPixel, dstBufferInfo.pPixels, dstBufferInfo.pitch);
873                 ret = Tizen::Graphics::_Effect::IsNinePatchedBitmap(dstImage);
874
875                 const_cast<_Bitmap*>(this)->Unlock();
876         }
877
878         return ret;
879 }
880
881 result
882 _Bitmap::Lock(BufferInfo& info, long timeout)
883 {
884         SysTryReturnResult(NID_GRP, this->IsValid(), E_OPERATION_FAILED, "This instance is not constructed yet.\n");
885
886         if (this->__pLockCallbackFunc)
887         {
888                 this->__pLockCallbackFunc(this->__pLockCallbackParam);
889         }
890
891         return this->__Lock(info, timeout);
892 }
893
894 result
895 _Bitmap::Unlock()
896 {
897         SysTryReturnResult(NID_GRP, this->IsValid(), E_OPERATION_FAILED, "This instance is not constructed yet.\n");
898
899         result r = this->__Unlock();
900
901         this->__isOpaqueAllOver = _IsOpaqueAllOver(this, &_Bitmap::__Lock, &_Bitmap::__Unlock);
902
903         if (this->__pUnlockCallbackFunc)
904         {
905                 this->__pUnlockCallbackFunc(this->__pUnlockCallbackParam);
906         }
907
908         return r;
909 }
910
911 result
912 _Bitmap::LockFast(BufferInfo& info, long timeout)
913 {
914         SysTryReturnResult(NID_GRP, this->IsValid(), E_OPERATION_FAILED, "This instance is not constructed yet.\n");
915
916         if (this->__pLockCallbackFunc)
917         {
918                 this->__pLockCallbackFunc(this->__pLockCallbackParam);
919         }
920
921         return this->__Lock(info, timeout);
922 }
923
924 result
925 _Bitmap::UnlockFast()
926 {
927         SysTryReturnResult(NID_GRP, this->IsValid(), E_OPERATION_FAILED, "This instance is not constructed yet.\n");
928
929         result r = this->__Unlock();
930
931         if (this->__pUnlockCallbackFunc)
932         {
933                 this->__pUnlockCallbackFunc(this->__pUnlockCallbackParam);
934         }
935
936         return r;
937 }
938
939 void
940 _Bitmap::UpdateOpaqueInfo(void)
941 {
942         if (this->IsValid())
943         {
944                 this->__isOpaqueAllOver = _IsOpaqueAllOver(this, &_Bitmap::__Lock, &_Bitmap::__Unlock);
945         }
946 }
947
948 void
949 _Bitmap::SetTimeStamp(unsigned long timeStamp)
950 {
951         __timeStamp = timeStamp;
952 }
953
954 int
955 _Bitmap::GetTimeStamp(void) const
956 {
957         return __timeStamp;
958 }
959
960 bool
961 _Bitmap::IsPremultiplied(void) const
962 {
963         return __isPremultiplied;
964 }
965
966 void
967 _Bitmap::AssignUserBuffer(unsigned char* pExtBuffer, int bytesPerLine)
968 {
969         if (this->__pScratchPad32)
970         {
971                 typedef unsigned long Pixel;
972
973                 _Util::ScratchPad<Pixel>* pBackupScratchPad32 = __pScratchPad32;
974
975                 __pScratchPad32 = new (std::nothrow) _Util::ScratchPad<Pixel>((Pixel*) pExtBuffer, pBackupScratchPad32->GetWidth(), pBackupScratchPad32->GetHeight(), bytesPerLine / sizeof(Pixel));
976
977                 if (__pScratchPad32 == null)
978                 {
979                         __pScratchPad32 = pBackupScratchPad32;
980                         return;
981                 }
982
983                 delete pBackupScratchPad32;
984
985                 this->_ChangeBuffer(false, pExtBuffer);
986         }
987         else if (this->__pScratchPad16)
988         {
989                 typedef unsigned short Pixel;
990
991                 _Util::ScratchPad<Pixel>* pBackupScratchPad16 = __pScratchPad16;
992
993                 __pScratchPad16 = new (std::nothrow) _Util::ScratchPad<Pixel>((Pixel*) pExtBuffer, pBackupScratchPad16->GetWidth(), pBackupScratchPad16->GetHeight(), bytesPerLine / sizeof(Pixel));
994
995                 if (__pScratchPad16 == null)
996                 {
997                         __pScratchPad16 = pBackupScratchPad16;
998                         return;
999                 }
1000
1001                 delete pBackupScratchPad16;
1002
1003                 this->_ChangeBuffer(false, pExtBuffer);
1004         }
1005 }
1006
1007 void
1008 _Bitmap::SetCallback(void (* LockCallback)(void*), void* pLockCallbackParam,
1009                      void (* UnlockCallback)(void*), void* pUnlockCallbackParam)
1010 {
1011         this->__pLockCallbackFunc = LockCallback;
1012         this->__pLockCallbackParam = pLockCallbackParam;
1013
1014         this->__pUnlockCallbackFunc = UnlockCallback;
1015         this->__pUnlockCallbackParam = pUnlockCallbackParam;
1016 }
1017
1018 result
1019 _Bitmap::__Scale(int width, int height)
1020 {
1021         SysAssert(!(__pScratchPad16 == null && __pScratchPad32 == null));
1022
1023         if (__pScratchPad16)
1024         {
1025                 return _Resize<unsigned short>(this, __pScratchPad16, width, height);
1026         }
1027         else
1028         {
1029                 //?? the alpha channel is applied twice in the 32-bit bitmap
1030                 return _Resize<unsigned long>(this, __pScratchPad32, width, height);
1031         }
1032 }
1033
1034 result
1035 _Bitmap::__ScaleEx(int width, int height, BitmapScalingQuality quality)
1036 {
1037         SysAssert(!(__pScratchPad16 == null && __pScratchPad32 == null));
1038
1039         if (__pScratchPad16)
1040         {
1041                 return _Resize<unsigned short>(this, __pScratchPad16, width, height, quality);
1042         }
1043         else
1044         {
1045                 return _Resize<unsigned long>(this, __pScratchPad32, width, height, quality);
1046         }
1047 }
1048
1049 result
1050 _Bitmap::__Merge(int destX, int destY, const _Bitmap& src, int srcX, int srcY, int srcWidth, int srcHeight)
1051 {
1052         SysAssert(!(__pScratchPad16 == null && __pScratchPad32 == null));
1053
1054         const _Bitmap* pSrcBitmap = &src;
1055
1056         if (pSrcBitmap == null)
1057         {
1058                 return E_SYSTEM;
1059         }
1060
1061         if (pSrcBitmap->__pScratchPad16 == null && pSrcBitmap->__pScratchPad32 == null)
1062         {
1063                 return E_SYSTEM;
1064         }
1065
1066         if (__pScratchPad16)
1067         {
1068                 if (pSrcBitmap->__pScratchPad16)
1069                 {
1070                         __pScratchPad16->BitBlt(destX, destY, pSrcBitmap->__pScratchPad16, srcX, srcY, srcWidth, srcHeight);
1071
1072                         return E_SUCCESS;
1073                 }
1074                 else
1075                 {
1076                         return _MergeWithConversion(__pScratchPad16, destX, destY, pSrcBitmap->__pScratchPad32, srcX, srcY, srcWidth, srcHeight);
1077                 }
1078         }
1079         else
1080         {
1081                 if (pSrcBitmap->__pScratchPad32)
1082                 {
1083                         __pScratchPad32->BitBlt(destX, destY, pSrcBitmap->__pScratchPad32, srcX, srcY, srcWidth, srcHeight);
1084
1085                         return E_SUCCESS;
1086                 }
1087                 else
1088                 {
1089                         return _MergeWithConversion(__pScratchPad32, destX, destY, pSrcBitmap->__pScratchPad16, srcX, srcY, srcWidth, srcHeight);
1090                 }
1091         }
1092 }
1093
1094 result
1095 _Bitmap::__Lock(BufferInfo& info, long timeout)
1096 {
1097         SysAssert(!(__pScratchPad16 == null && __pScratchPad32 == null));
1098
1099         if (this->__pBuffer == null)
1100         {
1101                 return E_SYSTEM;
1102         }
1103
1104         if (_BufferInfoImpl::GetInstance(info) != null)
1105         {
1106                 _BufferInfoImpl::GetInstance(info)->SetHandle(_BufferInfoImpl::HANDLE_TYPE_NONE, 0);
1107         }
1108
1109         if (__pScratchPad16)
1110         {
1111                 info.width = __pScratchPad16->GetWidth();
1112                 info.height = __pScratchPad16->GetHeight();
1113                 info.pitch = __pScratchPad16->GetWidth() * 2;
1114                 info.bitsPerPixel = 16;
1115                 info.pixelFormat = PIXEL_FORMAT_RGB565;
1116                 info.pPixels = (void*) this->__pBuffer;
1117                 //info.__handle   = INVALID_HANDLE;
1118         }
1119         else
1120         {
1121                 info.width = __pScratchPad32->GetWidth();
1122                 info.height = __pScratchPad32->GetHeight();
1123                 info.pitch = __pScratchPad32->GetWidth() * 4;
1124                 info.bitsPerPixel = 32;
1125                 info.pixelFormat = PIXEL_FORMAT_ARGB8888;
1126                 info.pPixels = (void*) this->__pBuffer;
1127                 //info.__handle   = INVALID_HANDLE;
1128         }
1129
1130         return E_SUCCESS;
1131 }
1132
1133 result
1134 _Bitmap::__Unlock(void)
1135 {
1136         return E_SUCCESS;
1137 }
1138
1139 }} // Tizen::Graphics