Revert " modify license, permission and remove ^M char"
[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(bool checkStrictly) 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
874                 ret = Tizen::Graphics::_Effect::IsNinePatchedBitmap(dstImage, checkStrictly);
875
876                 const_cast<_Bitmap*>(this)->Unlock();
877         }
878
879         return ret;
880 }
881
882 result
883 _Bitmap::Lock(BufferInfo& info, long timeout)
884 {
885         SysTryReturnResult(NID_GRP, this->IsValid(), E_OPERATION_FAILED, "This instance is not constructed yet.\n");
886
887         if (this->__pLockCallbackFunc)
888         {
889                 this->__pLockCallbackFunc(this->__pLockCallbackParam);
890         }
891
892         return this->__Lock(info, timeout);
893 }
894
895 result
896 _Bitmap::Unlock()
897 {
898         SysTryReturnResult(NID_GRP, this->IsValid(), E_OPERATION_FAILED, "This instance is not constructed yet.\n");
899
900         result r = this->__Unlock();
901
902         this->__isOpaqueAllOver = _IsOpaqueAllOver(this, &_Bitmap::__Lock, &_Bitmap::__Unlock);
903
904         if (this->__pUnlockCallbackFunc)
905         {
906                 this->__pUnlockCallbackFunc(this->__pUnlockCallbackParam);
907         }
908
909         return r;
910 }
911
912 result
913 _Bitmap::LockFast(BufferInfo& info, long timeout)
914 {
915         SysTryReturnResult(NID_GRP, this->IsValid(), E_OPERATION_FAILED, "This instance is not constructed yet.\n");
916
917         if (this->__pLockCallbackFunc)
918         {
919                 this->__pLockCallbackFunc(this->__pLockCallbackParam);
920         }
921
922         return this->__Lock(info, timeout);
923 }
924
925 result
926 _Bitmap::UnlockFast()
927 {
928         SysTryReturnResult(NID_GRP, this->IsValid(), E_OPERATION_FAILED, "This instance is not constructed yet.\n");
929
930         result r = this->__Unlock();
931
932         if (this->__pUnlockCallbackFunc)
933         {
934                 this->__pUnlockCallbackFunc(this->__pUnlockCallbackParam);
935         }
936
937         return r;
938 }
939
940 void
941 _Bitmap::UpdateOpaqueInfo(void)
942 {
943         if (this->IsValid())
944         {
945                 this->__isOpaqueAllOver = _IsOpaqueAllOver(this, &_Bitmap::__Lock, &_Bitmap::__Unlock);
946         }
947 }
948
949 void
950 _Bitmap::SetTimeStamp(unsigned long timeStamp)
951 {
952         __timeStamp = timeStamp;
953 }
954
955 int
956 _Bitmap::GetTimeStamp(void) const
957 {
958         return __timeStamp;
959 }
960
961 bool
962 _Bitmap::IsPremultiplied(void) const
963 {
964         return __isPremultiplied;
965 }
966
967 void
968 _Bitmap::AssignUserBuffer(unsigned char* pExtBuffer, int bytesPerLine)
969 {
970         if (this->__pScratchPad32)
971         {
972                 typedef unsigned long Pixel;
973
974                 _Util::ScratchPad<Pixel>* pBackupScratchPad32 = __pScratchPad32;
975
976                 __pScratchPad32 = new (std::nothrow) _Util::ScratchPad<Pixel>((Pixel*) pExtBuffer, pBackupScratchPad32->GetWidth(), pBackupScratchPad32->GetHeight(), bytesPerLine / sizeof(Pixel));
977
978                 if (__pScratchPad32 == null)
979                 {
980                         __pScratchPad32 = pBackupScratchPad32;
981                         return;
982                 }
983
984                 delete pBackupScratchPad32;
985
986                 this->_ChangeBuffer(false, pExtBuffer);
987         }
988         else if (this->__pScratchPad16)
989         {
990                 typedef unsigned short Pixel;
991
992                 _Util::ScratchPad<Pixel>* pBackupScratchPad16 = __pScratchPad16;
993
994                 __pScratchPad16 = new (std::nothrow) _Util::ScratchPad<Pixel>((Pixel*) pExtBuffer, pBackupScratchPad16->GetWidth(), pBackupScratchPad16->GetHeight(), bytesPerLine / sizeof(Pixel));
995
996                 if (__pScratchPad16 == null)
997                 {
998                         __pScratchPad16 = pBackupScratchPad16;
999                         return;
1000                 }
1001
1002                 delete pBackupScratchPad16;
1003
1004                 this->_ChangeBuffer(false, pExtBuffer);
1005         }
1006 }
1007
1008 void
1009 _Bitmap::SetCallback(void (* LockCallback)(void*), void* pLockCallbackParam,
1010                      void (* UnlockCallback)(void*), void* pUnlockCallbackParam)
1011 {
1012         this->__pLockCallbackFunc = LockCallback;
1013         this->__pLockCallbackParam = pLockCallbackParam;
1014
1015         this->__pUnlockCallbackFunc = UnlockCallback;
1016         this->__pUnlockCallbackParam = pUnlockCallbackParam;
1017 }
1018
1019 result
1020 _Bitmap::__Scale(int width, int height)
1021 {
1022         SysAssert(!(__pScratchPad16 == null && __pScratchPad32 == null));
1023
1024         if (__pScratchPad16)
1025         {
1026                 return _Resize<unsigned short>(this, __pScratchPad16, width, height);
1027         }
1028         else
1029         {
1030                 //?? the alpha channel is applied twice in the 32-bit bitmap
1031                 return _Resize<unsigned long>(this, __pScratchPad32, width, height);
1032         }
1033 }
1034
1035 result
1036 _Bitmap::__ScaleEx(int width, int height, BitmapScalingQuality quality)
1037 {
1038         SysAssert(!(__pScratchPad16 == null && __pScratchPad32 == null));
1039
1040         if (__pScratchPad16)
1041         {
1042                 return _Resize<unsigned short>(this, __pScratchPad16, width, height, quality);
1043         }
1044         else
1045         {
1046                 return _Resize<unsigned long>(this, __pScratchPad32, width, height, quality);
1047         }
1048 }
1049
1050 result
1051 _Bitmap::__Merge(int destX, int destY, const _Bitmap& src, int srcX, int srcY, int srcWidth, int srcHeight)
1052 {
1053         SysAssert(!(__pScratchPad16 == null && __pScratchPad32 == null));
1054
1055         const _Bitmap* pSrcBitmap = &src;
1056
1057         if (pSrcBitmap == null)
1058         {
1059                 return E_SYSTEM;
1060         }
1061
1062         if (pSrcBitmap->__pScratchPad16 == null && pSrcBitmap->__pScratchPad32 == null)
1063         {
1064                 return E_SYSTEM;
1065         }
1066
1067         if (__pScratchPad16)
1068         {
1069                 if (pSrcBitmap->__pScratchPad16)
1070                 {
1071                         __pScratchPad16->BitBlt(destX, destY, pSrcBitmap->__pScratchPad16, srcX, srcY, srcWidth, srcHeight);
1072
1073                         return E_SUCCESS;
1074                 }
1075                 else
1076                 {
1077                         return _MergeWithConversion(__pScratchPad16, destX, destY, pSrcBitmap->__pScratchPad32, srcX, srcY, srcWidth, srcHeight);
1078                 }
1079         }
1080         else
1081         {
1082                 if (pSrcBitmap->__pScratchPad32)
1083                 {
1084                         __pScratchPad32->BitBlt(destX, destY, pSrcBitmap->__pScratchPad32, srcX, srcY, srcWidth, srcHeight);
1085
1086                         return E_SUCCESS;
1087                 }
1088                 else
1089                 {
1090                         return _MergeWithConversion(__pScratchPad32, destX, destY, pSrcBitmap->__pScratchPad16, srcX, srcY, srcWidth, srcHeight);
1091                 }
1092         }
1093 }
1094
1095 result
1096 _Bitmap::__Lock(BufferInfo& info, long timeout)
1097 {
1098         SysAssert(!(__pScratchPad16 == null && __pScratchPad32 == null));
1099
1100         if (this->__pBuffer == null)
1101         {
1102                 return E_SYSTEM;
1103         }
1104
1105         if (_BufferInfoImpl::GetInstance(info) != null)
1106         {
1107                 _BufferInfoImpl::GetInstance(info)->SetHandle(_BufferInfoImpl::HANDLE_TYPE_NONE, 0);
1108         }
1109
1110         if (__pScratchPad16)
1111         {
1112                 info.width = __pScratchPad16->GetWidth();
1113                 info.height = __pScratchPad16->GetHeight();
1114                 info.pitch = __pScratchPad16->GetWidth() * 2;
1115                 info.bitsPerPixel = 16;
1116                 info.pixelFormat = PIXEL_FORMAT_RGB565;
1117                 info.pPixels = (void*) this->__pBuffer;
1118                 //info.__handle   = INVALID_HANDLE;
1119         }
1120         else
1121         {
1122                 info.width = __pScratchPad32->GetWidth();
1123                 info.height = __pScratchPad32->GetHeight();
1124                 info.pitch = __pScratchPad32->GetWidth() * 4;
1125                 info.bitsPerPixel = 32;
1126                 info.pixelFormat = PIXEL_FORMAT_ARGB8888;
1127                 info.pPixels = (void*) this->__pBuffer;
1128                 //info.__handle   = INVALID_HANDLE;
1129         }
1130
1131         return E_SUCCESS;
1132 }
1133
1134 result
1135 _Bitmap::__Unlock(void)
1136 {
1137         return E_SUCCESS;
1138 }
1139
1140 }} // Tizen::Graphics