Fork for IVI: mesa fixing
[profile/ivi/uifw.git] / src / graphics / FGrp_BitmapImpl.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_BitmapImpl.cpp
20  * @brief       This is the implementation file for _BitmapImpl class.
21  *
22  */
23
24 #include <new>
25 #include <memory>
26 #include <utility>
27
28 #include <FBaseSysLog.h>
29 #include <FIoFile.h>
30
31 #include <FGrpBitmap.h>
32
33 #include <FMedia_ImageDecoder.h>
34
35 #include "FGrp_BitmapImpl.h"
36 #include "FGrp_BitmapUtil.h"
37 #include "FGrp_BitmapCoordHolder.h"
38 #include "FGrp_Bitmap.h"
39 #include "FGrp_Canvas.h"
40 #include "FGrp_NonScale.h"
41 #include "FGrp_ResUtil.h"
42 #include "util/FGrp_Util.h"
43 #include "effect/FGrp_Effect.h"
44 #include "effect/FGrp_EffectFunc.h"
45
46 using namespace Tizen::Base;
47
48 #define INSTANCE_IS_VALID (this && const_cast<_BitmapImpl*>(this)->__CheckValidity())
49 #define BITMAPIMPL_IS_VALID(pBitmapImpl) (pBitmapImpl && const_cast<_BitmapImpl*>(pBitmapImpl)->__CheckValidity(true))
50 #define IS_BITMAPIMPL_VALID(pBitmapImpl) (pBitmapImpl && const_cast<_BitmapImpl*>(pBitmapImpl)->__CheckValidity(false))
51
52
53 namespace // unnamed
54 {
55
56 bool
57 _CheckValidityOfRectangle(const Tizen::Graphics::Rectangle& rect)
58 {
59         return ((rect.width > 0) && (rect.height > 0));
60 }
61
62 bool
63 _CheckValidity(const Tizen::Graphics::Rectangle& rtSrc, const Tizen::Graphics::Rectangle& rtDest)
64 {
65         // check 1. is width/height less or equal than 0?
66         if (rtSrc.width <= 0 || rtSrc.height <= 0 || rtDest.width <= 0 || rtDest.height <= 0)
67         {
68                 return false;     // "[E_OUT_OF_RANGE] The argument is out of range. (src(w:%d,h:%d), dst(w:%d,h:%d))", rtSrc.width, rtSrc.height, rtDest.width, rtDest.height);
69         }
70
71         // check 2.     is src exiting outside of dest entirely?
72         if (rtSrc.x > rtDest.x + rtDest.width - 1 || rtSrc.x + rtSrc.width - 1 < rtDest.x)
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))", rtSrc.x, rtSrc.y, rtSrc.width, rtSrc.height, rtDest.x, rtDest.y, rtDest.width, rtDest.height);
75         }
76
77         if (rtSrc.y > rtDest.y + rtDest.height - 1 || rtSrc.y + rtSrc.height - 1 < rtDest.y)
78         {
79                 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))", rtSrc.x, rtSrc.y, rtSrc.width, rtSrc.height, rtDest.x, rtDest.y, rtDest.width, rtDest.height);
80         }
81
82         return true;
83 }
84
85 int
86 _GetBytesPerPixel(Tizen::Graphics::BitmapPixelFormat pixelFormat)
87 {
88         if (pixelFormat == Tizen::Graphics::BITMAP_PIXEL_FORMAT_RGB565)
89         {
90                 return 2;
91         }
92         else if (pixelFormat == Tizen::Graphics::BITMAP_PIXEL_FORMAT_ARGB8888 || pixelFormat == Tizen::Graphics::BITMAP_PIXEL_FORMAT_R8G8B8A8)
93         {
94                 return 4;
95         }
96         else
97         {
98                 return 0;
99         }
100 }
101
102 result
103 _CheckBufferSize(const Tizen::Base::ByteBuffer& buffer, const Tizen::Graphics::Dimension& dim, Tizen::Graphics::BitmapPixelFormat pixelFormat)
104 {
105         int bytePerPixel = _GetBytesPerPixel(pixelFormat);
106
107         if (bytePerPixel == 0)
108         {
109                 SysTryReturnResult(NID_GRP, 0, E_INVALID_ARG, "BitmapPixelFormat(%d) is the invalid argument.", pixelFormat);
110         }
111
112         int byteNum = buffer.GetLimit();
113         int expectedBufferSize = dim.width * dim.height * bytePerPixel;
114
115         SysTryReturnResult(NID_GRP, expectedBufferSize <= byteNum, E_INVALID_ARG, "A buffer size is not correct. (expected: %d, actual: %d)", expectedBufferSize, byteNum);
116
117         return E_SUCCESS;
118 }
119
120 bool
121 _ScaleBuffer(const Tizen::Base::ByteBuffer& destBuffer, const Tizen::Graphics::Dimension& destSize, const Tizen::Base::ByteBuffer& sourBuffer, const Tizen::Graphics::Dimension& sourSize, Tizen::Graphics::BitmapPixelFormat pixelFormat)
122 {
123         switch (pixelFormat)
124         {
125         case Tizen::Graphics::BITMAP_PIXEL_FORMAT_RGB565:
126         {
127                 Tizen::Graphics::_Util::Pixmap dstImage(destSize.width, destSize.height, 16, (void*) destBuffer.GetPointer());
128                 Tizen::Graphics::_Util::Pixmap srcImage(sourSize.width, sourSize.height, 16, (void*) sourBuffer.GetPointer());
129                 return Tizen::Graphics::_Effect::ScaleImage(dstImage, 0, 0, destSize.width, destSize.height, srcImage);
130         }
131         case Tizen::Graphics::BITMAP_PIXEL_FORMAT_ARGB8888:
132         {
133                 Tizen::Graphics::_Util::Pixmap dstImage(destSize.width, destSize.height, 32, (void*) destBuffer.GetPointer());
134                 Tizen::Graphics::_Util::Pixmap srcImage(sourSize.width, sourSize.height, 32, (void*) sourBuffer.GetPointer());
135                 return Tizen::Graphics::_Effect::ScaleImage(dstImage, 0, 0, destSize.width, destSize.height, srcImage);
136         }
137         case Tizen::Graphics::BITMAP_PIXEL_FORMAT_R8G8B8A8:
138                 return false;
139         default:
140                 return false;
141         }
142 }
143
144 bool
145 _UpdateScaledBitmapEx(Tizen::Graphics::_Bitmap* pSrcBitmap, Tizen::Graphics::_Bitmap* pDstBitmap)
146 {
147         if (!(pSrcBitmap && pDstBitmap && pSrcBitmap->GetPixelColorFormat() == pDstBitmap->GetPixelColorFormat()))
148         {
149                 return false;
150         }
151
152         Tizen::Graphics::BufferInfo srcBufferInfo;
153         Tizen::Graphics::BufferInfo dstBufferInfo;
154
155         {
156                 if (pSrcBitmap->Lock(srcBufferInfo) != E_SUCCESS)
157                 {
158                         return false;
159                 }
160
161                 result r = pDstBitmap->Lock(dstBufferInfo);
162                 if (r != E_SUCCESS)
163                 {
164                         pSrcBitmap->Unlock();
165                         return false;
166                 }
167         }
168
169         bool ret = false;
170
171         do
172         {
173                 switch (pSrcBitmap->GetPixelColorFormat())
174                 {
175                 case Tizen::Graphics::BITMAP_PIXEL_FORMAT_RGB565:
176                 {
177                         Tizen::Graphics::_Util::Pixmap dstImage(dstBufferInfo.width, dstBufferInfo.height, 16, (void*) dstBufferInfo.pPixels);
178                         Tizen::Graphics::_Util::Pixmap srcImage(srcBufferInfo.width, srcBufferInfo.height, 16, (void*) srcBufferInfo.pPixels);
179                         ret = Tizen::Graphics::_Effect::ScaleImage(dstImage, 0, 0, dstBufferInfo.width, dstBufferInfo.height, srcImage);
180                 }
181                 break;
182
183                 case Tizen::Graphics::BITMAP_PIXEL_FORMAT_ARGB8888:
184                 {
185                         Tizen::Graphics::_Util::Pixmap dstImage(dstBufferInfo.width, dstBufferInfo.height, 32, (void*) dstBufferInfo.pPixels);
186                         Tizen::Graphics::_Util::Pixmap srcImage(srcBufferInfo.width, srcBufferInfo.height, 32, (void*) srcBufferInfo.pPixels);
187                         ret = Tizen::Graphics::_Effect::ScaleImage(dstImage, 0, 0, dstBufferInfo.width, dstBufferInfo.height, srcImage);
188                 }
189                 break;
190
191                 case Tizen::Graphics::BITMAP_PIXEL_FORMAT_R8G8B8A8:
192                 default:
193                         break;
194                 }
195         }
196         while (0);
197
198         pSrcBitmap->Unlock();
199         pDstBitmap->Unlock();
200
201         return ret;
202 }
203
204 ////////////////////////////////////////////////////////////////////////////////
205
206 unsigned long
207 _UpdateBitmapTimeStampInternal(void)
208 {
209         static unsigned long staticTimeStamp = 0;
210
211         ++staticTimeStamp;
212
213         staticTimeStamp = (staticTimeStamp == 0) ? (staticTimeStamp + 1) : staticTimeStamp;
214
215         return staticTimeStamp;
216 }
217
218 }
219
220 ////////////////////////////////////////////////////////////////////////////////
221
222 namespace Tizen { namespace Graphics
223 {
224
225 unsigned long
226 _GetBitmapTimeStamp(const Tizen::Graphics::_BitmapImpl& bitmap)
227 {
228         Tizen::Graphics::_Bitmap* _nativeBitmap = Tizen::Graphics::GetBitmapEx(bitmap);
229
230         return (_nativeBitmap) ? _nativeBitmap->GetTimeStamp() : 0;
231 }
232
233 unsigned long
234 _UpdateBitmapTimeStamp(Tizen::Graphics::_BitmapImpl& bitmap)
235 {
236         Tizen::Graphics::_Bitmap* _nativeBitmap = Tizen::Graphics::GetBitmapEx(bitmap);
237
238         if (_nativeBitmap)
239         {
240                 _nativeBitmap->SetTimeStamp(_UpdateBitmapTimeStampInternal());
241                 return _nativeBitmap->GetTimeStamp();
242         }
243
244         return 0;
245 }
246
247 ////////////////////////////////////////////////////////////////////////////////
248
249 _BitmapImpl::_BitmapImpl(void)
250 : _sharedItem(std::tr1::shared_ptr<_SharedItem>(new (std::nothrow)_SharedItem))
251 {
252         if (this->_sharedItem.get())
253         {
254                 this->_sharedItem->nativeBitmap.reset(new (std::nothrow) _Bitmap);
255                 this->_sharedItem->coordHolder.reset(new (std::nothrow) _BitmapCoordHolder);
256                 this->_sharedItem->lazyScaling = 0;
257                 this->_sharedItem->scaledNativeBitmap.reset(null);
258                 this->_sharedItem->pDestroyCallbackFunc = null;
259                 this->_sharedItem->pDestroyCallbackParam = null;
260                 this->_sharedItem->pLockCallbackFunc = null;
261                 this->_sharedItem->pLockCallbackParam = null;
262                 this->_sharedItem->pUnlockCallbackFunc = null;
263                 this->_sharedItem->pUnlockCallbackParam = null;
264                 this->_sharedItem->isMutable = true;
265                 this->_sharedItem->associated.pixelFormat = BITMAP_PIXEL_FORMAT_ARGB8888;
266
267                 if (this->_sharedItem->nativeBitmap.get() == null || this->_sharedItem->coordHolder.get() == null)
268                 {
269                         this->_sharedItem->nativeBitmap.reset();
270                         this->_sharedItem->coordHolder.reset();
271                         this->_sharedItem.reset();
272
273                         return;
274                 }
275         }
276
277         _UpdateBitmapTimeStamp(*this);
278 }
279
280 _BitmapImpl::~_BitmapImpl(void)
281 {
282         if (this->_sharedItem.get())
283         {
284                 if (this->_sharedItem->pDestroyCallbackFunc)
285                 {
286                         if (this->_sharedItem.unique())
287                         {
288                                 this->_sharedItem->pDestroyCallbackFunc(this->_sharedItem->pDestroyCallbackParam);
289                         }
290                 }
291         }
292 }
293
294 bool
295 _BitmapImpl::IsConstructed(void) const
296 {
297         return (this->_sharedItem.get() && (this->_sharedItem->nativeBitmap->IsValid() || !this->_sharedItem->associated.fileName.IsEmpty()));
298 }
299
300 result
301 _BitmapImpl::Construct(const Rectangle& vc_rect)
302 {
303         SysTryReturnResult(NID_GRP, this, E_OUT_OF_MEMORY, "This instance is not allocated yet.");
304
305         SysTryReturnResult(NID_GRP, this->_sharedItem.get(), E_OUT_OF_MEMORY, "Fails to allocate memory.");
306
307         SysTryReturnResult(NID_GRP, _CheckValidityOfRectangle(vc_rect), E_INVALID_ARG, "Both of width(%d) and height(%d) of 'rect' MUST be greater than 0.", vc_rect.width, vc_rect.height);
308
309         SysTryReturnResult(NID_GRP, vc_rect.x >= 0 && vc_rect.y >= 0, E_OUT_OF_RANGE, "The argument is out of range. (rect(x:%d,y:%d,w:%d,h:%d)).", vc_rect.x, vc_rect.y, vc_rect.width, vc_rect.height);
310
311         if (_ResUtil::NeedToConvertCoord())
312         {
313                 Rectangle pc_rect = _ResUtil::ConvertToPhyCoord(vc_rect);
314
315                 // special case
316                 pc_rect.width = (pc_rect.width > 0) ? pc_rect.width : 1;
317                 pc_rect.height = (pc_rect.height > 0) ? pc_rect.height : 1;
318
319                 result r = this->_sharedItem->nativeBitmap->Construct(pc_rect);
320
321                 if (!IsFailed(r))
322                 {
323                         this->_sharedItem->coordHolder->Init(vc_rect);
324                         this->_sharedItem->coordHolder->bitmapSize.phyCoord.w = pc_rect.width;
325                         this->_sharedItem->coordHolder->bitmapSize.phyCoord.h = pc_rect.height;
326                 }
327
328                 return r;
329         }
330         else
331         {
332                 return this->_sharedItem->nativeBitmap->Construct(vc_rect);
333         }
334 }
335
336 result
337 _BitmapImpl::Construct(const Dimension& vc_dim, BitmapPixelFormat pixelFormat)
338 {
339         SysTryReturnResult(NID_GRP, this, E_OUT_OF_MEMORY, "This instance is not allocated yet.");
340
341         SysTryReturnResult(NID_GRP, this->_sharedItem.get(), E_OUT_OF_MEMORY, "Fails to allocate memory.");
342
343         // check arg.
344         SysTryReturnResult(NID_GRP, vc_dim.width > 0 && vc_dim.height > 0, E_INVALID_ARG, "Both of width(%d) and height(%d) of 'dim' MUST be greater than 0.", vc_dim.width, vc_dim.height);
345
346         int size = vc_dim.width * vc_dim.height;
347
348         switch (pixelFormat)
349         {
350         case BITMAP_PIXEL_FORMAT_RGB565:
351                 size *= sizeof(unsigned short);
352                 break;
353         case BITMAP_PIXEL_FORMAT_ARGB8888:
354         case BITMAP_PIXEL_FORMAT_R8G8B8A8:
355                 size *= sizeof(unsigned long);
356                 break;
357         default:
358                 SysTryReturnResult(NID_GRP, 0, E_INVALID_ARG, "BitmapPixelFormat(%d) is invalid argument.", pixelFormat);
359                 break;
360         }
361
362         if (_ResUtil::NeedToConvertCoord())
363         {
364                 Dimension pc_dim = _ResUtil::ConvertToPhyCoord(vc_dim);
365
366                 // special case
367                 pc_dim.width = (pc_dim.width > 0) ? pc_dim.width : 1;
368                 pc_dim.height = (pc_dim.height > 0) ? pc_dim.height : 1;
369
370                 result r = this->_sharedItem->nativeBitmap->Construct(pc_dim, pixelFormat);
371
372                 if (!IsFailed(r))
373                 {
374                         _ResUtil::Rect vc_rect(0, 0, vc_dim.width, vc_dim.height);
375
376                         this->_sharedItem->coordHolder->Init(vc_rect);
377                         this->_sharedItem->coordHolder->bitmapSize.phyCoord.w = pc_dim.width;
378                         this->_sharedItem->coordHolder->bitmapSize.phyCoord.h = pc_dim.height;
379                 }
380
381                 return r;
382         }
383         else
384         {
385                 return this->_sharedItem->nativeBitmap->Construct(vc_dim, pixelFormat);
386         }
387 }
388
389 result
390 _BitmapImpl::Construct(const _CanvasImpl& canvas, const Rectangle& vc_rect)
391 {
392         SysTryReturnResult(NID_GRP, this, E_OUT_OF_MEMORY, "This instance is not allocated yet.");
393
394         SysTryReturnResult(NID_GRP, this->_sharedItem.get(), E_OUT_OF_MEMORY, "Fails to allocate memory.");
395
396         SysTryReturnResult(NID_GRP, &canvas, E_INVALID_ARG, "A canvas is invalid.");
397         SysTryReturnResult(NID_GRP, canvas._pNativeCanvas && canvas._pNativeCanvas->IsValid(), E_INVALID_ARG, "A canvas is invalid.");
398
399         Rectangle rtCanvas = canvas.GetBounds();
400
401         SysTryReturnResult(NID_GRP, !rtCanvas.IsEmpty(), E_INVALID_ARG, "A canvas is empty.");
402
403         SysTryReturnResult(NID_GRP, _CheckValidityOfRectangle(vc_rect), E_INVALID_ARG, "Both of width(%d) and height(%d) of 'rect' MUST be greater than 0.", vc_rect.width, vc_rect.height);
404
405         SysTryReturnResult(NID_GRP, _CheckValidity(vc_rect, rtCanvas), E_OUT_OF_RANGE, "The argument is out of range. (rect(x:%d,y:%d,w:%d,h:%d)).", vc_rect.x, vc_rect.y, vc_rect.width, vc_rect.height);
406
407         Tizen::Graphics::_Canvas* pCanvasEx = canvas._pNativeCanvas;
408
409         if (_ResUtil::NeedToConvertCoord())
410         {
411                 Rectangle pc_rect = _ResUtil::ConvertToPhyCoord(vc_rect);
412
413                 // special case (kiniirana)
414                 pc_rect.width = (pc_rect.width > 0) ? pc_rect.width : 1;
415                 pc_rect.height = (pc_rect.height > 0) ? pc_rect.height : 1;
416
417                 result r = this->_sharedItem->nativeBitmap->Construct(*pCanvasEx, pc_rect);
418
419                 if (!IsFailed(r))
420                 {
421                         this->_sharedItem->coordHolder->Init(vc_rect);
422                 }
423
424                 return r;
425         }
426         else
427         {
428                 return this->_sharedItem->nativeBitmap->Construct(*pCanvasEx, vc_rect);
429         }
430 }
431
432 result
433 _BitmapImpl::Construct(const _BitmapImpl& bitmap, const Rectangle& vc_rect)
434 {
435         SysTryReturnResult(NID_GRP, this, E_OUT_OF_MEMORY, "This instance is not allocated yet.");
436
437         SysTryReturnResult(NID_GRP, this->_sharedItem.get(), E_OUT_OF_MEMORY, "Fails to allocate memory.");
438
439         SysTryReturnResult(NID_GRP, BITMAPIMPL_IS_VALID(&bitmap), E_INVALID_ARG, "The source bitmap is invalid.");
440
441         Rectangle rtBitmap(0, 0, bitmap.GetWidth(), bitmap.GetHeight());
442
443         SysTryReturnResult(NID_GRP, _CheckValidityOfRectangle(vc_rect), E_INVALID_ARG, "Both of width(%d) and height(%d) of 'rect' MUST be greater than 0.", vc_rect.width, vc_rect.height);
444
445         SysTryReturnResult(NID_GRP, _CheckValidity(vc_rect, rtBitmap), E_OUT_OF_RANGE, "The argument is out of range. (rect(x:%d,y:%d,w:%d,h:%d)).", vc_rect.x, vc_rect.y, vc_rect.width, vc_rect.height);
446
447         _Bitmap* pSrcBitmapEx = Tizen::Graphics::GetBitmapEx(bitmap);
448
449         if (_ResUtil::NeedToConvertCoord())
450         {
451                 result r = E_SUCCESS;
452                 Rectangle pc_rect = _ResUtil::ConvertToPhyCoord(vc_rect);
453
454                 // special case
455                 pc_rect.width = (pc_rect.width > 0) ? pc_rect.width : 1;
456                 pc_rect.height = (pc_rect.height > 0) ? pc_rect.height : 1;
457
458                 if (Tizen::Graphics::IsLazyScalingBitmap(bitmap))
459                 {
460                         _Bitmap* pSrcScaledBitmapEx = Tizen::Graphics::GetScaledBitmapEx(bitmap);
461
462                         r = this->_sharedItem->nativeBitmap->Construct(*pSrcScaledBitmapEx, pc_rect);
463                 }
464                 else
465                 {
466                         r = this->_sharedItem->nativeBitmap->Construct(*pSrcBitmapEx, pc_rect);
467                 }
468
469                 if (!IsFailed(r))
470                 {
471                         this->_sharedItem->coordHolder->Init(vc_rect);
472                 }
473
474                 return r;
475         }
476         else
477         {
478                 return this->_sharedItem->nativeBitmap->Construct(*pSrcBitmapEx, vc_rect);
479         }
480 }
481
482 result
483 _BitmapImpl::Construct(const Tizen::Base::ByteBuffer& buffer, const Dimension& rq_dim, BitmapPixelFormat pixelFormat)
484 {
485 #if 1
486         return this->Construct(buffer, rq_dim, pixelFormat, true);
487 #else
488 //      return this->Construct(buffer, rq_dim, pixelFormat, BUFFER_SCALING_AUTO);
489 //      return this->Construct(buffer, rq_dim, pixelFormat, BUFFER_SCALING_NONE);
490
491         SysTryReturnResult(NID_GRP, this, E_OUT_OF_MEMORY, "This instance is not allocated yet.");
492
493         SysTryReturnResult(NID_GRP, __pImpl && this->_nativeBitmap, E_OUT_OF_MEMORY, "Fails to allocate memory.");
494
495         SysTryReturnResult(NID_GRP, rq_dim.width > 0 && rq_dim.height > 0, E_INVALID_ARG, "Both of width(%d) and height(%d) of a dimension MUST be greater than 0.", rq_dim.width, rq_dim.height);
496
497         SysTryReturnResult(NID_GRP, BITMAP_PIXEL_FORMAT_MIN < pixelFormat && pixelFormat < BITMAP_PIXEL_FORMAT_MAX, E_INVALID_ARG, "BitmapPixelFormat(%d) is the invalid argument.", pixelFormat);
498
499         {
500                 // buffer size should be verified.
501                 int bytePerPixel = 0;
502                 if (BITMAP_PIXEL_FORMAT_RGB565 == pixelFormat)
503                 {
504                         bytePerPixel = 2;
505                 }
506                 else if (BITMAP_PIXEL_FORMAT_ARGB8888 == pixelFormat || BITMAP_PIXEL_FORMAT_R8G8B8A8 == pixelFormat)
507                 {
508                         bytePerPixel = 4;
509                 }
510                 else
511                 {
512                         SysTryReturnResult(NID_GRP, 0, E_INVALID_ARG, "BitmapPixelFormat(%d) is the invalid argument.", pixelFormat);
513                 }
514
515                 int byteNum = buffer.GetLimit();
516                 int expectedBufferSize = rq_dim.width * rq_dim.height * bytePerPixel;
517
518                 SysTryReturnResult(NID_GRP, expectedBufferSize <= byteNum, E_INVALID_ARG, "A buffer size is not correct.");
519         }
520
521         if (_ResUtil::NeedToConvertCoord())
522         {
523                 Dimension vc_dim;
524                 Dimension pc_dim;
525
526                 vc_dim = rq_dim;
527                 pc_dim = _ResUtil::ConvertToPhyCoord(vc_dim);
528
529                 // special case
530                 pc_dim.width = (pc_dim.width > 0) ? pc_dim.width : 1;
531                 pc_dim.height = (pc_dim.height > 0) ? pc_dim.height : 1;
532
533                 if (pc_dim.width * 2 == rq_dim.width && pc_dim.height * 2 == rq_dim.height)
534                 {
535                         int pitch = rq_dim.width;
536
537                         if (pixelFormat == BITMAP_PIXEL_FORMAT_ARGB8888)
538                         {
539                                 const unsigned long MASK = 0x00FF00FF;
540
541                                 unsigned long* pBuffer = (unsigned long*) buffer.GetPointer();
542                                 for (int y = 0; y < pc_dim.height; y++)
543                                 {
544                                         for (int x = 0; x < pc_dim.width; x++)
545                                         {
546                                                 unsigned long add1 = (pBuffer[0] & MASK) + (pBuffer[1] & MASK) + (pBuffer[pitch] & MASK) + (pBuffer[pitch + 1] & MASK);
547                                                 unsigned long add2 = ((pBuffer[0] >> 8) & MASK) + ((pBuffer[1] >> 8) & MASK) + ((pBuffer[pitch] >> 8) & MASK) + ((pBuffer[pitch + 1] >> 8) & MASK);
548
549                                                 unsigned long pix = ((add1 >> 2) & MASK) | (((add2 >> 2) & MASK) << 8);
550
551                                                 pBuffer[0] = pix;
552                                                 pBuffer[1] = pix;
553                                                 pBuffer[pitch] = pix;
554                                                 pBuffer[pitch + 1] = pix;
555
556                                                 pBuffer += 2;
557                                         }
558                                         pBuffer += pitch;
559                                 }
560                         }
561                         else if (pixelFormat == BITMAP_PIXEL_FORMAT_RGB565)
562                         {
563                                 const unsigned short MASK1 = 0xF81F;
564                                 const unsigned short MASK2 = 0x07E0;
565                                 const unsigned short CHROMAKEY = 0xF81F | 0x0020;
566
567                                 bool hasChromakey;
568                                 {
569                                         unsigned short* pBuffer = (unsigned short*) buffer.GetPointer();
570                                         unsigned short* pBufferEnd = pBuffer + rq_dim.width * rq_dim.height;
571
572                                         while (pBuffer < pBufferEnd)
573                                         {
574                                                 if (*pBuffer == CHROMAKEY)
575                                                 {
576                                                         break;
577                                                 }
578
579                                                 ++pBuffer;
580                                         }
581
582                                         hasChromakey = (pBuffer < pBufferEnd);
583                                 }
584
585                                 if (hasChromakey)
586                                 {
587                                         ; // pass through default scaling algorithm
588                                 }
589                                 else
590                                 {
591                                         unsigned short* pBuffer = (unsigned short*) buffer.GetPointer();
592
593                                         for (int y = 0; y < pc_dim.height; y++)
594                                         {
595                                                 for (int x = 0; x < pc_dim.width; x++)
596                                                 {
597                                                         unsigned long add1 = (unsigned long) (pBuffer[0] & MASK1) + (unsigned long) (pBuffer[1] & MASK1) + (unsigned long) (pBuffer[pitch] & MASK1) + (unsigned long) (pBuffer[pitch + 1] & MASK1);
598                                                         unsigned long add2 = (pBuffer[0] & MASK2) + (pBuffer[1] & MASK2) + (pBuffer[pitch] & MASK2) + (pBuffer[pitch + 1] & MASK2);
599
600                                                         unsigned long pix = ((add1 >> 2) & MASK1) | ((add2 >> 2) & MASK2);
601
602                                                         pBuffer[0] = pix;
603                                                         pBuffer[1] = pix;
604                                                         pBuffer[pitch] = pix;
605                                                         pBuffer[pitch + 1] = pix;
606
607                                                         pBuffer += 2;
608                                                 }
609                                                 pBuffer += pitch;
610                                         }
611                                 }
612                         }
613                 }
614
615                 result r = this->_nativeBitmap->Construct(buffer, rq_dim, pixelFormat);
616
617                 if (!IsFailed(r))
618                 {
619                         this->_nativeBitmap->Scale(pc_dim);
620
621                         Rect vc_rect(0, 0, vc_dim.width, vc_dim.height);
622                         Rect pc_rect(0, 0, pc_dim.width, pc_dim.height);
623
624                         this->_coordHolder->bitmapSize.required = vc_rect;
625                         this->_coordHolder->bitmapSize.phyCoord = pc_rect;
626                         this->_coordHolder->bitmapSize.virCoord = vc_rect;
627                 }
628
629                 return r;
630         }
631         else
632         {
633                 return this->_nativeBitmap->Construct(buffer, rq_dim, pixelFormat);
634         }
635
636 #endif
637 }
638
639 result
640 _BitmapImpl::Construct(const BufferInfo& bufferInfo)
641 {
642         SysTryReturnResult(NID_GRP, this, E_OUT_OF_MEMORY, "This instance is not allocated yet.");
643
644         SysTryReturnResult(NID_GRP, this->_sharedItem.get(), E_OUT_OF_MEMORY, "Fails to allocate memory.");
645
646         SysTryReturnResult(NID_GRP, (bufferInfo.width > 0) && (bufferInfo.height > 0) && (bufferInfo.pitch > 0)
647                 , E_INVALID_ARG
648                 , "Invalid argument (BufferInfo::width = %d, BufferInfo::height = %d, BufferInfo::pitch = %d)"
649                 , bufferInfo.width, bufferInfo.height, bufferInfo.pitch);
650
651         SysTryReturnResult(NID_GRP, bufferInfo.bitsPerPixel > 0
652                 , E_INVALID_ARG
653                 , "Invalid argument (BufferInfo::bitsPerPixel = %d)"
654                 , bufferInfo.bitsPerPixel);
655
656         SysTryReturnResult(NID_GRP, (bufferInfo.pixelFormat > PIXEL_FORMAT_MIN) && (bufferInfo.pixelFormat < PIXEL_FORMAT_MAX)
657                 , E_INVALID_ARG
658                 , "Invalid argument (BufferInfo::pixelFormat = %d)"
659                 , bufferInfo.pixelFormat);
660
661         SysTryReturnResult(NID_GRP, bufferInfo.pPixels != null
662                 , E_INVALID_ARG
663                 , "Invalid argument (BufferInfo::pPixels = null)");
664
665         SysTryReturnResult(NID_GRP, bufferInfo.bitsPerPixel == 32 || bufferInfo.bitsPerPixel == 16
666                 , E_UNSUPPORTED_FORMAT
667                 , "Unsupported format (BufferInfo::bitsPerPixel = %d)"
668                 , bufferInfo.bitsPerPixel);
669
670         BitmapPixelFormat bitmapPixelFormat = BITMAP_PIXEL_FORMAT_MIN;
671
672         switch (bufferInfo.pixelFormat)
673         {
674         case PIXEL_FORMAT_RGB565:
675                 bitmapPixelFormat = BITMAP_PIXEL_FORMAT_RGB565;
676                 break;
677         case PIXEL_FORMAT_ARGB8888:
678                 bitmapPixelFormat = BITMAP_PIXEL_FORMAT_ARGB8888;
679                 break;
680         case PIXEL_FORMAT_R8G8B8A8:
681                 bitmapPixelFormat = BITMAP_PIXEL_FORMAT_R8G8B8A8;
682                 break;
683         default:
684                 break;
685         }
686
687         SysTryReturnResult(NID_GRP, bitmapPixelFormat != BITMAP_PIXEL_FORMAT_MIN
688                 , E_UNSUPPORTED_FORMAT
689                 , "Unsupported format (BufferInfo::pixelFormat = %d)"
690                 , bufferInfo.pixelFormat);
691
692         result r = this->Construct(static_cast<const byte*>(bufferInfo.pPixels), bufferInfo.pitch * bufferInfo.height, Dimension(bufferInfo.width, bufferInfo.height), bitmapPixelFormat, false);
693
694         SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
695
696         this->_sharedItem->nativeBitmap->_SetOwnership(false);
697
698         return E_SUCCESS;
699 }
700
701 result
702 _BitmapImpl::Construct(const Tizen::Base::ByteBuffer& buffer, const Dimension& rq_dim, BitmapPixelFormat pixelFormat, bool autoScaling)
703 {
704         SysTryReturnResult(NID_GRP, this, E_OUT_OF_MEMORY, "This instance is not allocated yet.");
705
706         SysTryReturnResult(NID_GRP, this->_sharedItem.get(), E_OUT_OF_MEMORY, "Fails to allocate memory.");
707
708         SysTryReturnResult(NID_GRP, rq_dim.width > 0 && rq_dim.height > 0, E_INVALID_ARG, "Both of width(%d) and height(%d) of a dimension MUST be greater than 0.", rq_dim.width, rq_dim.height);
709
710         SysTryReturnResult(NID_GRP, BITMAP_PIXEL_FORMAT_MIN < pixelFormat && pixelFormat < BITMAP_PIXEL_FORMAT_MAX, E_INVALID_ARG, "BitmapPixelFormat(%d) is the invalid argument.", pixelFormat);
711
712         result r = _CheckBufferSize(buffer, rq_dim, pixelFormat);
713
714         if (r != E_SUCCESS)
715         {
716                 return r;
717         }
718
719         if (_ResUtil::NeedToConvertCoord())
720         {
721                 result r = this->_sharedItem->nativeBitmap->Construct(buffer, rq_dim, pixelFormat);
722
723                 if (!IsFailed(r))
724                 {
725                         Dimension vc_dim;
726                         Dimension pc_dim;
727
728                         if (autoScaling)
729                         {
730                                 vc_dim = rq_dim;
731                                 pc_dim = _ResUtil::ConvertToPhyCoord(vc_dim);
732
733                                 // special case
734                                 pc_dim.width = (pc_dim.width > 0) ? pc_dim.width : 1;
735                                 pc_dim.height = (pc_dim.height > 0) ? pc_dim.height : 1;
736
737                                 const BitmapScalingQuality quality = BITMAP_SCALING_QUALITY_LOW;
738
739                                 this->_sharedItem->nativeBitmap->ScaleEx(pc_dim, quality);
740                         }
741                         else
742                         {
743                                 pc_dim = rq_dim;
744                                 vc_dim = _ResUtil::ConvertToVirCoord(pc_dim);
745                         }
746
747                         _ResUtil::Rect vc_rect(0, 0, vc_dim.width, vc_dim.height);
748                         _ResUtil::Rect pc_rect(0, 0, pc_dim.width, pc_dim.height);
749
750                         this->_sharedItem->coordHolder->bitmapSize.required = vc_rect;
751                         this->_sharedItem->coordHolder->bitmapSize.phyCoord = pc_rect;
752                         this->_sharedItem->coordHolder->bitmapSize.virCoord = vc_rect;
753                 }
754
755                 return r;
756         }
757         else
758         {
759                 return this->_sharedItem->nativeBitmap->Construct(buffer, rq_dim, pixelFormat);
760         }
761 }
762
763 result
764 _BitmapImpl::Construct(const byte* pBuffer, int bufSize, const Dimension& rq_dim, BitmapPixelFormat pixelFormat, bool autoScaling)
765 {
766         SysTryReturnResult(NID_GRP, this, E_OUT_OF_MEMORY, "This instance is not allocated yet.");
767
768         SysTryReturnResult(NID_GRP, this->_sharedItem.get(), E_OUT_OF_MEMORY, "Fails to allocate memory.");
769
770         SysTryReturnResult(NID_GRP, pBuffer, E_INVALID_ARG, "The specified buffer pointer is invalid.", rq_dim.width, rq_dim.height);
771
772         SysTryReturnResult(NID_GRP, rq_dim.width > 0 && rq_dim.height > 0, E_INVALID_ARG, "Both of width(%d) and height(%d) of a dimension MUST be greater than 0.", rq_dim.width, rq_dim.height);
773
774         SysTryReturnResult(NID_GRP, pixelFormat > BITMAP_PIXEL_FORMAT_MIN && pixelFormat < BITMAP_PIXEL_FORMAT_MAX, E_INVALID_ARG, "BitmapPixelFormat(%d) is the invalid argument.", pixelFormat);
775
776         SysTryReturnResult(NID_GRP, (bufSize > 0) && (bufSize >= rq_dim.width * rq_dim.height * _GetBytesPerPixel(pixelFormat)), E_INVALID_ARG, "The specified buffer size is too small (buffer size = %d, dim(%d, %d))", bufSize, rq_dim.width, rq_dim.height);
777
778         if (_ResUtil::NeedToConvertCoord())
779         {
780                 result r = this->_sharedItem->nativeBitmap->Construct(pBuffer, bufSize, rq_dim, pixelFormat);
781
782                 if (!IsFailed(r))
783                 {
784                         Dimension vc_dim;
785                         Dimension pc_dim;
786
787                         if (autoScaling)
788                         {
789                                 vc_dim = rq_dim;
790                                 pc_dim = _ResUtil::ConvertToPhyCoord(vc_dim);
791
792                                 // special case
793                                 pc_dim.width = (pc_dim.width > 0) ? pc_dim.width : 1;
794                                 pc_dim.height = (pc_dim.height > 0) ? pc_dim.height : 1;
795
796                                 const BitmapScalingQuality quality = BITMAP_SCALING_QUALITY_LOW;
797
798                                 this->_sharedItem->nativeBitmap->ScaleEx(pc_dim, quality);
799                         }
800                         else
801                         {
802                                 pc_dim = rq_dim;
803                                 vc_dim = _ResUtil::ConvertToVirCoord(pc_dim);
804                         }
805
806                         _ResUtil::Rect vc_rect(0, 0, vc_dim.width, vc_dim.height);
807                         _ResUtil::Rect pc_rect(0, 0, pc_dim.width, pc_dim.height);
808
809                         this->_sharedItem->coordHolder->bitmapSize.required = vc_rect;
810                         this->_sharedItem->coordHolder->bitmapSize.phyCoord = pc_rect;
811                         this->_sharedItem->coordHolder->bitmapSize.virCoord = vc_rect;
812                 }
813
814                 return r;
815         }
816         else
817         {
818                 return this->_sharedItem->nativeBitmap->Construct(pBuffer, bufSize, rq_dim, pixelFormat);
819         }
820 }
821
822 result
823 _BitmapImpl::Construct(const Tizen::Base::ByteBuffer& buffer, const Dimension& rq_dim, BitmapPixelFormat pixelFormat, BufferScaling bufferScaling)
824 {
825         SysTryReturnResult(NID_GRP, this, E_OUT_OF_MEMORY, "This instance is not allocated yet.");
826
827         SysTryReturnResult(NID_GRP, this->_sharedItem.get(), E_OUT_OF_MEMORY, "Fails to allocate memory.");
828
829         SysTryReturnResult(NID_GRP, rq_dim.width > 0 && rq_dim.height > 0, E_INVALID_ARG, "Both of width(%d) and height(%d) of a dimension MUST be greater than 0.", rq_dim.width, rq_dim.height);
830
831         SysTryReturnResult(NID_GRP, pixelFormat > BITMAP_PIXEL_FORMAT_MIN && pixelFormat < BITMAP_PIXEL_FORMAT_MAX, E_INVALID_ARG, "BitmapPixelFormat(%d) is the invalid argument.", pixelFormat);
832
833         result r = _CheckBufferSize(buffer, rq_dim, pixelFormat);
834
835         if (r != E_SUCCESS)
836         {
837                 return r;
838         }
839
840         switch (bufferScaling)
841         {
842         case BUFFER_SCALING_AUTO:
843                 return this->Construct(buffer, rq_dim, pixelFormat, true);
844         case BUFFER_SCALING_NONE:
845                 break;
846         default:
847                 SysTryReturnResult(NID_GRP, 0, E_INVALID_ARG, "BufferScaling(%d) is the invalid argument.", pixelFormat);
848                 break;
849         }
850
851         if (_ResUtil::NeedToConvertCoord())
852         {
853                 result r = this->_sharedItem->nativeBitmap->Construct(buffer, rq_dim, pixelFormat);
854
855                 if (!IsFailed(r))
856                 {
857                         Dimension vc_dim = rq_dim;
858                         Dimension pc_dim = _ResUtil::ConvertToPhyCoord(vc_dim);
859
860                         // special case
861                         pc_dim.width = (pc_dim.width > 0) ? pc_dim.width : 1;
862                         pc_dim.height = (pc_dim.height > 0) ? pc_dim.height : 1;
863
864                         this->_sharedItem->lazyScaling = 1;
865
866                         _ResUtil::Rect vc_rect(0, 0, vc_dim.width, vc_dim.height);
867                         _ResUtil::Rect pc_rect(0, 0, pc_dim.width, pc_dim.height);
868
869                         this->_sharedItem->coordHolder->bitmapSize.required = vc_rect;
870                         this->_sharedItem->coordHolder->bitmapSize.phyCoord = pc_rect;
871                         this->_sharedItem->coordHolder->bitmapSize.virCoord = vc_rect;
872
873                         {
874                                 bool isScaledBufferAvailable = false;
875
876                                 Tizen::Base::ByteBuffer scaledBuffer;
877
878                                 {
879                                         int scaledCapacity = _GetBytesPerPixel(pixelFormat) * (pc_dim.width * pc_dim.height);
880                                         SysAssert(scaledCapacity > 0);
881
882                                         // OOM ignored
883                                         isScaledBufferAvailable = (scaledBuffer.Construct(scaledCapacity) == E_SUCCESS);
884                                 }
885
886                                 if (isScaledBufferAvailable)
887                                 {
888                                         _ScaleBuffer(scaledBuffer, pc_dim, buffer, vc_dim, pixelFormat);
889
890                                         this->_sharedItem->scaledNativeBitmap.reset(new (std::nothrow) _Bitmap);
891
892                                         if (this->_sharedItem->scaledNativeBitmap.get())
893                                         {
894                                                 if (this->_sharedItem->scaledNativeBitmap->Construct(scaledBuffer, pc_dim, pixelFormat) == E_SUCCESS)
895                                                 {
896                                                         // Post-processing
897
898                                                         // BufferInfo bufferInfo;
899                                                         // this->_scaledNativeBitmap->Lock(bufferInfo);
900                                                         // this->_scaledNativeBitmap->Unlock();
901                                                         ;
902                                                 }
903                                                 else
904                                                 {
905                                                         this->_sharedItem->scaledNativeBitmap.reset(null);
906                                                 }
907                                         }
908                                 }
909                         }
910                 }
911
912                 return r;
913         }
914         else
915         {
916                 return this->_sharedItem->nativeBitmap->Construct(buffer, rq_dim, pixelFormat);
917         }
918 }
919
920 result
921 _BitmapImpl::Construct(const Tizen::Base::String& fileName, BitmapPixelFormat pixelFormat)
922 {
923         SysTryReturnResult(NID_GRP, this, E_OUT_OF_MEMORY, "This instance is not allocated yet.");
924
925         SysTryReturnResult(NID_GRP, this->_sharedItem.get(), E_OUT_OF_MEMORY, "Fails to allocate memory.");
926
927         switch (pixelFormat)
928         {
929         case BITMAP_PIXEL_FORMAT_RGB565:
930         case BITMAP_PIXEL_FORMAT_ARGB8888:
931         case BITMAP_PIXEL_FORMAT_R8G8B8A8:
932                 break;
933         default:
934                 SysTryReturnResult(NID_GRP, false, E_INVALID_ARG, "BitmapPixelFormat(%d) is invalid argument.", pixelFormat);
935                 break;
936         }
937
938         SysTryReturnResult(NID_GRP, Tizen::Io::File::IsFileExist(fileName), E_INVALID_ARG, "The specified file is not found.");
939
940         // This function doesn't verify the specified image file.
941         this->_sharedItem->associated.fileName = fileName;
942         this->_sharedItem->associated.pixelFormat = pixelFormat;
943
944         return E_SUCCESS;
945 }
946
947 const Tizen::Base::String&
948 _BitmapImpl::GetFileName(void) const
949 {
950         if (this && this->_sharedItem.get())
951         {
952                 return this->_sharedItem->associated.fileName;
953         }
954         else
955         {
956                 static Tizen::Base::String emptyString;
957                 emptyString.Clear();
958
959                 return emptyString;
960         }
961 }
962
963 result
964 _BitmapImpl::Scale(const Dimension& vc_dim)
965 {
966         SysTryReturnResult(NID_GRP, INSTANCE_IS_VALID, E_OPERATION_FAILED, "This instance is not constructed yet.");
967
968         SysTryReturnResult(NID_GRP, vc_dim.width > 0 && vc_dim.height > 0, E_OUT_OF_RANGE, "Both of width(%d) and height(%d) MUST be greater than 0.", vc_dim.width, vc_dim.height);
969
970         if (vc_dim.width == this->GetWidth() && vc_dim.height == this->GetHeight())
971         {
972                 return E_SUCCESS;
973         }
974
975         _UpdateBitmapTimeStamp(*this);
976
977         if (_ResUtil::NeedToConvertCoord())
978         {
979                 if (this->_sharedItem->lazyScaling && this->_sharedItem->scaledNativeBitmap.get())
980                 {
981                         Dimension pc_dim = _ResUtil::ConvertToPhyCoord(vc_dim);
982
983                         // special case
984                         pc_dim.width = (pc_dim.width > 0) ? pc_dim.width : 1;
985                         pc_dim.height = (pc_dim.height > 0) ? pc_dim.height : 1;
986
987                         result r = this->_sharedItem->nativeBitmap->Scale(vc_dim);
988
989                         if (!IsFailed(r))
990                         {
991                                 Rectangle vc_rect(0, 0, vc_dim.width, vc_dim.height);
992
993                                 this->_sharedItem->coordHolder->Init(vc_rect);
994                                 this->_sharedItem->coordHolder->bitmapSize.phyCoord.w = pc_dim.width;
995                                 this->_sharedItem->coordHolder->bitmapSize.phyCoord.h = pc_dim.height;
996
997                                 result r = this->_sharedItem->scaledNativeBitmap->Scale(pc_dim);
998
999                                 if (!IsFailed(r))
1000                                 {
1001                                         _UpdateScaledBitmapEx(this->_sharedItem->nativeBitmap.get(), this->_sharedItem->scaledNativeBitmap.get());
1002                                 }
1003                         }
1004
1005                         return r;
1006                 }
1007                 else
1008                 {
1009                         Dimension pc_dim = _ResUtil::ConvertToPhyCoord(vc_dim);
1010
1011                         // special case
1012                         pc_dim.width = (pc_dim.width > 0) ? pc_dim.width : 1;
1013                         pc_dim.height = (pc_dim.height > 0) ? pc_dim.height : 1;
1014
1015                         result r = this->_sharedItem->nativeBitmap->Scale(pc_dim);
1016
1017                         if (!IsFailed(r))
1018                         {
1019                                 Rectangle vc_rect(0, 0, vc_dim.width, vc_dim.height);
1020
1021                                 this->_sharedItem->coordHolder->Init(vc_rect);
1022                                 this->_sharedItem->coordHolder->bitmapSize.phyCoord.w = pc_dim.width;
1023                                 this->_sharedItem->coordHolder->bitmapSize.phyCoord.h = pc_dim.height;
1024                         }
1025
1026                         return r;
1027                 }
1028         }
1029         else
1030         {
1031                 return this->_sharedItem->nativeBitmap->Scale(vc_dim);
1032         }
1033 }
1034
1035 result
1036 _BitmapImpl::Merge(const Point& vc_dest, const _BitmapImpl& src, const Rectangle& vc_srcRect)
1037 {
1038         SysTryReturnResult(NID_GRP, INSTANCE_IS_VALID, E_OPERATION_FAILED, "This instance is not constructed yet.");
1039
1040         SysTryReturnResult(NID_GRP, &src && src._sharedItem.get(), E_INVALID_ARG, "The source bitmap is invalid.");
1041
1042         SysTryReturnResult(NID_GRP, src._sharedItem->nativeBitmap->IsValid(), E_INVALID_ARG, "The source bitmap is invalid.");
1043
1044         SysTryReturnResult(NID_GRP, &vc_srcRect, E_INVALID_ARG, "The source rectangle is invalid.");
1045         SysTryReturnResult(NID_GRP, &vc_dest, E_INVALID_ARG, "The destination position is invalid.");
1046         SysTryReturnResult(NID_GRP, vc_dest.x >= 0 && vc_dest.y >= 0, E_OUT_OF_RANGE, "The argument is out of range. (dest(x:%d,y:%d)).", vc_dest.x, vc_dest.y);
1047
1048         SysTryReturnResult(NID_GRP, (vc_srcRect.width >= 0) && (vc_srcRect.height >= 0), E_INVALID_ARG, "The given rectangle(width:%d,height:%d) is invalid.", vc_srcRect.width, vc_srcRect.height);
1049
1050         if ((vc_srcRect.width == 0) || (vc_srcRect.height == 0))
1051         {
1052                 return E_SUCCESS;
1053         }
1054
1055         _UpdateBitmapTimeStamp(*this);
1056
1057         Rectangle rtBitmap(0, 0, src.GetWidth(), src.GetHeight());
1058         SysTryReturnResult(NID_GRP, _CheckValidity(vc_srcRect, rtBitmap), E_OUT_OF_RANGE, "The argument is out of range. (srcRect(x:%d,y:%d,w:%d,h:%d)).", vc_srcRect.x, vc_srcRect.y, vc_srcRect.width, vc_srcRect.height);
1059
1060         _Bitmap* pSrcBitmapEx = Tizen::Graphics::GetBitmapEx(src);
1061         _Bitmap* pDstBitmapEx = this->_sharedItem->nativeBitmap.get();
1062
1063         if (_ResUtil::NeedToConvertCoord())
1064         {
1065                 Point pc_dest = _ResUtil::ConvertToPhyCoord(vc_dest);
1066                 Rectangle pc_srcRect = _ResUtil::ConvertToPhyCoord(vc_srcRect);
1067
1068                 /*
1069                     case 0: scaled bitmap -> scaled bitmap
1070                         merge level 0
1071                     case 1: scaled bitmap -> lazy scaled bitmap
1072                         merge level 0 from the scaled source bitmap
1073                         merge level 0(src) and level 1(dst)
1074                     case 2: lazy scaled bitmap -> scaled bitmap
1075                         merge level 1(src) and level 0(dst)
1076                     case 3: lazy scaled bitmap ->  lazy scaled bitmap
1077                         merge level 0 (using virtual coordinate)
1078                         merge level 1 (using physical coordinate)
1079                 */
1080                 int caseNo = (Tizen::Graphics::IsLazyScalingBitmap(src)) ? 2 : 0;
1081                 caseNo += (Tizen::Graphics::IsLazyScalingBitmap(*this)) ? 1 : 0;
1082
1083                 switch (caseNo)
1084                 {
1085                 case 0: // source: pre-scale, destination: pre-scale --> merge by using the physical coordinate
1086                 {
1087                         return pDstBitmapEx->Merge(pc_dest, *pSrcBitmapEx, pc_srcRect);
1088                 }
1089                 case 1: // source: pre-scale --> level0 bitmap: merge after enlarging, level1 bitmap: merge from source directly
1090                 {
1091                         result r = E_SUCCESS;
1092
1093                         // step 1
1094                         {
1095                                 _Bitmap srcResizedBitmap;
1096                                 {
1097                                         Dimension srcVirDim(src._sharedItem->coordHolder->bitmapSize.virCoord.w, src._sharedItem->coordHolder->bitmapSize.virCoord.h);
1098
1099                                         r = srcResizedBitmap.Construct(srcVirDim, pSrcBitmapEx->GetPixelColorFormat());
1100                                         SysTryReturnResult(NID_GRP, !IsFailed(r), E_OUT_OF_MEMORY, "Fails to allocate memory.");
1101                                 }
1102
1103                                 _UpdateScaledBitmapEx(pSrcBitmapEx, &srcResizedBitmap);
1104
1105                                 r = pDstBitmapEx->Merge(vc_dest, srcResizedBitmap, vc_srcRect);
1106                         }
1107
1108                         // step 2
1109                         if (!IsFailed(r) && this->_sharedItem->scaledNativeBitmap.get())
1110                         {
1111                                 return this->_sharedItem->scaledNativeBitmap->Merge(pc_dest, *pSrcBitmapEx, pc_srcRect);
1112                         }
1113
1114                         return r;
1115                 }
1116                 case 2: // destination: pre-scale --> merge from the level1 bitmap of source
1117                 {
1118                         _Bitmap* pSrcScaledBitmapEx = Tizen::Graphics::GetScaledBitmapEx(src);
1119
1120
1121                         if (pSrcScaledBitmapEx)
1122                         {
1123                                 return pDstBitmapEx->Merge(pc_dest, *pSrcScaledBitmapEx, pc_srcRect);
1124                         }
1125                         else
1126                         {
1127                                 SysTryReturnResult(NID_GRP, 0, E_INVALID_ARG, "The source bitmap is invalid.");
1128                         }
1129
1130                         return E_INVALID_ARG;
1131                 }
1132                 case 3: // source: lazy-scale, destination: lazy-scale --> merge between level0, merge between level1
1133                 {
1134                         result r = pDstBitmapEx->Merge(vc_dest, *pSrcBitmapEx, vc_srcRect);
1135
1136                         _Bitmap* pSrcScaledBitmapEx = Tizen::Graphics::GetScaledBitmapEx(src);
1137
1138                         if (this->_sharedItem->scaledNativeBitmap.get() && pSrcScaledBitmapEx)
1139                         {
1140                                 this->_sharedItem->scaledNativeBitmap->Merge(pc_dest, *pSrcScaledBitmapEx, pc_srcRect);
1141                         }
1142
1143                         return r;
1144                 }
1145                 default:
1146                         SysAssert(0);
1147                         return E_INVALID_ARG;
1148                 }
1149         }
1150         else
1151         {
1152                 return pDstBitmapEx->Merge(vc_dest, *pSrcBitmapEx, vc_srcRect);
1153         }
1154
1155         // for removing compiler warnings
1156         return E_OPERATION_FAILED;
1157 }
1158
1159 int
1160 _BitmapImpl::GetHeight() const
1161 {
1162         if (!(INSTANCE_IS_VALID))
1163         {
1164                 SysLog(NID_GRP, "[E_OPERATION_FAILED] This instance is not constructed yet.");
1165                 return -1;
1166         }
1167
1168         if (_ResUtil::NeedToConvertCoord())
1169         {
1170                 return this->_sharedItem->coordHolder->bitmapSize.required.h;
1171         }
1172         else
1173         {
1174                 return this->_sharedItem->nativeBitmap->GetHeight();
1175         }
1176 }
1177
1178 int
1179 _BitmapImpl::GetWidth() const
1180 {
1181         if (!(INSTANCE_IS_VALID))
1182         {
1183                 SysLog(NID_GRP, "[E_OPERATION_FAILED] This instance is not constructed yet.");
1184                 return -1;
1185         }
1186
1187         if (_ResUtil::NeedToConvertCoord())
1188         {
1189                 return this->_sharedItem->coordHolder->bitmapSize.required.w;
1190         }
1191         else
1192         {
1193                 return this->_sharedItem->nativeBitmap->GetWidth();
1194         }
1195 }
1196
1197 int
1198 _BitmapImpl::GetBitsPerPixel() const
1199 {
1200         if (!(INSTANCE_IS_VALID))
1201         {
1202                 SysLog(NID_GRP, "[E_OPERATION_FAILED] This instance is not constructed yet.");
1203                 return -1;
1204         }
1205
1206         return this->_sharedItem->nativeBitmap->GetBitsPerPixel();
1207 }
1208
1209 BitmapPixelFormat
1210 _BitmapImpl::GetPixelColorFormat() const
1211 {
1212         if (!(INSTANCE_IS_VALID))
1213         {
1214                 SysLog(NID_GRP, "[E_OPERATION_FAILED] This instance is not constructed yet.");
1215                 return BITMAP_PIXEL_FORMAT_MAX;
1216         }
1217
1218         return this->_sharedItem->nativeBitmap->GetPixelColorFormat();
1219 }
1220
1221 result
1222 _BitmapImpl::SetMaskingColor(const Color* pColor)
1223 {
1224         SysTryReturnResult(NID_GRP, INSTANCE_IS_VALID, E_OPERATION_FAILED, "This instance is not constructed yet.");
1225
1226         _UpdateBitmapTimeStamp(*this);
1227
1228         return this->_sharedItem->nativeBitmap->SetMaskingColor(pColor);
1229 }
1230
1231 result
1232 _BitmapImpl::GetMaskingColor(Color& color) const
1233 {
1234         SysTryReturnResult(NID_GRP, INSTANCE_IS_VALID, E_OPERATION_FAILED, "This instance is not constructed yet.");
1235
1236         return this->_sharedItem->nativeBitmap->GetMaskingColor(color);
1237 }
1238
1239 void
1240 _BitmapImpl::SetAlphaConstant(int opacity)
1241 {
1242         if (INSTANCE_IS_VALID)
1243         {
1244                 _UpdateBitmapTimeStamp(*this);
1245
1246                 this->_sharedItem->nativeBitmap->SetAlphaConstant(opacity);
1247         }
1248 }
1249
1250 int
1251 _BitmapImpl::GetAlphaConstant(void) const
1252 {
1253         return (INSTANCE_IS_VALID) ? this->_sharedItem->nativeBitmap->GetAlphaConstant() : -1;
1254 }
1255
1256 result
1257 _BitmapImpl::SetScalingQuality(BitmapScalingQuality quality)
1258 {
1259         SysTryReturnResult(NID_GRP, INSTANCE_IS_VALID, E_OPERATION_FAILED, "This instance is not constructed yet.");
1260
1261         switch (quality)
1262         {
1263         case BITMAP_SCALING_QUALITY_LOW:
1264         case BITMAP_SCALING_QUALITY_MID:
1265         case BITMAP_SCALING_QUALITY_HIGH:
1266                 break;
1267         default:
1268                 return E_INVALID_ARG;
1269         }
1270
1271         _UpdateBitmapTimeStamp(*this);
1272
1273         this->_sharedItem->nativeBitmap->SetScalingQuality(quality);
1274
1275         return E_SUCCESS;
1276 }
1277
1278 BitmapScalingQuality
1279 _BitmapImpl::GetScalingQuality(void) const
1280 {
1281         return (INSTANCE_IS_VALID) ? this->_sharedItem->nativeBitmap->GetScalingQuality() : BITMAP_SCALING_QUALITY_LOW;
1282 }
1283
1284 bool
1285 _BitmapImpl::IsNinePatchedBitmap(void) const
1286 {
1287         if (!(INSTANCE_IS_VALID))
1288         {
1289                 SysLog(NID_GRP, "[E_OPERATION_FAILED] This instance is not constructed yet.");
1290                 return false;
1291         }
1292
1293         _Bitmap* pRefBitmap = (this->_sharedItem->lazyScaling && this->_sharedItem->scaledNativeBitmap.get()) ? this->_sharedItem->scaledNativeBitmap.get() : this->_sharedItem->nativeBitmap.get();
1294
1295         return pRefBitmap->IsNinePatchedBitmap();
1296 }
1297
1298 void
1299 _BitmapImpl::SetAsImmutable(void)
1300 {
1301         if (INSTANCE_IS_VALID)
1302         {
1303                 if (this->_sharedItem->isMutable)
1304                 {
1305                         BufferInfo bi;
1306
1307                         if (this->Lock(bi) == E_SUCCESS)
1308                         {
1309                                 _Util::Pixmap dstImage(bi.width, bi.height, bi.bitsPerPixel, (void*)bi.pPixels, bi.pitch);
1310                                 dstImage.ConvertPremultiplied();
1311
1312                                 this->Unlock();
1313                         }
1314
1315                         this->_sharedItem->isMutable = false;
1316                         this->_sharedItem->nativeBitmap->__isPremultiplied = true;
1317
1318                         //?? this->_sharedItem->scaledNativeBitmap
1319                 }
1320         }
1321 }
1322
1323 bool
1324 _BitmapImpl::IsMutable(void)
1325 {
1326         SysTryReturnResult(NID_GRP, INSTANCE_IS_VALID, false, "This instance is not constructed yet.");
1327
1328         return this->_sharedItem->isMutable;
1329 }
1330
1331 result
1332 _BitmapImpl::Lock(BufferInfo& info, long timeout)
1333 {
1334         SysTryReturnResult(NID_GRP, INSTANCE_IS_VALID, E_OPERATION_FAILED, "This instance is not constructed yet.");
1335
1336         _UpdateBitmapTimeStamp(*this);
1337
1338         return this->_sharedItem->nativeBitmap->Lock(info, timeout);
1339 }
1340
1341 result
1342 _BitmapImpl::Unlock()
1343 {
1344         SysTryReturnResult(NID_GRP, INSTANCE_IS_VALID, E_OPERATION_FAILED, "This instance is not constructed yet.");
1345
1346         result r = this->_sharedItem->nativeBitmap->Unlock();
1347
1348         _UpdateBitmapTimeStamp(*this);
1349
1350         if ((r == E_SUCCESS) && (this->_sharedItem->lazyScaling))
1351         {
1352                 if (this->_sharedItem->scaledNativeBitmap.get())
1353                 {
1354                         _UpdateScaledBitmapEx(this->_sharedItem->nativeBitmap.get(), this->_sharedItem->scaledNativeBitmap.get());
1355                         this->_sharedItem->scaledNativeBitmap->UpdateOpaqueInfo();
1356                 }
1357         }
1358
1359         return r;
1360 }
1361
1362 result
1363 _BitmapImpl::LockFast(BufferInfo& info, long timeout)
1364 {
1365         SysTryReturnResult(NID_GRP, INSTANCE_IS_VALID, E_OPERATION_FAILED, "This instance is not constructed yet.");
1366
1367         _UpdateBitmapTimeStamp(*this);
1368
1369         return this->_sharedItem->nativeBitmap->LockFast(info, timeout);
1370 }
1371
1372 result
1373 _BitmapImpl::UnlockFast()
1374 {
1375         SysTryReturnResult(NID_GRP, INSTANCE_IS_VALID, E_OPERATION_FAILED, "This instance is not constructed yet.");
1376
1377         result r = this->_sharedItem->nativeBitmap->UnlockFast();
1378
1379         _UpdateBitmapTimeStamp(*this);
1380
1381         if ((r == E_SUCCESS) && (this->_sharedItem->lazyScaling))
1382         {
1383                 if (this->_sharedItem->scaledNativeBitmap.get())
1384                 {
1385                         _UpdateScaledBitmapEx(this->_sharedItem->nativeBitmap.get(), this->_sharedItem->scaledNativeBitmap.get());
1386                 }
1387         }
1388
1389         return r;
1390 }
1391
1392 bool
1393 _BitmapImpl::_SetCallback(void (* DestroyCallback)(void*), void* pDestroyCallbackParam,
1394                               void (* LockCallback)(void*), void* pLockCallbackParam,
1395                               void (* UnlockCallback)(void*), void* pUnlockCallbackParam)
1396 {
1397         if (!(INSTANCE_IS_VALID))
1398         {
1399                 SysLog(NID_GRP, "[E_OPERATION_FAILED] This instance is not constructed yet.");
1400                 return false;
1401         }
1402
1403         _UpdateBitmapTimeStamp(*this);
1404
1405         this->_sharedItem->pDestroyCallbackFunc = DestroyCallback;
1406         this->_sharedItem->pDestroyCallbackParam = pDestroyCallbackParam;
1407
1408         this->_sharedItem->pLockCallbackFunc = LockCallback;
1409         this->_sharedItem->pLockCallbackParam = pLockCallbackParam;
1410
1411         this->_sharedItem->pUnlockCallbackFunc = UnlockCallback;
1412         this->_sharedItem->pUnlockCallbackParam = pUnlockCallbackParam;
1413
1414         if (this->_sharedItem->nativeBitmap.get())
1415         {
1416                 this->_sharedItem->nativeBitmap->SetCallback(LockCallback, pLockCallbackParam, UnlockCallback, pUnlockCallbackParam);
1417         }
1418
1419         if (this->_sharedItem->scaledNativeBitmap.get())
1420         {
1421                 this->_sharedItem->scaledNativeBitmap->SetCallback(LockCallback, pLockCallbackParam, UnlockCallback, pUnlockCallbackParam);
1422         }
1423
1424         return true;
1425 }
1426
1427 Bitmap*
1428 _BitmapImpl::GetExpandedBitmapN(const Bitmap& ninePatchedBitmap, int width, int height)
1429 {
1430         SysTryReturn(NID_GRP, width > 0 && height > 0, null, E_INVALID_ARG, "[E_INVALID_ARG] The given parameter is invalid (width = %d, height = %d)", width, height);
1431
1432         SysTryReturn(NID_GRP, &ninePatchedBitmap, null, E_INVALID_ARG, "[E_INVALID_ARG] The given bitmap is invalid (null reference passed)");
1433
1434         const _BitmapImpl* pSrcBitmapImpl = _BitmapImpl::GetInstance(ninePatchedBitmap);
1435
1436         SysTryReturn(NID_GRP, BITMAPIMPL_IS_VALID(pSrcBitmapImpl), null, E_INVALID_ARG, "[E_INVALID_ARG] The given bitmap is invalid");
1437
1438         SysTryReturn(NID_GRP, pSrcBitmapImpl->IsNinePatchedBitmap(), null, E_INVALID_ARG, "[E_INVALID_ARG] The given bitmap is not a nine-patched bitmap");
1439
1440         BitmapPixelFormat pixelFormat = pSrcBitmapImpl->GetPixelColorFormat();
1441
1442         switch (pixelFormat)
1443         {
1444         case BITMAP_PIXEL_FORMAT_RGB565:
1445         case BITMAP_PIXEL_FORMAT_ARGB8888:
1446                 break;
1447         default:
1448                 SysTryReturn(NID_GRP, false, null, E_UNSUPPORTED_FORMAT, "[E_UNSUPPORTED_FORMAT] Pixel format of the given bitmap is invalid (%d)", pixelFormat);
1449                 break;
1450         }
1451
1452         std::auto_ptr<Bitmap> expandedBitmap(new (std::nothrow) Bitmap);
1453
1454         SysTryReturn(NID_GRP, expandedBitmap.get(), null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed (new Bitmap)");
1455
1456         result r = expandedBitmap->Construct(Dimension(width, height), pixelFormat);
1457
1458         SysTryReturn(NID_GRP, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
1459
1460         _BitmapImpl* pDstBitmapImpl = _BitmapImpl::GetInstance(*expandedBitmap.get());
1461
1462         SysAssert(pDstBitmapImpl != null);
1463
1464         {
1465                 _Util::LockManager srcBitmap(*pSrcBitmapImpl);
1466                 _Util::LockManager dstBitmap(*pDstBitmapImpl);
1467
1468                 SysTryReturn(NID_GRP, srcBitmap.IsValid(), null, srcBitmap.GetResult(), "[%s] Buffer locking of the source bitmap failed", srcBitmap.GetResult());
1469                 SysTryReturn(NID_GRP, dstBitmap.IsValid(), null, dstBitmap.GetResult(), "[%s] Buffer locking of the target bitmap failed", dstBitmap.GetResult());
1470
1471                 if (dstBitmap.GetBufferInfo().width < srcBitmap.GetBufferInfo().width - 2 ||
1472                         dstBitmap.GetBufferInfo().height < srcBitmap.GetBufferInfo().height - 2)
1473                 {
1474                         // down-scales from the source bitmap only
1475                         const BufferInfo& srcBufferInfo = srcBitmap.GetBufferInfo();
1476                         const BufferInfo& dstBufferInfo = dstBitmap.GetBufferInfo();
1477
1478                         memset(dstBufferInfo.pPixels, 0, dstBufferInfo.pitch * dstBufferInfo.height);
1479
1480                         _Util::Pixmap dstImage(dstBufferInfo.width, dstBufferInfo.height, dstBufferInfo.bitsPerPixel, (void*) dstBufferInfo.pPixels, dstBufferInfo.pitch);
1481
1482                         Rectangle sourRect(1, 1, srcBufferInfo.width - 2, srcBufferInfo.height - 2);
1483                         Rectangle destRect(0, 0, dstBufferInfo.width, dstBufferInfo.height);
1484
1485                         unsigned char* pSrcPixels = (unsigned char*) srcBufferInfo.pPixels + sourRect.y * srcBufferInfo.pitch + sourRect.x * (srcBufferInfo.bitsPerPixel / 8);
1486                         _Util::Pixmap srcImage(sourRect.width, sourRect.height, srcBufferInfo.bitsPerPixel, (void*) pSrcPixels, srcBufferInfo.pitch);
1487
1488                         Tizen::Graphics::_Effect::ScaleImage(dstImage, destRect.x, destRect.y, destRect.width, destRect.height, srcImage, Tizen::Graphics::_Effect::ROP_COPY);
1489                 }
1490                 else
1491                 {
1492                         const BufferInfo& srcBufferInfo = srcBitmap.GetBufferInfo();
1493                         const BufferInfo& dstBufferInfo = dstBitmap.GetBufferInfo();
1494
1495                         memset(dstBufferInfo.pPixels, 0, dstBufferInfo.pitch * dstBufferInfo.height);
1496
1497                         _Util::Pixmap dstImage(dstBufferInfo.width, dstBufferInfo.height, dstBufferInfo.bitsPerPixel, (void*) dstBufferInfo.pPixels, dstBufferInfo.pitch);
1498
1499                         _Util::AccumList<_Util::Pair<_Util::Rectangle<int>, _Util::Rectangle<int> > > boundsList;
1500
1501                         Rectangle destRect(0, 0, dstBufferInfo.width, dstBufferInfo.height);
1502
1503                         // assert(pSrcBitmapImpl->_nativeBitmap);
1504                         r = _Util::GetPatchList(boundsList, destRect, *pSrcBitmapImpl->_sharedItem->nativeBitmap.get());
1505
1506                         SysTryReturn(NID_GRP, r == E_SUCCESS, null, E_SYSTEM, "[E_SYSTEM] _Util::GetPatchList() failed (error = %#x)", r);
1507
1508                         _Util::AccumList<_Util::Pair<_Util::Rectangle<int>, _Util::Rectangle<int> > >::Iterator iter = boundsList.Begin();
1509
1510                         while (iter != boundsList.End())
1511                         {
1512                                 Rectangle destRect(iter->first.x, iter->first.y, iter->first.w, iter->first.h);
1513                                 Rectangle sourRect(iter->second.x, iter->second.y, iter->second.w, iter->second.h);
1514
1515                                 {
1516                                         unsigned char* pSrcPixels = (unsigned char*) srcBufferInfo.pPixels + sourRect.y * srcBufferInfo.pitch + sourRect.x * (srcBufferInfo.bitsPerPixel / 8);
1517                                         _Util::Pixmap srcImage(sourRect.width, sourRect.height, srcBufferInfo.bitsPerPixel, (void*) pSrcPixels, srcBufferInfo.pitch);
1518
1519                                         Tizen::Graphics::_Effect::ScaleImage(dstImage, destRect.x, destRect.y, destRect.width, destRect.height, srcImage, Tizen::Graphics::_Effect::ROP_COPY);
1520                                 }
1521
1522                                 ++iter;
1523                         }
1524                 }
1525         }
1526
1527         return expandedBitmap.release();
1528 }
1529
1530 Bitmap*
1531 _BitmapImpl::GetColorReplacedBitmapN(const Bitmap& bitmap, const Color& replacedColor, const Color& newColor)
1532 {
1533         SysTryReturn(NID_GRP, &bitmap, null, E_INVALID_ARG, "[E_INVALID_ARG] The given bitmap is invalid (null reference passed)");
1534
1535         std::auto_ptr<Bitmap> pRetBitmap;
1536
1537         {
1538                 Bitmap* pSrcBitmap = const_cast<Bitmap*>(&bitmap);
1539
1540                 BufferInfo biSrc;
1541                 pSrcBitmap->Lock(biSrc);
1542                 {
1543                         pRetBitmap.reset(_BitmapUtil::CreateBitmapN(Dimension(biSrc.width, biSrc.height), biSrc.bitsPerPixel));
1544
1545                         if (pRetBitmap.get())
1546                         {
1547                                 BufferInfo biDst;
1548                                 pRetBitmap->Lock(biDst);
1549
1550                                 if ((biSrc.pitch == biDst.pitch) && (biSrc.height == biDst.height))
1551                                 {
1552                                         memcpy(biDst.pPixels, biSrc.pPixels, biDst.pitch * biDst.height);
1553                                 }
1554
1555                                 pRetBitmap->Unlock();
1556                         }
1557                 }
1558                 pSrcBitmap->Unlock();
1559
1560                 SysTryReturn(NID_GRP, pRetBitmap.get(), null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] New bitmap construction failed");
1561         }
1562
1563         BufferInfo bufferInfo;
1564
1565         result r = pRetBitmap->Lock(bufferInfo);
1566
1567         SysTryReturn(NID_GRP, r == E_SUCCESS, null, E_SYSTEM, "[E_SYSTEM] The allocated bitmap cannot retrieve the own buffer address");
1568
1569         if (bufferInfo.bitsPerPixel == 32)
1570         {
1571                 typedef unsigned long Pixel;
1572
1573                 Pixel keyColor = replacedColor.GetRGB32() & 0x00FFFFFF;
1574                 Pixel chgColor = newColor.GetRGB32() & 0x00FFFFFF;
1575                 Pixel* pBuffer = reinterpret_cast<Pixel*>(bufferInfo.pPixels);
1576                 int padding = bufferInfo.pitch * 8 / bufferInfo.bitsPerPixel - bufferInfo.width;
1577
1578                 Pixel keyAlpha = (newColor.GetRGB32() & 0xFF000000) >> 24;
1579                 keyAlpha += (keyAlpha >> 7);
1580
1581                 if (keyAlpha < 256)
1582                 {
1583                         for (int y = 0; y < bufferInfo.height; y++)
1584                         {
1585                                 for (int x = 0; x < bufferInfo.width; x++)
1586                                 {
1587                                         // if buffer.rgb = replacedColor.rgb then begin
1588                                         //    buffer.a <- buffer.a * newColor.a;
1589                                         //    buffer.r <- newColor.r;
1590                                         //    buffer.g <- newColor.g;
1591                                         //    buffer.b <- newColor.b;
1592                                         // end if
1593
1594                                         if ((*pBuffer & 0x00FFFFFF) == keyColor)
1595                                         {
1596                                                 Pixel alpha = (*pBuffer >> 8) & 0x00FF0000;
1597                                                 alpha = (alpha * keyAlpha) & 0xFF000000;
1598
1599                                                 *pBuffer = alpha | chgColor;
1600                                         }
1601
1602                                         ++pBuffer;
1603                                 }
1604
1605                                 pBuffer += padding;
1606                         }
1607                 }
1608                 else
1609                 {
1610                         for (int y = 0; y < bufferInfo.height; y++)
1611                         {
1612                                 for (int x = 0; x < bufferInfo.width; x++)
1613                                 {
1614                                         // if buffer.rgb = replacedColor.rgb then begin
1615                                         //    buffer.a <- buffer.a;
1616                                         //    buffer.r <- newColor.r;
1617                                         //    buffer.g <- newColor.g;
1618                                         //    buffer.b <- newColor.b;
1619                                         // end if
1620
1621                                         if ((*pBuffer & 0x00FFFFFF) == keyColor)
1622                                         {
1623                                                 *pBuffer = (*pBuffer & 0xFF000000) | chgColor;
1624                                         }
1625
1626                                         ++pBuffer;
1627                                 }
1628
1629                                 pBuffer += padding;
1630                         }
1631                 }
1632         }
1633         else if (bufferInfo.bitsPerPixel == 16)
1634         {
1635                 typedef unsigned short Pixel;
1636
1637                 Pixel keyColor = 0;
1638                 Pixel chgColor = 0;
1639                 Pixel* pBuffer = reinterpret_cast<Pixel*>(bufferInfo.pPixels);
1640                 int padding = bufferInfo.pitch * 8 / bufferInfo.bitsPerPixel - bufferInfo.width;
1641
1642                 {
1643                         unsigned long color32 = replacedColor.GetRGB32();
1644                         _Effect::Func::ConvertColorFormatFast(&keyColor, &color32);
1645                 }
1646
1647                 {
1648                         unsigned long color32 = newColor.GetRGB32() & 0x00FFFFFF;
1649                         _Effect::Func::ConvertColorFormatFast(&chgColor, &color32);
1650                 }
1651
1652                 for (int y = 0; y < bufferInfo.height; y++)
1653                 {
1654                         for (int x = 0; x < bufferInfo.width; x++)
1655                         {
1656                                 if (*pBuffer == keyColor)
1657                                 {
1658                                         *pBuffer = chgColor;
1659                                 }
1660
1661                                 ++pBuffer;
1662                         }
1663
1664                         pBuffer += padding;
1665                 }
1666         }
1667         else
1668         {
1669                 return null;
1670         }
1671
1672         pRetBitmap->Unlock();
1673
1674         return pRetBitmap.release();
1675 }
1676
1677 Bitmap*
1678 _BitmapImpl::CloneN(const Bitmap& bitmap)
1679 {
1680         const _BitmapImpl* pSrcBitmapImpl = null;
1681         _BitmapImpl* pDstBitmapImpl = null;
1682
1683         // source bitmap verification
1684         {
1685                 SysTryReturn(NID_GRP, &bitmap, null, E_INVALID_ARG, "[E_INVALID_ARG] The given bitmap is invalid (null reference passed)");
1686
1687                 pSrcBitmapImpl = _BitmapImpl::GetInstance(bitmap);
1688
1689                 SysTryReturn(NID_GRP, IS_BITMAPIMPL_VALID(pSrcBitmapImpl), null, E_INVALID_ARG, "[E_INVALID_ARG] The given bitmap is invalid");
1690         }
1691
1692         // destination bitmap allocation
1693         std::auto_ptr<Bitmap> pRetBitmap(new (std::nothrow) Bitmap);
1694
1695         {
1696                 SysTryReturn(NID_GRP, pRetBitmap.get(), null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed (new Bitmap)");
1697
1698                 pDstBitmapImpl = _BitmapImpl::GetInstance(*pRetBitmap.get());
1699
1700                 SysTryReturn(NID_GRP, pDstBitmapImpl && pDstBitmapImpl->_sharedItem.get() && !pDstBitmapImpl->_sharedItem->nativeBitmap->IsValid(), null, E_SYSTEM, "[E_SYSTEM] The allocated bitmap is invalid");
1701         }
1702
1703         pDstBitmapImpl->_sharedItem = pSrcBitmapImpl->_sharedItem;
1704
1705         return pRetBitmap.release();
1706 }
1707
1708 _BitmapImpl*
1709 _BitmapImpl::GetNonScaledBitmapImplN(const Tizen::Base::ByteBuffer& buffer, const Dimension& dim, BitmapPixelFormat pixelFormat)
1710 {
1711         return _NonScale::CreateBitmapN(buffer, dim, pixelFormat);
1712 }
1713
1714 Bitmap*
1715 _BitmapImpl::GetNonScaledBitmapN(const Tizen::Base::ByteBuffer& buffer, const Dimension& dim, BitmapPixelFormat pixelFormat)
1716 {
1717         _BitmapImpl* pBitmapImpl = _BitmapImpl::GetNonScaledBitmapImplN(buffer, dim, pixelFormat);
1718
1719         if (pBitmapImpl == null)
1720         {
1721                 return null;
1722         }
1723
1724         return Tizen::Graphics::_BitmapUtil::CreateBitmapN(pBitmapImpl);
1725 }
1726
1727 _BitmapImpl*&
1728 _BitmapImpl::_GetBitmapImpl(Bitmap* pBitmap)
1729 {
1730         return pBitmap->__pImpl;
1731 }
1732
1733 _BitmapImpl*
1734 _BitmapImpl::GetInstance(Bitmap& bitmap)
1735 {
1736         return (&bitmap != null) ? bitmap.__pImpl : null;
1737 }
1738
1739 const _BitmapImpl*
1740 _BitmapImpl::GetInstance(const Bitmap& bitmap)
1741 {
1742         return (&bitmap != null) ? bitmap.__pImpl : null;
1743 }
1744
1745 bool
1746 _BitmapImpl::__CheckValidity(bool canBufferExpand)
1747 {
1748         if (this->_sharedItem.get())
1749         {
1750                 if (this->_sharedItem->nativeBitmap->IsValid())
1751                 {
1752                         return true;
1753                 }
1754
1755                 if (!this->_sharedItem->associated.fileName.IsEmpty())
1756                 {
1757                         if (canBufferExpand)
1758                         {
1759                                 if (!__RealizeBuffer())
1760                                 {
1761                                         // linkedFileName does not exist or is not a image file.
1762                                         this->Construct(Dimension(1, 1), BITMAP_PIXEL_FORMAT_ARGB8888);
1763                                 }
1764
1765                                 this->_sharedItem->associated.fileName.Clear();
1766                         }
1767
1768                         return true;
1769                 }
1770         }
1771
1772         return false;
1773 }
1774
1775 bool
1776 _BitmapImpl::__RealizeBuffer(void)
1777 {
1778         int imageWidth = 0;
1779         int imageHeight = 0;
1780
1781         Tizen::Media::MediaPixelFormat format = Tizen::Media::MEDIA_PIXEL_FORMAT_BGRA8888;
1782
1783         // The following does not consider the case of big-endian
1784         switch (this->_sharedItem->associated.pixelFormat)
1785         {
1786         case BITMAP_PIXEL_FORMAT_RGB565:
1787                 format = Tizen::Media::MEDIA_PIXEL_FORMAT_RGB565LE;
1788                 break;
1789         case BITMAP_PIXEL_FORMAT_R8G8B8A8:
1790                 format = Tizen::Media::MEDIA_PIXEL_FORMAT_RGBA8888;
1791                 break;
1792         case BITMAP_PIXEL_FORMAT_ARGB8888:
1793         default:
1794                 format = Tizen::Media::MEDIA_PIXEL_FORMAT_BGRA8888;
1795                 break;
1796         }
1797
1798         std::auto_ptr<ByteBuffer> pImageBuffer(Tizen::Media::_ImageDecoder::DecodeToBufferN(this->_sharedItem->associated.fileName, format, imageWidth, imageHeight));
1799
1800         if (pImageBuffer.get() == null)
1801         {
1802                 return false;
1803         }
1804
1805         std::auto_ptr<_BitmapImpl> pTempBitmapImpl(_BitmapImpl::GetNonScaledBitmapImplN(*pImageBuffer, Dimension(imageWidth, imageHeight), this->_sharedItem->associated.pixelFormat));
1806
1807         if (pTempBitmapImpl.get() == null || pTempBitmapImpl->_sharedItem.get() == null)
1808         {
1809                 return false;
1810         }
1811
1812         pImageBuffer.reset();
1813
1814         this->_sharedItem->Move(*(pTempBitmapImpl->_sharedItem.get()));
1815
1816         return true;
1817 }
1818
1819 void _BitmapImpl::_SharedItem::Move(_BitmapImpl::_SharedItem& source)
1820 {
1821         std::swap(this->nativeBitmap, source.nativeBitmap);
1822         std::swap(this->coordHolder, source.coordHolder);
1823         std::swap(this->lazyScaling, source.lazyScaling);
1824         std::swap(this->scaledNativeBitmap, source.scaledNativeBitmap);
1825         std::swap(this->isMutable, source.isMutable);
1826 }
1827
1828 }} // Tizen::Graphics