2ffe89c4b8a4de6ba558fe1f6f23fe29a0cc12fe
[platform/framework/native/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 Apache License, Version 2.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://www.apache.org/licenses/LICENSE-2.0/
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(true))
49 #define IS_INSTANCE_VALID (this && const_cast<_BitmapImpl*>(this)->__CheckValidity(false))
50
51 #define BITMAPIMPL_IS_VALID(pBitmapImpl) (pBitmapImpl && const_cast<_BitmapImpl*>(pBitmapImpl)->__CheckValidity(true))
52 #define IS_BITMAPIMPL_VALID(pBitmapImpl) (pBitmapImpl && const_cast<_BitmapImpl*>(pBitmapImpl)->__CheckValidity(false))
53
54
55 namespace // unnamed
56 {
57
58 bool
59 _CheckValidityOfRectangle(const Tizen::Graphics::Rectangle& rect)
60 {
61         return ((rect.width > 0) && (rect.height > 0));
62 }
63
64 bool
65 _CheckValidity(const Tizen::Graphics::Rectangle& rtSrc, const Tizen::Graphics::Rectangle& rtDest)
66 {
67         // check 1. is width/height less or equal than 0?
68         if (rtSrc.width <= 0 || rtSrc.height <= 0 || rtDest.width <= 0 || rtDest.height <= 0)
69         {
70                 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);
71         }
72
73         // check 2.     is src exiting outside of dest entirely?
74         if (rtSrc.x > rtDest.x + rtDest.width - 1 || rtSrc.x + rtSrc.width - 1 < rtDest.x)
75         {
76                 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);
77         }
78
79         if (rtSrc.y > rtDest.y + rtDest.height - 1 || rtSrc.y + rtSrc.height - 1 < rtDest.y)
80         {
81                 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);
82         }
83
84         return true;
85 }
86
87 bool
88 _CheckValidity(const Tizen::Graphics::FloatRectangle& rtSrc, const Tizen::Graphics::FloatRectangle& rtDest)
89 {
90         // check 1. is width/height less or equal than 0?
91         if (rtSrc.width <= 0.0f || rtSrc.height <= 0.0f || rtDest.width <= 0.0f || rtDest.height <= 0.0f)
92         {
93                 return false;     // "[E_OUT_OF_RANGE] The argument is out of range. (src(w:%f,h:%f), dst(w:%f,h:%f))", rtSrc.width, rtSrc.height, rtDest.width, rtDest.height);
94         }
95
96         // check 2.     is src exiting outside of dest entirely?
97         if (rtSrc.x > rtDest.x + rtDest.width || rtSrc.x + rtSrc.width < rtDest.x)
98         {
99                 return false;     // "[E_OUT_OF_RANGE] The argument is out of range. (src(x:%f,y:%f,w:%f,h:%f), dst(x:%f,y:%f,w:%f,h:%f))", rtSrc.x, rtSrc.y, rtSrc.width, rtSrc.height, rtDest.x, rtDest.y, rtDest.width, rtDest.height);
100         }
101
102         if (rtSrc.y > rtDest.y + rtDest.height || rtSrc.y + rtSrc.height < rtDest.y)
103         {
104                 return false;     // "[E_OUT_OF_RANGE] The argument is out of range. (src(x:%f,y:%f,w:%f,h:%f), dst(x:%f,y:%f,w:%f,h:%f))", rtSrc.x, rtSrc.y, rtSrc.width, rtSrc.height, rtDest.x, rtDest.y, rtDest.width, rtDest.height);
105         }
106
107         return true;
108 }
109
110
111 int
112 _GetBytesPerPixel(Tizen::Graphics::BitmapPixelFormat pixelFormat)
113 {
114         if (pixelFormat == Tizen::Graphics::BITMAP_PIXEL_FORMAT_RGB565)
115         {
116                 return 2;
117         }
118         else if (pixelFormat == Tizen::Graphics::BITMAP_PIXEL_FORMAT_ARGB8888 || pixelFormat == Tizen::Graphics::BITMAP_PIXEL_FORMAT_R8G8B8A8)
119         {
120                 return 4;
121         }
122         else
123         {
124                 return 0;
125         }
126 }
127
128 void
129 _GetScaleInfo(Tizen::Graphics::BitmapScalingQuality quality, float width, float height, float scaleWidth, float scaleHeight, Tizen::Graphics::_Util::AccumList<Tizen::Graphics::_Util::Pair<float, float> >& scalingValue)
130 {
131         scalingValue.Clear();
132
133         scalingValue.Push(Tizen::Graphics::_Util::MakePair(scaleWidth, scaleHeight));
134
135         if (quality == Tizen::Graphics::BITMAP_SCALING_QUALITY_HIGH)
136         {
137                 int intWidth = int(width);
138                 int intHeight = int(height);
139
140                 int tempWidth = int(scaleWidth);
141                 int tempHeight = int(scaleHeight);
142
143                 while (intWidth > (tempWidth << 1) || intHeight > (tempHeight << 1))
144                 {
145                         if (intWidth > (tempWidth << 1))
146                         {
147                                 tempWidth <<= 1;
148                         }
149
150                         if (intHeight > (tempHeight << 1))
151                         {
152                                 tempHeight <<= 1;
153                         }
154
155                         scalingValue.Push(Tizen::Graphics::_Util::MakePair(float(tempWidth), float(tempHeight)));
156                 }
157         }
158 }
159
160
161 result
162 _CheckBufferSize(const Tizen::Base::ByteBuffer& buffer, const Tizen::Graphics::Dimension& dim, Tizen::Graphics::BitmapPixelFormat pixelFormat)
163 {
164         int bytePerPixel = _GetBytesPerPixel(pixelFormat);
165
166         if (bytePerPixel == 0)
167         {
168                 SysTryReturnResult(NID_GRP, 0, E_INVALID_ARG, "BitmapPixelFormat(%d) is the invalid argument.", pixelFormat);
169         }
170
171         int byteNum = buffer.GetLimit();
172         int expectedBufferSize = dim.width * dim.height * bytePerPixel;
173
174         SysTryReturnResult(NID_GRP, expectedBufferSize <= byteNum, E_INVALID_ARG, "A buffer size is not correct. (expected: %d, actual: %d)", expectedBufferSize, byteNum);
175
176         return E_SUCCESS;
177 }
178
179 bool
180 _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)
181 {
182         switch (pixelFormat)
183         {
184         case Tizen::Graphics::BITMAP_PIXEL_FORMAT_RGB565:
185         {
186                 Tizen::Graphics::_Util::Pixmap dstImage(destSize.width, destSize.height, 16, (void*) destBuffer.GetPointer());
187                 Tizen::Graphics::_Util::Pixmap srcImage(sourSize.width, sourSize.height, 16, (void*) sourBuffer.GetPointer());
188                 return Tizen::Graphics::_Effect::ScaleImage(dstImage, 0, 0, destSize.width, destSize.height, srcImage);
189         }
190         case Tizen::Graphics::BITMAP_PIXEL_FORMAT_ARGB8888:
191         {
192                 Tizen::Graphics::_Util::Pixmap dstImage(destSize.width, destSize.height, 32, (void*) destBuffer.GetPointer());
193                 Tizen::Graphics::_Util::Pixmap srcImage(sourSize.width, sourSize.height, 32, (void*) sourBuffer.GetPointer());
194                 return Tizen::Graphics::_Effect::ScaleImage(dstImage, 0, 0, destSize.width, destSize.height, srcImage);
195         }
196         case Tizen::Graphics::BITMAP_PIXEL_FORMAT_R8G8B8A8:
197                 return false;
198         default:
199                 return false;
200         }
201 }
202
203 bool
204 _UpdateScaledBitmapEx(Tizen::Graphics::_Bitmap* pSrcBitmap, Tizen::Graphics::_Bitmap* pDstBitmap)
205 {
206         if (!(pSrcBitmap && pDstBitmap && pSrcBitmap->GetPixelColorFormat() == pDstBitmap->GetPixelColorFormat()))
207         {
208                 return false;
209         }
210
211         Tizen::Graphics::BufferInfo srcBufferInfo;
212         Tizen::Graphics::BufferInfo dstBufferInfo;
213
214         {
215                 if (pSrcBitmap->Lock(srcBufferInfo) != E_SUCCESS)
216                 {
217                         return false;
218                 }
219
220                 result r = pDstBitmap->Lock(dstBufferInfo);
221                 if (r != E_SUCCESS)
222                 {
223                         pSrcBitmap->Unlock();
224                         return false;
225                 }
226         }
227
228         bool ret = false;
229
230         do
231         {
232                 switch (pSrcBitmap->GetPixelColorFormat())
233                 {
234                 case Tizen::Graphics::BITMAP_PIXEL_FORMAT_RGB565:
235                 {
236                         Tizen::Graphics::_Util::Pixmap dstImage(dstBufferInfo.width, dstBufferInfo.height, 16, (void*) dstBufferInfo.pPixels);
237                         Tizen::Graphics::_Util::Pixmap srcImage(srcBufferInfo.width, srcBufferInfo.height, 16, (void*) srcBufferInfo.pPixels);
238                         ret = Tizen::Graphics::_Effect::ScaleImage(dstImage, 0, 0, dstBufferInfo.width, dstBufferInfo.height, srcImage);
239                 }
240                 break;
241
242                 case Tizen::Graphics::BITMAP_PIXEL_FORMAT_ARGB8888:
243                 {
244                         Tizen::Graphics::_Util::Pixmap dstImage(dstBufferInfo.width, dstBufferInfo.height, 32, (void*) dstBufferInfo.pPixels);
245                         Tizen::Graphics::_Util::Pixmap srcImage(srcBufferInfo.width, srcBufferInfo.height, 32, (void*) srcBufferInfo.pPixels);
246                         ret = Tizen::Graphics::_Effect::ScaleImage(dstImage, 0, 0, dstBufferInfo.width, dstBufferInfo.height, srcImage);
247                 }
248                 break;
249
250                 case Tizen::Graphics::BITMAP_PIXEL_FORMAT_R8G8B8A8:
251                 default:
252                         break;
253                 }
254         }
255         while (0);
256
257         pSrcBitmap->Unlock();
258         pDstBitmap->Unlock();
259
260         return ret;
261 }
262
263 ////////////////////////////////////////////////////////////////////////////////
264
265 unsigned long
266 _UpdateBitmapTimeStampInternal(void)
267 {
268         static unsigned long staticTimeStamp = 0;
269
270         ++staticTimeStamp;
271
272         staticTimeStamp = (staticTimeStamp == 0) ? (staticTimeStamp + 1) : staticTimeStamp;
273
274         return staticTimeStamp;
275 }
276
277 }
278
279 ////////////////////////////////////////////////////////////////////////////////
280
281 namespace Tizen { namespace Graphics
282 {
283
284 unsigned long
285 _GetBitmapTimeStamp(const Tizen::Graphics::_BitmapImpl& bitmap)
286 {
287         Tizen::Graphics::_Bitmap* _nativeBitmap = Tizen::Graphics::_GetBitmapEx(bitmap);
288
289         return (_nativeBitmap) ? _nativeBitmap->GetTimeStamp() : 0;
290 }
291
292 unsigned long
293 _UpdateBitmapTimeStamp(Tizen::Graphics::_BitmapImpl& bitmap)
294 {
295         Tizen::Graphics::_Bitmap* _nativeBitmap = Tizen::Graphics::_GetBitmapEx(bitmap);
296
297         if (_nativeBitmap)
298         {
299                 _nativeBitmap->SetTimeStamp(_UpdateBitmapTimeStampInternal());
300                 return _nativeBitmap->GetTimeStamp();
301         }
302
303         return 0;
304 }
305
306 ////////////////////////////////////////////////////////////////////////////////
307
308 _BitmapImpl::_BitmapImpl(void)
309         : _magicKey(0)
310         , _sharedItem(std::tr1::shared_ptr<_SharedItem>(new (std::nothrow)_SharedItem))
311 {
312         if (this->_sharedItem.get())
313         {
314                 this->_sharedItem->nativeBitmap.reset(new (std::nothrow) _Bitmap);
315                 this->_sharedItem->coordHolder.reset(new (std::nothrow) _BitmapCoordinateHolder);
316                 this->_sharedItem->lazyScaling = 0;
317                 this->_sharedItem->scaledNativeBitmap.reset(null);
318                 this->_sharedItem->pDestroyCallbackFunc = null;
319                 this->_sharedItem->pDestroyCallbackParam = null;
320                 this->_sharedItem->pLockCallbackFunc = null;
321                 this->_sharedItem->pLockCallbackParam = null;
322                 this->_sharedItem->pUnlockCallbackFunc = null;
323                 this->_sharedItem->pUnlockCallbackParam = null;
324                 this->_sharedItem->pPostlockCallbackFunc = null;
325                 this->_sharedItem->pPostlockCallbackParam = null;
326
327                 this->_sharedItem->isMutable = true;
328                 this->_sharedItem->associated.pixelFormat = BITMAP_PIXEL_FORMAT_ARGB8888;
329                 this->_sharedItem->associated.hasBeenDetectedByUsingName = false;
330                 this->_sharedItem->associated.determinedNinePatchedAtFirst = false;
331
332                 if (this->_sharedItem->nativeBitmap.get() == null || this->_sharedItem->coordHolder.get() == null)
333                 {
334                         this->_sharedItem->nativeBitmap.reset();
335                         this->_sharedItem->coordHolder.reset();
336                         this->_sharedItem.reset();
337
338                         return;
339                 }
340         }
341
342         _UpdateBitmapTimeStamp(*this);
343
344         _Util::CarveMagicKey(*this, _magicKey);
345 }
346
347 _BitmapImpl::~_BitmapImpl(void)
348 {
349         if (this->_sharedItem.get())
350         {
351                 if (this->_sharedItem->pDestroyCallbackFunc)
352                 {
353                         if (this->_sharedItem.unique())
354                         {
355                                 this->_sharedItem->pDestroyCallbackFunc(this->_sharedItem->pDestroyCallbackParam);
356                         }
357                 }
358         }
359
360         _Util::EraseMagicKey(*this, _magicKey);
361 }
362
363 bool
364 _BitmapImpl::IsConstructed(void) const
365 {
366         return (this->_sharedItem.get() && (this->_sharedItem->nativeBitmap->IsValid() || !this->_sharedItem->associated.fileName.IsEmpty()));
367 }
368
369 Tizen::Base::String
370 _BitmapImpl::GetFileName(void) const
371 {
372         return (this->_sharedItem.get()) ? this->_sharedItem->associated.fileName : String();
373 }
374
375 result
376 _BitmapImpl::Construct(const Rectangle& vc_rect)
377 {
378         SysTryReturnResult(NID_GRP, this, E_OUT_OF_MEMORY, "This instance is not allocated yet.");
379
380         SysTryReturnResult(NID_GRP, this->_sharedItem.get(), E_OUT_OF_MEMORY, "Memory allocation failed.");
381
382         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);
383
384         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);
385
386         {
387                 _Util::Dimension<int> vcDim = { vc_rect.width, vc_rect.height };
388
389                 this->_sharedItem->coordHolder->ResetFromVc(vcDim);
390
391                 // SysAssert(this->_sharedItem->coordHolder->size.pcInt.w > 0 && this->_sharedItem->coordHolder->size.pcInt.h > 0);
392
393                 Rectangle pcRect = _ResUtil::ConvertToPhyCoord(vc_rect);
394
395                 pcRect.width = this->_sharedItem->coordHolder->size.pcInt.w;
396                 pcRect.height = this->_sharedItem->coordHolder->size.pcInt.h;
397
398                 return this->_sharedItem->nativeBitmap->Construct(pcRect);
399         }
400 }
401
402 result
403 _BitmapImpl::Construct(const Dimension& vc_dim, BitmapPixelFormat pixelFormat)
404 {
405         SysTryReturnResult(NID_GRP, this, E_OUT_OF_MEMORY, "This instance is not allocated yet.");
406
407         SysTryReturnResult(NID_GRP, this->_sharedItem.get(), E_OUT_OF_MEMORY, "Memory allocation failed.");
408
409         // check arg.
410         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);
411
412         switch (pixelFormat)
413         {
414         case BITMAP_PIXEL_FORMAT_RGB565:
415         case BITMAP_PIXEL_FORMAT_ARGB8888:
416         case BITMAP_PIXEL_FORMAT_R8G8B8A8:
417                 break;
418         default:
419                 SysTryReturnResult(NID_GRP, 0, E_INVALID_ARG, "BitmapPixelFormat(%d) is invalid argument.", pixelFormat);
420                 break;
421         }
422
423         {
424                 _Util::Dimension<int> vcDim = { vc_dim.width, vc_dim.height };
425
426                 this->_sharedItem->coordHolder->ResetFromVc(vcDim);
427
428                 // SysAssert(this->_sharedItem->coordHolder->size.pcInt.w > 0 && this->_sharedItem->coordHolder->size.pcInt.h > 0);
429
430                 Dimension pcDim(this->_sharedItem->coordHolder->size.pcInt.w, this->_sharedItem->coordHolder->size.pcInt.h);
431
432                 return this->_sharedItem->nativeBitmap->Construct(pcDim, pixelFormat);
433         }
434 }
435
436 result
437 _BitmapImpl::Construct(const _CanvasImpl& canvas, const Rectangle& vc_rect)
438 {
439         SysTryReturnResult(NID_GRP, this, E_OUT_OF_MEMORY, "This instance is not allocated yet.");
440
441         SysTryReturnResult(NID_GRP, this->_sharedItem.get(), E_OUT_OF_MEMORY, "Memory allocation failed.");
442
443         SysTryReturnResult(NID_GRP, &canvas, E_INVALID_ARG, "A canvas is invalid.");
444         SysTryReturnResult(NID_GRP, canvas._pNativeCanvas && canvas._pNativeCanvas->IsValid(), E_INVALID_ARG, "A canvas is invalid.");
445
446         Rectangle rtCanvas = canvas.GetBounds();
447
448         SysTryReturnResult(NID_GRP, !rtCanvas.IsEmpty(), E_INVALID_ARG, "A canvas is empty.");
449
450         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);
451
452         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);
453
454         Tizen::Graphics::_Canvas* pCanvasEx = canvas._pNativeCanvas;
455
456         {
457                 _Util::Dimension<int> vcDim = { vc_rect.width, vc_rect.height };
458
459                 this->_sharedItem->coordHolder->ResetFromVc(vcDim);
460
461                 // SysAssert(this->_sharedItem->coordHolder->size.pcInt.w > 0 && this->_sharedItem->coordHolder->size.pcInt.h > 0);
462
463                 Rectangle pcRect = _ResUtil::ConvertToPhyCoord(vc_rect);
464
465                 pcRect.width = this->_sharedItem->coordHolder->size.pcInt.w;
466                 pcRect.height = this->_sharedItem->coordHolder->size.pcInt.h;
467
468                 return this->_sharedItem->nativeBitmap->Construct(*pCanvasEx, pcRect);
469         }
470 }
471
472 result
473 _BitmapImpl::Construct(const _BitmapImpl& bitmap, const Rectangle& vc_rect)
474 {
475         SysTryReturnResult(NID_GRP, this, E_OUT_OF_MEMORY, "This instance is not allocated yet.");
476
477         SysTryReturnResult(NID_GRP, this->_sharedItem.get(), E_OUT_OF_MEMORY, "Memory allocation failed.");
478
479         SysTryReturnResult(NID_GRP, BITMAPIMPL_IS_VALID(&bitmap), E_INVALID_ARG, "The source bitmap is invalid.");
480
481         Rectangle rtBitmap(0, 0, bitmap.GetWidth(), bitmap.GetHeight());
482
483         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);
484
485         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);
486
487         _Bitmap* pSrcBitmapEx = Tizen::Graphics::_GetBitmapEx(bitmap);
488
489         {
490                 _Util::Dimension<int> vcDim = { vc_rect.width, vc_rect.height };
491
492                 this->_sharedItem->coordHolder->ResetFromVc(vcDim);
493
494                 // SysAssert(this->_sharedItem->coordHolder->size.pcInt.w > 0 && this->_sharedItem->coordHolder->size.pcInt.h > 0);
495
496                 result r = E_SUCCESS;
497                 Rectangle pcRect = _ResUtil::ConvertToPhyCoord(vc_rect);
498
499                 pcRect.width = this->_sharedItem->coordHolder->size.pcInt.w;
500                 pcRect.height = this->_sharedItem->coordHolder->size.pcInt.h;
501
502                 if (Tizen::Graphics::_IsLazyScalingBitmap(bitmap))
503                 {
504                         _Bitmap* pSrcScaledBitmapEx = Tizen::Graphics::_GetScaledBitmapEx(bitmap);
505
506                         r = this->_sharedItem->nativeBitmap->Construct(*pSrcScaledBitmapEx, pcRect);
507                 }
508                 else
509                 {
510                         r = this->_sharedItem->nativeBitmap->Construct(*pSrcBitmapEx, pcRect);
511                 }
512
513                 return r;
514         }
515 }
516
517 result
518 _BitmapImpl::Construct(const Tizen::Base::ByteBuffer& buffer, const Dimension& rq_dim, BitmapPixelFormat pixelFormat)
519 {
520 #if 1
521         return this->Construct(buffer, rq_dim, pixelFormat, true);
522 #else
523 //      return this->Construct(buffer, rq_dim, pixelFormat, BUFFER_SCALING_AUTO);
524 //      return this->Construct(buffer, rq_dim, pixelFormat, BUFFER_SCALING_NONE);
525
526         SysTryReturnResult(NID_GRP, this, E_OUT_OF_MEMORY, "This instance is not allocated yet.");
527
528         SysTryReturnResult(NID_GRP, __pImpl && this->_nativeBitmap, E_OUT_OF_MEMORY, "Memory allocation failed.");
529
530         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);
531
532         SysTryReturnResult(NID_GRP, BITMAP_PIXEL_FORMAT_MIN < pixelFormat && pixelFormat < BITMAP_PIXEL_FORMAT_MAX, E_INVALID_ARG, "BitmapPixelFormat(%d) is the invalid argument.", pixelFormat);
533
534         {
535                 // buffer size should be verified.
536                 int bytePerPixel = 0;
537                 if (BITMAP_PIXEL_FORMAT_RGB565 == pixelFormat)
538                 {
539                         bytePerPixel = 2;
540                 }
541                 else if (BITMAP_PIXEL_FORMAT_ARGB8888 == pixelFormat || BITMAP_PIXEL_FORMAT_R8G8B8A8 == pixelFormat)
542                 {
543                         bytePerPixel = 4;
544                 }
545                 else
546                 {
547                         SysTryReturnResult(NID_GRP, 0, E_INVALID_ARG, "BitmapPixelFormat(%d) is the invalid argument.", pixelFormat);
548                 }
549
550                 int byteNum = buffer.GetLimit();
551                 int expectedBufferSize = rq_dim.width * rq_dim.height * bytePerPixel;
552
553                 SysTryReturnResult(NID_GRP, expectedBufferSize <= byteNum, E_INVALID_ARG, "A buffer size is not correct.");
554         }
555
556         if (_ResUtil::NeedToConvertCoord())
557         {
558                 Dimension vc_dim;
559                 Dimension pc_dim;
560
561                 vc_dim = rq_dim;
562                 pc_dim = _ResUtil::ConvertToPhyCoord(vc_dim);
563
564                 // special case
565                 pc_dim.width = (pc_dim.width > 0) ? pc_dim.width : 1;
566                 pc_dim.height = (pc_dim.height > 0) ? pc_dim.height : 1;
567
568                 if (pc_dim.width * 2 == rq_dim.width && pc_dim.height * 2 == rq_dim.height)
569                 {
570                         int pitch = rq_dim.width;
571
572                         if (pixelFormat == BITMAP_PIXEL_FORMAT_ARGB8888)
573                         {
574                                 const unsigned long MASK = 0x00FF00FF;
575
576                                 unsigned long* pBuffer = (unsigned long*) buffer.GetPointer();
577                                 for (int y = 0; y < pc_dim.height; y++)
578                                 {
579                                         for (int x = 0; x < pc_dim.width; x++)
580                                         {
581                                                 unsigned long add1 = (pBuffer[0] & MASK) + (pBuffer[1] & MASK) + (pBuffer[pitch] & MASK) + (pBuffer[pitch + 1] & MASK);
582                                                 unsigned long add2 = ((pBuffer[0] >> 8) & MASK) + ((pBuffer[1] >> 8) & MASK) + ((pBuffer[pitch] >> 8) & MASK) + ((pBuffer[pitch + 1] >> 8) & MASK);
583
584                                                 unsigned long pix = ((add1 >> 2) & MASK) | (((add2 >> 2) & MASK) << 8);
585
586                                                 pBuffer[0] = pix;
587                                                 pBuffer[1] = pix;
588                                                 pBuffer[pitch] = pix;
589                                                 pBuffer[pitch + 1] = pix;
590
591                                                 pBuffer += 2;
592                                         }
593                                         pBuffer += pitch;
594                                 }
595                         }
596                         else if (pixelFormat == BITMAP_PIXEL_FORMAT_RGB565)
597                         {
598                                 const unsigned short MASK1 = 0xF81F;
599                                 const unsigned short MASK2 = 0x07E0;
600                                 const unsigned short CHROMAKEY = 0xF81F | 0x0020;
601
602                                 bool hasChromakey;
603                                 {
604                                         unsigned short* pBuffer = (unsigned short*) buffer.GetPointer();
605                                         unsigned short* pBufferEnd = pBuffer + rq_dim.width * rq_dim.height;
606
607                                         while (pBuffer < pBufferEnd)
608                                         {
609                                                 if (*pBuffer == CHROMAKEY)
610                                                 {
611                                                         break;
612                                                 }
613
614                                                 ++pBuffer;
615                                         }
616
617                                         hasChromakey = (pBuffer < pBufferEnd);
618                                 }
619
620                                 if (hasChromakey)
621                                 {
622                                         ; // pass through default scaling algorithm
623                                 }
624                                 else
625                                 {
626                                         unsigned short* pBuffer = (unsigned short*) buffer.GetPointer();
627
628                                         for (int y = 0; y < pc_dim.height; y++)
629                                         {
630                                                 for (int x = 0; x < pc_dim.width; x++)
631                                                 {
632                                                         unsigned long add1 = (unsigned long) (pBuffer[0] & MASK1) + (unsigned long) (pBuffer[1] & MASK1) + (unsigned long) (pBuffer[pitch] & MASK1) + (unsigned long) (pBuffer[pitch + 1] & MASK1);
633                                                         unsigned long add2 = (pBuffer[0] & MASK2) + (pBuffer[1] & MASK2) + (pBuffer[pitch] & MASK2) + (pBuffer[pitch + 1] & MASK2);
634
635                                                         unsigned long pix = ((add1 >> 2) & MASK1) | ((add2 >> 2) & MASK2);
636
637                                                         pBuffer[0] = pix;
638                                                         pBuffer[1] = pix;
639                                                         pBuffer[pitch] = pix;
640                                                         pBuffer[pitch + 1] = pix;
641
642                                                         pBuffer += 2;
643                                                 }
644                                                 pBuffer += pitch;
645                                         }
646                                 }
647                         }
648                 }
649
650                 result r = this->_nativeBitmap->Construct(buffer, rq_dim, pixelFormat);
651
652                 if (!IsFailed(r))
653                 {
654                         this->_nativeBitmap->Scale(pc_dim);
655
656                         Rect vc_rect(0, 0, vc_dim.width, vc_dim.height);
657                         Rect pc_rect(0, 0, pc_dim.width, pc_dim.height);
658
659                         this->_coordHolder->bitmapSize.required = vc_rect;
660                         this->_coordHolder->bitmapSize.phyCoord = pc_rect;
661                         this->_coordHolder->bitmapSize.virCoord = vc_rect;
662                 }
663
664                 return r;
665         }
666         else
667         {
668                 return this->_nativeBitmap->Construct(buffer, rq_dim, pixelFormat);
669         }
670
671 #endif
672 }
673
674 result
675 _BitmapImpl::Construct(const BufferInfo& bufferInfo)
676 {
677         SysTryReturnResult(NID_GRP, this, E_OUT_OF_MEMORY, "This instance is not allocated yet.");
678
679         SysTryReturnResult(NID_GRP, this->_sharedItem.get(), E_OUT_OF_MEMORY, "Memory allocation failed.");
680
681         SysTryReturnResult(NID_GRP, (bufferInfo.width > 0) && (bufferInfo.height > 0) && (bufferInfo.pitch > 0)
682                 , E_INVALID_ARG
683                 , "Invalid argument (BufferInfo::width = %d, BufferInfo::height = %d, BufferInfo::pitch = %d)"
684                 , bufferInfo.width, bufferInfo.height, bufferInfo.pitch);
685
686         SysTryReturnResult(NID_GRP, bufferInfo.bitsPerPixel > 0
687                 , E_INVALID_ARG
688                 , "Invalid argument (BufferInfo::bitsPerPixel = %d)"
689                 , bufferInfo.bitsPerPixel);
690
691         SysTryReturnResult(NID_GRP, (bufferInfo.pixelFormat > PIXEL_FORMAT_MIN) && (bufferInfo.pixelFormat < PIXEL_FORMAT_MAX)
692                 , E_INVALID_ARG
693                 , "Invalid argument (BufferInfo::pixelFormat = %d)"
694                 , bufferInfo.pixelFormat);
695
696         SysTryReturnResult(NID_GRP, bufferInfo.pPixels != null
697                 , E_INVALID_ARG
698                 , "Invalid argument (BufferInfo::pPixels = null)");
699
700         SysTryReturnResult(NID_GRP, bufferInfo.bitsPerPixel == 32 || bufferInfo.bitsPerPixel == 16
701                 , E_UNSUPPORTED_FORMAT
702                 , "Unsupported format (BufferInfo::bitsPerPixel = %d)"
703                 , bufferInfo.bitsPerPixel);
704
705         BitmapPixelFormat bitmapPixelFormat = BITMAP_PIXEL_FORMAT_MIN;
706
707         switch (bufferInfo.pixelFormat)
708         {
709         case PIXEL_FORMAT_RGB565:
710                 bitmapPixelFormat = BITMAP_PIXEL_FORMAT_RGB565;
711                 break;
712         case PIXEL_FORMAT_ARGB8888:
713                 bitmapPixelFormat = BITMAP_PIXEL_FORMAT_ARGB8888;
714                 break;
715         case PIXEL_FORMAT_R8G8B8A8:
716                 bitmapPixelFormat = BITMAP_PIXEL_FORMAT_R8G8B8A8;
717                 break;
718         default:
719                 break;
720         }
721
722         SysTryReturnResult(NID_GRP, bitmapPixelFormat != BITMAP_PIXEL_FORMAT_MIN
723                 , E_UNSUPPORTED_FORMAT
724                 , "Unsupported format (BufferInfo::pixelFormat = %d)"
725                 , bufferInfo.pixelFormat);
726
727         result r = this->Construct(static_cast<const byte*>(bufferInfo.pPixels), bufferInfo.width, bufferInfo.height, bitmapPixelFormat, bufferInfo.pitch);
728
729         SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
730
731         this->_sharedItem->nativeBitmap->_SetOwnership(false);
732
733         return E_SUCCESS;
734 }
735
736 result
737 _BitmapImpl::Construct(const Tizen::Base::ByteBuffer& buffer, const Dimension& rq_dim, BitmapPixelFormat pixelFormat, bool autoScaling)
738 {
739         SysTryReturnResult(NID_GRP, this, E_OUT_OF_MEMORY, "This instance is not allocated yet.");
740
741         SysTryReturnResult(NID_GRP, this->_sharedItem.get(), E_OUT_OF_MEMORY, "Memory allocation failed.");
742
743         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);
744
745         SysTryReturnResult(NID_GRP, BITMAP_PIXEL_FORMAT_MIN < pixelFormat && pixelFormat < BITMAP_PIXEL_FORMAT_MAX, E_INVALID_ARG, "BitmapPixelFormat(%d) is the invalid argument.", pixelFormat);
746
747         result r = _CheckBufferSize(buffer, rq_dim, pixelFormat);
748
749         if (r != E_SUCCESS)
750         {
751                 return r;
752         }
753
754         r = this->_sharedItem->nativeBitmap->Construct(buffer, rq_dim, pixelFormat);
755
756         if (!IsFailed(r))
757         {
758                 if (autoScaling)
759                 {
760                         _Util::Dimension<int> vcDim = { rq_dim.width, rq_dim.height };
761
762                         this->_sharedItem->coordHolder->ResetFromVc(vcDim);
763
764                         // SysAssert(this->_sharedItem->coordHolder->size.pcInt.w > 0 && this->_sharedItem->coordHolder->size.pcInt.h > 0);
765
766                         Dimension pcDim(this->_sharedItem->coordHolder->size.pcInt.w, this->_sharedItem->coordHolder->size.pcInt.h);
767                         const BitmapScalingQuality quality = BITMAP_SCALING_QUALITY_LOW;
768
769                         this->_sharedItem->nativeBitmap->ScaleEx(pcDim, quality);
770                 }
771                 else
772                 {
773                         _Util::Dimension<int> pcDim = { rq_dim.width, rq_dim.height };
774
775                         this->_sharedItem->coordHolder->ResetFromPc(pcDim);
776                 }
777         }
778
779         return r;
780 }
781
782 result
783 _BitmapImpl::Construct(const byte* pBuffer, int bufSize, const Dimension& rq_dim, BitmapPixelFormat pixelFormat, bool autoScaling)
784 {
785         SysTryReturnResult(NID_GRP, this, E_OUT_OF_MEMORY, "This instance is not allocated yet.");
786
787         SysTryReturnResult(NID_GRP, this->_sharedItem.get(), E_OUT_OF_MEMORY, "Memory allocation failed.");
788
789         SysTryReturnResult(NID_GRP, pBuffer, E_INVALID_ARG, "The specified buffer pointer is invalid.");
790
791         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);
792
793         SysTryReturnResult(NID_GRP, pixelFormat > BITMAP_PIXEL_FORMAT_MIN && pixelFormat < BITMAP_PIXEL_FORMAT_MAX, E_INVALID_ARG, "BitmapPixelFormat(%d) is the invalid argument.", pixelFormat);
794
795         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);
796
797         _Util::Dimension<int> vcDim = { rq_dim.width, rq_dim.height };
798
799         this->_sharedItem->coordHolder->ResetFromVc(vcDim);
800
801         // SysAssert(this->_sharedItem->coordHolder->size.pcInt.w > 0 && this->_sharedItem->coordHolder->size.pcInt.h > 0);
802
803         result r = this->_sharedItem->nativeBitmap->Construct(pBuffer, bufSize, rq_dim, pixelFormat);
804
805         if (!IsFailed(r) && _ResUtil::NeedToConvertCoord())
806         {
807                 if (autoScaling)
808                 {
809                         Dimension pcDim(this->_sharedItem->coordHolder->size.pcInt.w, this->_sharedItem->coordHolder->size.pcInt.h);
810                         const BitmapScalingQuality quality = BITMAP_SCALING_QUALITY_LOW;
811
812                         this->_sharedItem->nativeBitmap->ScaleEx(pcDim, quality);
813                 }
814                 else
815                 {
816                         _Util::Dimension<int> pcDim = { rq_dim.width, rq_dim.height };
817
818                         this->_sharedItem->coordHolder->ResetFromPc(pcDim);
819                 }
820         }
821
822         return r;
823 }
824
825 result
826 _BitmapImpl::Construct(const byte* pExtBuffer, int width, int height, BitmapPixelFormat pixelFormat, int pitch)
827 {
828         SysTryReturnResult(NID_GRP, this, E_OUT_OF_MEMORY, "This instance is not allocated yet.");
829
830         SysTryReturnResult(NID_GRP, this->_sharedItem.get(), E_OUT_OF_MEMORY, "Memory allocation failed.");
831
832         SysTryReturnResult(NID_GRP, pExtBuffer, E_INVALID_ARG, "The specified buffer pointer is invalid.", width, height);
833
834         SysTryReturnResult(NID_GRP, width > 0 && height > 0, E_INVALID_ARG, "Both of width(%d) and height(%d) of a dimension MUST be greater than 0.", width, height);
835
836         SysTryReturnResult(NID_GRP, pixelFormat > BITMAP_PIXEL_FORMAT_MIN && pixelFormat < BITMAP_PIXEL_FORMAT_MAX, E_INVALID_ARG, "BitmapPixelFormat(%d) is the invalid argument.", pixelFormat);
837
838         // SysAssert(this->_sharedItem->coordHolder->size.pcInt.w > 0 && this->_sharedItem->coordHolder->size.pcInt.h > 0);
839
840         int bpp = _GetBytesPerPixel(pixelFormat);
841
842         SysTryReturnResult(NID_GRP, bpp > 0, E_INVALID_ARG, "BitmapPixelFormat(%d) is the invalid argument.", pixelFormat);
843
844         result r = this->_sharedItem->nativeBitmap->Construct(pExtBuffer, width, height, bpp * 8, pitch / bpp);
845
846         if (!IsFailed(r))
847         {
848                 _Util::Dimension<int> pcDim = { width, height };
849
850                 this->_sharedItem->coordHolder->ResetFromPc(pcDim);
851         }
852
853         return r;
854 }
855
856 result
857 _BitmapImpl::Construct(const Tizen::Base::ByteBuffer& buffer, const Dimension& rq_dim, BitmapPixelFormat pixelFormat, BufferScaling bufferScaling)
858 {
859         SysTryReturnResult(NID_GRP, this, E_OUT_OF_MEMORY, "This instance is not allocated yet.");
860
861         SysTryReturnResult(NID_GRP, this->_sharedItem.get(), E_OUT_OF_MEMORY, "Memory allocation failed.");
862
863         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);
864
865         SysTryReturnResult(NID_GRP, pixelFormat > BITMAP_PIXEL_FORMAT_MIN && pixelFormat < BITMAP_PIXEL_FORMAT_MAX, E_INVALID_ARG, "BitmapPixelFormat(%d) is the invalid argument.", pixelFormat);
866
867         result r = _CheckBufferSize(buffer, rq_dim, pixelFormat);
868
869         if (r != E_SUCCESS)
870         {
871                 return r;
872         }
873
874         switch (bufferScaling)
875         {
876         case BUFFER_SCALING_AUTO:
877                 return this->Construct(buffer, rq_dim, pixelFormat, true);
878         case BUFFER_SCALING_NONE:
879                 break;
880         default:
881                 SysTryReturnResult(NID_GRP, 0, E_INVALID_ARG, "BufferScaling(%d) is the invalid argument.", pixelFormat);
882                 break;
883         }
884
885         _Util::Dimension<int> vcDim = { rq_dim.width, rq_dim.height };
886
887         this->_sharedItem->coordHolder->ResetFromVc(vcDim);
888
889         // SysAssert(this->_sharedItem->coordHolder->size.pcInt.w > 0 && this->_sharedItem->coordHolder->size.pcInt.h > 0);
890
891         r = this->_sharedItem->nativeBitmap->Construct(buffer, rq_dim, pixelFormat);
892
893         if (!IsFailed(r) && _ResUtil::NeedToConvertCoord())
894         {
895                 this->_sharedItem->lazyScaling = 1;
896
897                 {
898                         Dimension vc_dim = rq_dim;
899                         Dimension pc_dim(this->_sharedItem->coordHolder->size.pcInt.w, this->_sharedItem->coordHolder->size.pcInt.h);
900
901                         bool isScaledBufferAvailable = false;
902                         Tizen::Base::ByteBuffer scaledBuffer;
903
904                         {
905                                 int scaledCapacity = _GetBytesPerPixel(pixelFormat) * (pc_dim.width * pc_dim.height);
906                                 SysAssert(scaledCapacity > 0);
907
908                                 // OOM ignored
909                                 isScaledBufferAvailable = (scaledBuffer.Construct(scaledCapacity) == E_SUCCESS);
910                         }
911
912                         if (isScaledBufferAvailable)
913                         {
914                                 _ScaleBuffer(scaledBuffer, pc_dim, buffer, vc_dim, pixelFormat);
915
916                                 this->_sharedItem->scaledNativeBitmap.reset(new (std::nothrow) _Bitmap);
917
918                                 if (this->_sharedItem->scaledNativeBitmap.get())
919                                 {
920                                         if (this->_sharedItem->scaledNativeBitmap->Construct(scaledBuffer, pc_dim, pixelFormat) == E_SUCCESS)
921                                         {
922                                                 // Post-processing
923
924                                                 // BufferInfo bufferInfo;
925                                                 // this->_scaledNativeBitmap->Lock(bufferInfo);
926                                                 // this->_scaledNativeBitmap->Unlock();
927                                                 ;
928                                         }
929                                         else
930                                         {
931                                                 this->_sharedItem->scaledNativeBitmap.reset(null);
932                                         }
933                                 }
934                         }
935                 }
936         }
937
938         return r;
939 }
940
941 result
942 _BitmapImpl::Construct(const Tizen::Base::String& fileName, BitmapPixelFormat pixelFormat)
943 {
944         SysTryReturnResult(NID_GRP, this, E_OUT_OF_MEMORY, "This instance is not allocated yet.");
945
946         SysTryReturnResult(NID_GRP, this->_sharedItem.get(), E_OUT_OF_MEMORY, "Memory allocation failed.");
947
948         switch (pixelFormat)
949         {
950         case BITMAP_PIXEL_FORMAT_RGB565:
951         case BITMAP_PIXEL_FORMAT_ARGB8888:
952         case BITMAP_PIXEL_FORMAT_R8G8B8A8:
953                 break;
954         default:
955                 SysTryReturnResult(NID_GRP, false, E_INVALID_ARG, "BitmapPixelFormat(%d) is invalid argument.", pixelFormat);
956                 break;
957         }
958
959         SysTryReturnResult(NID_GRP, Tizen::Io::File::IsFileExist(fileName), E_INVALID_ARG, "The specified file is not found.");
960
961         // This function doesn't verify the specified image file.
962         this->_sharedItem->associated.fileName = fileName;
963         this->_sharedItem->associated.pixelFormat = pixelFormat;
964         this->_sharedItem->associated.hasBeenDetectedByUsingName = false;
965         this->_sharedItem->associated.determinedNinePatchedAtFirst = false;
966
967         return E_SUCCESS;
968 }
969
970 result
971 _BitmapImpl::Construct(const FloatRectangle& vcRectF)
972 {
973         SysTryReturnResult(NID_GRP, this, E_OUT_OF_MEMORY, "This instance is not allocated yet.");
974
975         SysTryReturnResult(NID_GRP, this->_sharedItem.get(), E_OUT_OF_MEMORY, "Memory allocation failed.");
976
977         SysTryReturnResult(NID_GRP, vcRectF.width > 0.0f && vcRectF.height > 0.0f, E_INVALID_ARG, "Both of width(%f) and height(%f) of a rectangle MUST be greater than 0.", vcRectF.width, vcRectF.height);
978
979         SysTryReturnResult(NID_GRP, vcRectF.x >= 0.0f && vcRectF.y >= 0.0f, E_OUT_OF_RANGE, "The argument is out of range. (rect(x:%f,y:%f,w:%f,h:%f)).", vcRectF.x, vcRectF.y, vcRectF.width, vcRectF.height);
980
981         {
982                 _Util::Dimension<float> vcDimF = { vcRectF.width, vcRectF.height };
983
984                 this->_sharedItem->coordHolder->ResetFromVc(vcDimF);
985
986                 // SysAssert(this->_sharedItem->coordHolder->size.pcInt.w > 0 && this->_sharedItem->coordHolder->size.pcInt.h > 0);
987
988                 FloatRectangle pcRectF = _ResUtil::ConvertToPhyCoord(vcRectF);
989                 Rectangle pcRect;
990
991                 pcRect.x = _FloatToIntForPos(pcRectF.x);
992                 pcRect.y = _FloatToIntForPos(pcRectF.y);
993                 pcRect.width = this->_sharedItem->coordHolder->size.pcInt.w;
994                 pcRect.height = this->_sharedItem->coordHolder->size.pcInt.h;
995
996                 return this->_sharedItem->nativeBitmap->Construct(pcRect);
997         }
998 }
999
1000 result
1001 _BitmapImpl::Construct(const FloatDimension& vcDimF, BitmapPixelFormat pixelFormat)
1002 {
1003         SysTryReturnResult(NID_GRP, this, E_OUT_OF_MEMORY, "This instance is not allocated yet.");
1004
1005         SysTryReturnResult(NID_GRP, this->_sharedItem.get(), E_OUT_OF_MEMORY, "Memory allocation failed.");
1006
1007         SysTryReturnResult(NID_GRP, vcDimF.width > 0.0f && vcDimF.height > 0.0f, E_INVALID_ARG, "Both of width(%f) and height(%f) of a dimension MUST be greater than 0.", vcDimF.width, vcDimF.height);
1008
1009         switch (pixelFormat)
1010         {
1011         case BITMAP_PIXEL_FORMAT_RGB565:
1012         case BITMAP_PIXEL_FORMAT_ARGB8888:
1013         case BITMAP_PIXEL_FORMAT_R8G8B8A8:
1014                 break;
1015         default:
1016                 SysTryReturnResult(NID_GRP, 0, E_INVALID_ARG, "BitmapPixelFormat(%d) is invalid argument.", pixelFormat);
1017                 break;
1018         }
1019
1020         {
1021                 _Util::Dimension<float> vcUtilDimF = { vcDimF.width, vcDimF.height };
1022
1023                 this->_sharedItem->coordHolder->ResetFromVc(vcUtilDimF);
1024
1025                 Dimension pcDim(this->_sharedItem->coordHolder->size.pcInt.w, this->_sharedItem->coordHolder->size.pcInt.h);
1026
1027                 return this->_sharedItem->nativeBitmap->Construct(pcDim, pixelFormat);
1028         }
1029 }
1030
1031 result
1032 _BitmapImpl::Construct(const _CanvasImpl& canvas, const FloatRectangle& vcRectF)
1033 {
1034         SysTryReturnResult(NID_GRP, this, E_OUT_OF_MEMORY, "This instance is not allocated yet.");
1035
1036         SysTryReturnResult(NID_GRP, this->_sharedItem.get(), E_OUT_OF_MEMORY, "Memory allocation failed.");
1037
1038         SysTryReturnResult(NID_GRP, &canvas, E_INVALID_ARG, "A canvas is invalid.");
1039         SysTryReturnResult(NID_GRP, canvas._pNativeCanvas && canvas._pNativeCanvas->IsValid(), E_INVALID_ARG, "A canvas is invalid.");
1040
1041         FloatRectangle rtCanvasF = canvas.GetBoundsF();
1042
1043         SysTryReturnResult(NID_GRP, !rtCanvasF.IsEmpty(), E_INVALID_ARG, "A canvas is empty.");
1044
1045         SysTryReturnResult(NID_GRP, vcRectF.width > 0.0f && vcRectF.height > 0.0f, E_INVALID_ARG, "Both of width(%f) and height(%f) of a rectangle MUST be greater than 0.", vcRectF.width, vcRectF.height);
1046
1047         SysTryReturnResult(NID_GRP, _CheckValidity(vcRectF, rtCanvasF), E_OUT_OF_RANGE, "The argument is out of range. (rect(x:%f,y:%f,w:%f,h:%f)).", vcRectF.x, vcRectF.y, vcRectF.width, vcRectF.height);
1048
1049         Tizen::Graphics::_Canvas* pCanvasEx = canvas._pNativeCanvas;
1050
1051         {
1052                 _Util::Dimension<float> vcDimF = { vcRectF.width, vcRectF.height };
1053
1054                 this->_sharedItem->coordHolder->ResetFromVc(vcDimF);
1055
1056                 FloatRectangle pcRectF = _ResUtil::ConvertToPhyCoord(vcRectF);
1057                 Rectangle pcRect;
1058
1059                 pcRect.x = _FloatToIntForPos(pcRectF.x);
1060                 pcRect.y = _FloatToIntForPos(pcRectF.y);
1061                 pcRect.width = this->_sharedItem->coordHolder->size.pcInt.w;
1062                 pcRect.height = this->_sharedItem->coordHolder->size.pcInt.h;
1063
1064                 return this->_sharedItem->nativeBitmap->Construct(*pCanvasEx, pcRect);
1065         }
1066 }
1067
1068 result
1069 _BitmapImpl::Construct(const _BitmapImpl& bitmap, const FloatRectangle& vcRectF)
1070 {
1071         SysTryReturnResult(NID_GRP, this, E_OUT_OF_MEMORY, "This instance is not allocated yet.");
1072
1073         SysTryReturnResult(NID_GRP, this->_sharedItem.get(), E_OUT_OF_MEMORY, "Memory allocation failed.");
1074
1075         SysTryReturnResult(NID_GRP, BITMAPIMPL_IS_VALID(&bitmap), E_INVALID_ARG, "The source bitmap is invalid.");
1076
1077         SysTryReturnResult(NID_GRP, vcRectF.width > 0.0f && vcRectF.height > 0.0f, E_INVALID_ARG, "Both of width(%f) and height(%f) of a rectangle MUST be greater than 0.", vcRectF.width, vcRectF.height);
1078
1079         FloatRectangle rtBitmapF(0, 0, bitmap.GetWidthF(), bitmap.GetHeightF());
1080
1081         SysTryReturnResult(NID_GRP, _CheckValidity(vcRectF, rtBitmapF), E_OUT_OF_RANGE, "The argument is out of range. (rect(x:%f,y:%f,w:%f,h:%f)).", vcRectF.x, vcRectF.y, vcRectF.width, vcRectF.height);
1082
1083         _Bitmap* pSrcBitmapEx = Tizen::Graphics::_GetBitmapEx(bitmap);
1084
1085         {
1086                 _Util::Dimension<float> vcDimF = { vcRectF.width, vcRectF.height };
1087
1088                 this->_sharedItem->coordHolder->ResetFromVc(vcDimF);
1089
1090                 FloatRectangle pcRectF = _ResUtil::ConvertToPhyCoord(vcRectF);
1091                 Rectangle pcRect;
1092
1093                 pcRect.x = _FloatToIntForPos(pcRectF.x);
1094                 pcRect.y = _FloatToIntForPos(pcRectF.y);
1095                 pcRect.width = this->_sharedItem->coordHolder->size.pcInt.w;
1096                 pcRect.height = this->_sharedItem->coordHolder->size.pcInt.h;
1097
1098                 result r = E_SUCCESS;
1099
1100                 if (Tizen::Graphics::_IsLazyScalingBitmap(bitmap))
1101                 {
1102                         _Bitmap* pSrcScaledBitmapEx = Tizen::Graphics::_GetScaledBitmapEx(bitmap);
1103
1104                         r = this->_sharedItem->nativeBitmap->Construct(*pSrcScaledBitmapEx, pcRect);
1105                 }
1106                 else
1107                 {
1108                         r = this->_sharedItem->nativeBitmap->Construct(*pSrcBitmapEx, pcRect);
1109                 }
1110
1111                 return r;
1112         }
1113 }
1114
1115 result
1116 _BitmapImpl::Scale(const Dimension& vc_dim)
1117 {
1118         SysTryReturnResult(NID_GRP, INSTANCE_IS_VALID, E_OPERATION_FAILED, "This instance is not constructed yet.");
1119
1120         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);
1121
1122         if (vc_dim.width == this->GetWidth() && vc_dim.height == this->GetHeight())
1123         {
1124                 return E_SUCCESS;
1125         }
1126         else
1127         {
1128                 return this->Scale(FloatDimension(float(vc_dim.width), float(vc_dim.height)));
1129         }
1130 }
1131
1132 result
1133 _BitmapImpl::Scale(const FloatDimension& vcDimF)
1134 {
1135         SysTryReturnResult(NID_GRP, INSTANCE_IS_VALID, E_OPERATION_FAILED, "This instance is not constructed yet.");
1136
1137         SysTryReturnResult(NID_GRP, vcDimF.width > 0.0f && vcDimF.height > 0.0f, E_OUT_OF_RANGE, "Both of width(%f) and height(%f) MUST be greater than 0.", vcDimF.width, vcDimF.height);
1138
1139         if (vcDimF.width == this->GetWidthF() && vcDimF.height == this->GetHeightF())
1140         {
1141                 return E_SUCCESS;
1142         }
1143
1144         _UpdateBitmapTimeStamp(*this);
1145
1146         result r = E_SUCCESS;
1147
1148         _Util::AccumList<_Util::Pair<float, float> > scalingValue;
1149
1150         _GetScaleInfo(this->GetScalingQuality(), this->GetWidthF(), this->GetHeightF(), vcDimF.width, vcDimF.height, scalingValue);
1151
1152         for (_Util::AccumList<_Util::Pair<float, float> >::Iterator iter = scalingValue.End(); iter != scalingValue.Begin(); --iter)
1153         {
1154                 this->__Scale((iter-1)->first, (iter-1)->second);
1155         }
1156
1157         return r;
1158 }
1159
1160 result
1161 _BitmapImpl::Merge(const Point& vcDest, const _BitmapImpl& src, const Rectangle& vcSrcRect)
1162 {
1163         SysTryReturnResult(NID_GRP, INSTANCE_IS_VALID, E_OPERATION_FAILED, "This instance is not constructed yet.");
1164
1165         SysTryReturnResult(NID_GRP, &src && src._sharedItem.get(), E_INVALID_ARG, "The source bitmap is invalid.");
1166
1167         SysTryReturnResult(NID_GRP, src._sharedItem->nativeBitmap->IsValid(), E_INVALID_ARG, "The source bitmap is invalid.");
1168
1169         SysTryReturnResult(NID_GRP, &vcSrcRect, E_INVALID_ARG, "The source rectangle is invalid.");
1170         SysTryReturnResult(NID_GRP, &vcDest, E_INVALID_ARG, "The destination position is invalid.");
1171         SysTryReturnResult(NID_GRP, vcDest.x >= 0 && vcDest.y >= 0, E_OUT_OF_RANGE, "The argument is out of range. (dest(x:%d,y:%d)).", vcDest.x, vcDest.y);
1172         SysTryReturnResult(NID_GRP, vcSrcRect.x >= 0 && vcSrcRect.y >= 0, E_OUT_OF_RANGE, "The argument is out of range. (source(x:%d,y:%d)).", vcSrcRect.x, vcSrcRect.y);
1173
1174         SysTryReturnResult(NID_GRP, (vcSrcRect.width >= 0) && (vcSrcRect.height >= 0), E_INVALID_ARG, "The given rectangle(width:%d,height:%d) is invalid.", vcSrcRect.width, vcSrcRect.height);
1175
1176         if ((vcSrcRect.width == 0) || (vcSrcRect.height == 0))
1177         {
1178                 return E_SUCCESS;
1179         }
1180         else
1181         {
1182                 Rectangle rtBitmap(0, 0, src.GetWidth(), src.GetHeight());
1183                 SysTryReturnResult(NID_GRP, _CheckValidity(vcSrcRect, rtBitmap), E_OUT_OF_RANGE, "The argument is out of range. (srcRect(x:%d,y:%d,w:%d,h:%d)).", vcSrcRect.x, vcSrcRect.y, vcSrcRect.width, vcSrcRect.height);
1184
1185                 return this->Merge(FloatPoint(float(vcDest.x), float(vcDest.y)), src, FloatRectangle(float(vcSrcRect.x), float(vcSrcRect.y), float(vcSrcRect.width), float(vcSrcRect.height)));
1186         }
1187 }
1188
1189 result
1190 _BitmapImpl::Merge(const FloatPoint& destVcPosF, const _BitmapImpl& srcBitmap, const FloatRectangle& srcVcRectF)
1191 {
1192         SysTryReturnResult(NID_GRP, INSTANCE_IS_VALID, E_OPERATION_FAILED, "This instance is not constructed yet.");
1193
1194         SysTryReturnResult(NID_GRP, &srcBitmap && srcBitmap._sharedItem.get(), E_INVALID_ARG, "The source bitmap is invalid.");
1195
1196         SysTryReturnResult(NID_GRP, srcBitmap._sharedItem->nativeBitmap->IsValid(), E_INVALID_ARG, "The source bitmap is invalid.");
1197
1198         SysTryReturnResult(NID_GRP, &srcVcRectF, E_INVALID_ARG, "The source rectangle is invalid.");
1199         SysTryReturnResult(NID_GRP, &destVcPosF, E_INVALID_ARG, "The destination position is invalid.");
1200         SysTryReturnResult(NID_GRP, destVcPosF.x >= 0.0f && destVcPosF.y >= 0.0f, E_OUT_OF_RANGE, "The argument is out of range. (destPoint(x:%f,y:%f)).", destVcPosF.x, destVcPosF.y);
1201         SysTryReturnResult(NID_GRP, srcVcRectF.x >= 0.0f && srcVcRectF.y >= 0.0f, E_OUT_OF_RANGE, "The argument is out of range. (source(x:%f,y:%f)).", srcVcRectF.x, srcVcRectF.y);
1202
1203         SysTryReturnResult(NID_GRP, srcVcRectF.width >= 0.0f && srcVcRectF.height >= 0.0f, E_INVALID_ARG, "The given rectangle(width:%f,height:%f) is invalid.", srcVcRectF.width, srcVcRectF.height);
1204
1205         if ((srcVcRectF.width == 0.0f) || (srcVcRectF.height == 0.0f))
1206         {
1207                 return E_SUCCESS;
1208         }
1209
1210         FloatRectangle rtBitmapF(0, 0, srcBitmap.GetWidthF(), srcBitmap.GetHeightF());
1211         SysTryReturnResult(NID_GRP, _CheckValidity(srcVcRectF, rtBitmapF), E_OUT_OF_RANGE, "The argument is out of range. (srcRect(x:%f,y:%f,w:%f,h:%f)).", srcVcRectF.x, srcVcRectF.y, srcVcRectF.width, srcVcRectF.height);
1212
1213         _UpdateBitmapTimeStamp(*this);
1214
1215         _Bitmap* pSrcBitmapEx = Tizen::Graphics::_GetBitmapEx(srcBitmap);
1216         _Bitmap* pDstBitmapEx = this->_sharedItem->nativeBitmap.get();
1217
1218         Point destVcPos(_FloatToIntForPos(destVcPosF.x), _FloatToIntForPos(destVcPosF.y));
1219         Rectangle srcVcRect;
1220
1221         srcVcRect.x = _FloatToIntForPos(srcVcRectF.x);
1222         srcVcRect.y = _FloatToIntForPos(srcVcRectF.y);
1223         srcVcRect.width = _FloatToIntForPos(srcVcRectF.GetBottomRight().x - srcVcRectF.GetTopLeft().x);
1224         srcVcRect.height= _FloatToIntForPos(srcVcRectF.GetBottomRight().y - srcVcRectF.GetTopLeft().y);
1225
1226         if (_ResUtil::NeedToConvertCoord())
1227         {
1228                 FloatPoint destPcPosF = _ResUtil::ConvertToPhyCoord(destVcPosF);
1229                 FloatRectangle srcPcRectF = _ResUtil::ConvertToPhyCoord(srcVcRectF);
1230
1231                 Point destPcPos(_FloatToIntForPos(destPcPosF.x), _FloatToIntForPos(destPcPosF.y));
1232                 Rectangle srcPcRect;
1233
1234                 srcPcRect.x = _FloatToIntForPos(srcPcRectF.x);
1235                 srcPcRect.y = _FloatToIntForPos(srcPcRectF.y);
1236                 srcPcRect.width = _FloatToIntForPos(srcPcRectF.GetBottomRight().x - srcPcRectF.GetTopLeft().x);
1237                 srcPcRect.height= _FloatToIntForPos(srcPcRectF.GetBottomRight().y - srcPcRectF.GetTopLeft().y);
1238
1239                 /*
1240                     case 0: scaled bitmap -> scaled bitmap
1241                         merge level 0
1242                     case 1: scaled bitmap -> lazy scaled bitmap
1243                         merge level 0 from the scaled source bitmap
1244                         merge level 0(src) and level 1(dst)
1245                     case 2: lazy scaled bitmap -> scaled bitmap
1246                         merge level 1(src) and level 0(dst)
1247                     case 3: lazy scaled bitmap ->  lazy scaled bitmap
1248                         merge level 0 (using virtual coordinate)
1249                         merge level 1 (using physical coordinate)
1250                 */
1251                 int caseNo = (Tizen::Graphics::_IsLazyScalingBitmap(srcBitmap)) ? 2 : 0;
1252                 caseNo += (Tizen::Graphics::_IsLazyScalingBitmap(*this)) ? 1 : 0;
1253
1254                 switch (caseNo)
1255                 {
1256                 case 0: // source: pre-scale, destination: pre-scale --> merge by using the physical coordinate
1257                 {
1258                         return pDstBitmapEx->Merge(destPcPos, *pSrcBitmapEx, srcPcRect);
1259                 }
1260                 case 1: // source: pre-scale --> level0 bitmap: merge after enlarging, level1 bitmap: merge from source directly
1261                 {
1262                         result r = E_SUCCESS;
1263
1264                         // step 1
1265                         {
1266                                 _Bitmap srcResizedBitmap;
1267                                 {
1268                                         Dimension srcVcDim;
1269
1270                                         srcVcDim.width = static_cast<int>(srcBitmap._sharedItem->coordHolder->size.vcFloatActual.w);
1271                                         srcVcDim.height = static_cast<int>(srcBitmap._sharedItem->coordHolder->size.vcFloatActual.h);
1272
1273                                         r = srcResizedBitmap.Construct(srcVcDim, pSrcBitmapEx->GetPixelColorFormat());
1274
1275                                         SysTryReturnResult(NID_GRP, !IsFailed(r), E_OUT_OF_MEMORY, "Memory allocation failed.");
1276                                 }
1277
1278                                 _UpdateScaledBitmapEx(pSrcBitmapEx, &srcResizedBitmap);
1279
1280                                 r = pDstBitmapEx->Merge(destVcPos, srcResizedBitmap, srcVcRect);
1281                         }
1282
1283                         // step 2
1284                         if (!IsFailed(r) && this->_sharedItem->scaledNativeBitmap.get())
1285                         {
1286                                 return this->_sharedItem->scaledNativeBitmap->Merge(destPcPos, *pSrcBitmapEx, srcPcRect);
1287                         }
1288
1289                         return r;
1290                 }
1291                 case 2: // destination: pre-scale --> merge from the level1 bitmap of source
1292                 {
1293                         _Bitmap* pSrcScaledBitmapEx = Tizen::Graphics::_GetScaledBitmapEx(srcBitmap);
1294
1295                         SysTryReturnResult(NID_GRP, pSrcScaledBitmapEx != null, E_INVALID_ARG, "The source bitmap is invalid.");
1296
1297                         return pDstBitmapEx->Merge(destPcPos, *pSrcScaledBitmapEx, srcPcRect);
1298                 }
1299                 case 3: // source: lazy-scale, destination: lazy-scale --> merge between level0, merge between level1
1300                 {
1301                         result r = pDstBitmapEx->Merge(destVcPos, *pSrcBitmapEx, srcVcRect);
1302
1303                         _Bitmap* pSrcScaledBitmapEx = Tizen::Graphics::_GetScaledBitmapEx(srcBitmap);
1304
1305                         if (this->_sharedItem->scaledNativeBitmap.get() && pSrcScaledBitmapEx)
1306                         {
1307                                 this->_sharedItem->scaledNativeBitmap->Merge(destPcPos, *pSrcScaledBitmapEx, srcPcRect);
1308                         }
1309
1310                         return r;
1311                 }
1312                 default:
1313                         SysAssert(0);
1314                         return E_INVALID_ARG;
1315                 }
1316         }
1317         else
1318         {
1319                 return pDstBitmapEx->Merge(destVcPos, *pSrcBitmapEx, srcVcRect);
1320         }
1321
1322         // for removing compiler warnings
1323         return E_OPERATION_FAILED;
1324 }
1325
1326 int
1327 _BitmapImpl::GetHeight() const
1328 {
1329         if (!(INSTANCE_IS_VALID))
1330         {
1331                 SysLog(NID_GRP, "[E_OPERATION_FAILED] This instance is not constructed yet.");
1332                 return -1;
1333         }
1334
1335         return this->_sharedItem->coordHolder->size.vcInt.h;
1336 }
1337
1338 float
1339 _BitmapImpl::GetHeightF(void) const
1340 {
1341         if (!(INSTANCE_IS_VALID))
1342         {
1343                 SysLog(NID_GRP, "[E_OPERATION_FAILED] This instance is not constructed yet.");
1344                 return -1.0f;
1345         }
1346
1347         return this->_sharedItem->coordHolder->size.vcFloat.h;
1348 }
1349
1350 float
1351 _BitmapImpl::GetActualHeight(void) const
1352 {
1353         if (!(INSTANCE_IS_VALID))
1354         {
1355                 SysLog(NID_GRP, "[E_OPERATION_FAILED] This instance is not constructed yet.");
1356                 return -1.0f;
1357         }
1358
1359         return this->_sharedItem->coordHolder->size.vcFloatActual.h;
1360 }
1361
1362 int
1363 _BitmapImpl::GetWidth() const
1364 {
1365         if (!(INSTANCE_IS_VALID))
1366         {
1367                 SysLog(NID_GRP, "[E_OPERATION_FAILED] This instance is not constructed yet.");
1368                 return -1;
1369         }
1370
1371         return this->_sharedItem->coordHolder->size.vcInt.w;
1372 }
1373
1374 float
1375 _BitmapImpl::GetWidthF(void) const
1376 {
1377         if (!(INSTANCE_IS_VALID))
1378         {
1379                 SysLog(NID_GRP, "[E_OPERATION_FAILED] This instance is not constructed yet.");
1380                 return -1.0f;
1381         }
1382
1383         return this->_sharedItem->coordHolder->size.vcFloat.w;
1384 }
1385
1386 float
1387 _BitmapImpl::GetActualWidth(void) const
1388 {
1389         if (!(INSTANCE_IS_VALID))
1390         {
1391                 SysLog(NID_GRP, "[E_OPERATION_FAILED] This instance is not constructed yet.");
1392                 return -1.0f;
1393         }
1394
1395         return this->_sharedItem->coordHolder->size.vcFloatActual.w;
1396 }
1397
1398 int
1399 _BitmapImpl::GetBitsPerPixel() const
1400 {
1401         if (!(INSTANCE_IS_VALID))
1402         {
1403                 SysLog(NID_GRP, "[E_OPERATION_FAILED] This instance is not constructed yet.");
1404                 return -1;
1405         }
1406
1407         return this->_sharedItem->nativeBitmap->GetBitsPerPixel();
1408 }
1409
1410 BitmapPixelFormat
1411 _BitmapImpl::GetPixelColorFormat() const
1412 {
1413         if (!(INSTANCE_IS_VALID))
1414         {
1415                 SysLog(NID_GRP, "[E_OPERATION_FAILED] This instance is not constructed yet.");
1416                 return BITMAP_PIXEL_FORMAT_MAX;
1417         }
1418
1419         return this->_sharedItem->nativeBitmap->GetPixelColorFormat();
1420 }
1421
1422 result
1423 _BitmapImpl::SetMaskingColor(const Color* pColor)
1424 {
1425         SysTryReturnResult(NID_GRP, INSTANCE_IS_VALID, E_OPERATION_FAILED, "This instance is not constructed yet.");
1426
1427         _UpdateBitmapTimeStamp(*this);
1428
1429         return this->_sharedItem->nativeBitmap->SetMaskingColor(pColor);
1430 }
1431
1432 result
1433 _BitmapImpl::GetMaskingColor(Color& color) const
1434 {
1435         SysTryReturnResult(NID_GRP, INSTANCE_IS_VALID, E_OPERATION_FAILED, "This instance is not constructed yet.");
1436
1437         return this->_sharedItem->nativeBitmap->GetMaskingColor(color);
1438 }
1439
1440 void
1441 _BitmapImpl::SetAlphaConstant(int opacity)
1442 {
1443         if (INSTANCE_IS_VALID)
1444         {
1445                 _UpdateBitmapTimeStamp(*this);
1446
1447                 this->_sharedItem->nativeBitmap->SetAlphaConstant(opacity);
1448         }
1449 }
1450
1451 int
1452 _BitmapImpl::GetAlphaConstant(void) const
1453 {
1454         return (INSTANCE_IS_VALID) ? this->_sharedItem->nativeBitmap->GetAlphaConstant() : -1;
1455 }
1456
1457 result
1458 _BitmapImpl::SetScalingQuality(BitmapScalingQuality quality)
1459 {
1460         SysTryReturnResult(NID_GRP, INSTANCE_IS_VALID, E_OPERATION_FAILED, "This instance is not constructed yet.");
1461
1462         switch (quality)
1463         {
1464         case BITMAP_SCALING_QUALITY_LOW:
1465         case BITMAP_SCALING_QUALITY_MID:
1466         case BITMAP_SCALING_QUALITY_HIGH:
1467                 break;
1468         default:
1469                 return E_INVALID_ARG;
1470         }
1471
1472         _UpdateBitmapTimeStamp(*this);
1473
1474         this->_sharedItem->nativeBitmap->SetScalingQuality(quality);
1475
1476         return E_SUCCESS;
1477 }
1478
1479 BitmapScalingQuality
1480 _BitmapImpl::GetScalingQuality(void) const
1481 {
1482         return (INSTANCE_IS_VALID) ? this->_sharedItem->nativeBitmap->GetScalingQuality() : BITMAP_SCALING_QUALITY_LOW;
1483 }
1484
1485 bool
1486 _BitmapImpl::IsNinePatchedBitmap(void) const
1487 {
1488 #if 1
1489         if (!(INSTANCE_IS_VALID))
1490         {
1491                 SysLog(NID_GRP, "[E_OPERATION_FAILED] This instance is not constructed yet.");
1492                 return false;
1493         }
1494
1495         _Bitmap* pRefBitmap = (this->_sharedItem->lazyScaling && this->_sharedItem->scaledNativeBitmap.get()) ? this->_sharedItem->scaledNativeBitmap.get() : this->_sharedItem->nativeBitmap.get();
1496
1497         return pRefBitmap->IsNinePatchedBitmap();
1498 #else
1499         if (!(IS_INSTANCE_VALID))
1500         {
1501                 SysLog(NID_GRP, "[E_OPERATION_FAILED] This instance is not constructed yet.");
1502                 return false;
1503         }
1504
1505         const Tizen::Base::String& associatedFileName = this->_sharedItem->associated.fileName;
1506
1507         if (associatedFileName.IsEmpty())
1508         {
1509                 _Bitmap* pRefBitmap = (this->_sharedItem->lazyScaling && this->_sharedItem->scaledNativeBitmap.get()) ? this->_sharedItem->scaledNativeBitmap.get() : this->_sharedItem->nativeBitmap.get();
1510
1511                 return pRefBitmap->IsNinePatchedBitmap();
1512         }
1513         else
1514         {
1515                 return HasNinePatchedBitmapTag(associatedFileName);
1516         }
1517 #endif
1518 }
1519
1520 void
1521 _BitmapImpl::SetAsImmutable(void)
1522 {
1523         if (INSTANCE_IS_VALID)
1524         {
1525                 if (this->_sharedItem->isMutable)
1526                 {
1527                         BufferInfo bi;
1528
1529                         if (this->Lock(bi) == E_SUCCESS)
1530                         {
1531                                 _Util::Pixmap dstImage(bi.width, bi.height, bi.bitsPerPixel, (void*)bi.pPixels, bi.pitch);
1532                                 dstImage.ConvertPremultiplied();
1533
1534                                 this->Unlock();
1535                         }
1536
1537                         this->_sharedItem->isMutable = false;
1538                         this->_sharedItem->nativeBitmap->__isPremultiplied = true;
1539
1540                         //?? this->_sharedItem->scaledNativeBitmap
1541                 }
1542         }
1543 }
1544
1545 bool
1546 _BitmapImpl::IsMutable(void) const
1547 {
1548         SysTryReturnResult(NID_GRP, INSTANCE_IS_VALID, false, "This instance is not constructed yet.");
1549
1550         return this->_sharedItem->isMutable;
1551 }
1552
1553 result
1554 _BitmapImpl::Lock(BufferInfo& info, long timeout)
1555 {
1556         SysTryReturnResult(NID_GRP, INSTANCE_IS_VALID, E_OPERATION_FAILED, "This instance is not constructed yet.");
1557
1558         _UpdateBitmapTimeStamp(*this);
1559
1560         return this->_sharedItem->nativeBitmap->Lock(info, timeout);
1561 }
1562
1563 result
1564 _BitmapImpl::Unlock()
1565 {
1566         SysTryReturnResult(NID_GRP, INSTANCE_IS_VALID, E_OPERATION_FAILED, "This instance is not constructed yet.");
1567
1568         result r = this->_sharedItem->nativeBitmap->Unlock();
1569
1570         _UpdateBitmapTimeStamp(*this);
1571
1572         if ((r == E_SUCCESS) && (this->_sharedItem->lazyScaling))
1573         {
1574                 if (this->_sharedItem->scaledNativeBitmap.get())
1575                 {
1576                         _UpdateScaledBitmapEx(this->_sharedItem->nativeBitmap.get(), this->_sharedItem->scaledNativeBitmap.get());
1577                         this->_sharedItem->scaledNativeBitmap->UpdateOpaqueInfo();
1578                 }
1579         }
1580
1581         return r;
1582 }
1583
1584 result
1585 _BitmapImpl::LockFast(BufferInfo& info, long timeout)
1586 {
1587         SysTryReturnResult(NID_GRP, INSTANCE_IS_VALID, E_OPERATION_FAILED, "This instance is not constructed yet.");
1588
1589         _UpdateBitmapTimeStamp(*this);
1590
1591         return this->_sharedItem->nativeBitmap->LockFast(info, timeout);
1592 }
1593
1594 result
1595 _BitmapImpl::UnlockFast()
1596 {
1597         SysTryReturnResult(NID_GRP, INSTANCE_IS_VALID, E_OPERATION_FAILED, "This instance is not constructed yet.");
1598
1599         result r = this->_sharedItem->nativeBitmap->UnlockFast();
1600
1601         _UpdateBitmapTimeStamp(*this);
1602
1603         if ((r == E_SUCCESS) && (this->_sharedItem->lazyScaling))
1604         {
1605                 if (this->_sharedItem->scaledNativeBitmap.get())
1606                 {
1607                         _UpdateScaledBitmapEx(this->_sharedItem->nativeBitmap.get(), this->_sharedItem->scaledNativeBitmap.get());
1608                 }
1609         }
1610
1611         return r;
1612 }
1613
1614 bool
1615 _BitmapImpl::CheckNinePatchedBitmapStrictly(const Bitmap& bitmap)
1616 {
1617         const _BitmapImpl* pThis = _BitmapImpl::GetInstance(bitmap);
1618
1619         if (!(IS_BITMAPIMPL_VALID(pThis)))
1620         {
1621                 SysLog(NID_GRP, "[E_OPERATION_FAILED] The given bitmap is not constructed yet.");
1622                 return false;
1623         }
1624
1625         if (pThis->_sharedItem->associated.hasBeenDetectedByUsingName)
1626         {
1627                 return pThis->_sharedItem->associated.determinedNinePatchedAtFirst;
1628         }
1629
1630         const Tizen::Base::String& associatedFileName = pThis->_sharedItem->associated.fileName;
1631
1632         if (associatedFileName.IsEmpty())
1633         {
1634                 _Bitmap* pRefBitmap = (pThis->_sharedItem->lazyScaling && pThis->_sharedItem->scaledNativeBitmap.get()) ? pThis->_sharedItem->scaledNativeBitmap.get() : pThis->_sharedItem->nativeBitmap.get();
1635
1636                 return pRefBitmap->IsNinePatchedBitmap(true);
1637         }
1638         else
1639         {
1640                 bool ret = HasNinePatchedBitmapTag(associatedFileName);
1641
1642                 pThis->_sharedItem->associated.hasBeenDetectedByUsingName = true;
1643                 pThis->_sharedItem->associated.determinedNinePatchedAtFirst = ret;
1644
1645                 return ret;
1646         }
1647 }
1648
1649 bool
1650 _BitmapImpl::_SetCallback(void (* DestroyCallback)(void*), void* pDestroyCallbackParam,
1651                               void (* LockCallback)(void*), void* pLockCallbackParam,
1652                               void (* UnlockCallback)(void*), void* pUnlockCallbackParam,
1653                               void (* PostlockCallback)(BufferInfo&, void*), void* pPostlockCallbackParam)
1654 {
1655         if (!(INSTANCE_IS_VALID))
1656         {
1657                 SysLog(NID_GRP, "[E_OPERATION_FAILED] This instance is not constructed yet.");
1658                 return false;
1659         }
1660
1661         _UpdateBitmapTimeStamp(*this);
1662
1663         this->_sharedItem->pDestroyCallbackFunc = DestroyCallback;
1664         this->_sharedItem->pDestroyCallbackParam = pDestroyCallbackParam;
1665
1666         this->_sharedItem->pLockCallbackFunc = LockCallback;
1667         this->_sharedItem->pLockCallbackParam = pLockCallbackParam;
1668
1669         this->_sharedItem->pUnlockCallbackFunc = UnlockCallback;
1670         this->_sharedItem->pUnlockCallbackParam = pUnlockCallbackParam;
1671
1672         this->_sharedItem->pPostlockCallbackFunc = PostlockCallback;
1673         this->_sharedItem->pPostlockCallbackParam = pPostlockCallbackParam;
1674
1675         if (this->_sharedItem->nativeBitmap.get())
1676         {
1677                 this->_sharedItem->nativeBitmap->SetCallback(LockCallback, pLockCallbackParam, UnlockCallback, pUnlockCallbackParam, PostlockCallback, pPostlockCallbackParam);
1678         }
1679
1680         if (this->_sharedItem->scaledNativeBitmap.get())
1681         {
1682                 this->_sharedItem->scaledNativeBitmap->SetCallback(LockCallback, pLockCallbackParam, UnlockCallback, pUnlockCallbackParam, PostlockCallback, pPostlockCallbackParam);
1683         }
1684
1685         return true;
1686 }
1687
1688 Bitmap*
1689 _BitmapImpl::GetExpandedBitmapN(const Bitmap& ninePatchedBitmap, int width, int height)
1690 {
1691         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);
1692
1693         SysTryReturn(NID_GRP, &ninePatchedBitmap, null, E_INVALID_ARG, "[E_INVALID_ARG] The given bitmap is invalid (null reference passed)");
1694
1695         const _BitmapImpl* pSrcBitmapImpl = _BitmapImpl::GetInstance(ninePatchedBitmap);
1696
1697         SysTryReturn(NID_GRP, BITMAPIMPL_IS_VALID(pSrcBitmapImpl), null, E_INVALID_ARG, "[E_INVALID_ARG] The given bitmap is invalid");
1698
1699         SysTryReturn(NID_GRP, pSrcBitmapImpl->IsNinePatchedBitmap(), null, E_INVALID_ARG, "[E_INVALID_ARG] The given bitmap is not a nine-patched bitmap");
1700
1701         BitmapPixelFormat pixelFormat = pSrcBitmapImpl->GetPixelColorFormat();
1702
1703         switch (pixelFormat)
1704         {
1705         case BITMAP_PIXEL_FORMAT_RGB565:
1706         case BITMAP_PIXEL_FORMAT_ARGB8888:
1707                 break;
1708         default:
1709                 SysTryReturn(NID_GRP, false, null, E_UNSUPPORTED_FORMAT, "[E_UNSUPPORTED_FORMAT] Pixel format of the given bitmap is invalid (%d)", pixelFormat);
1710                 break;
1711         }
1712
1713         return _BitmapImpl::GetExpandedBitmapFN(ninePatchedBitmap, float(width), float (height));
1714 }
1715
1716 Bitmap*
1717 _BitmapImpl::GetExpandedBitmapFN(const Bitmap& ninePatchedBitmap, float width, float height)
1718 {
1719         SysTryReturn(NID_GRP, width > 0.0f && height > 0.0f, null, E_INVALID_ARG, "[E_INVALID_ARG] The given parameter is invalid (width = %f, height = %f)", width, height);
1720
1721         SysTryReturn(NID_GRP, &ninePatchedBitmap, null, E_INVALID_ARG, "[E_INVALID_ARG] The given bitmap is invalid (null reference passed)");
1722
1723         const _BitmapImpl* pSrcBitmapImpl = _BitmapImpl::GetInstance(ninePatchedBitmap);
1724
1725         SysTryReturn(NID_GRP, BITMAPIMPL_IS_VALID(pSrcBitmapImpl), null, E_INVALID_ARG, "[E_INVALID_ARG] The given bitmap is invalid");
1726
1727         SysTryReturn(NID_GRP, pSrcBitmapImpl->IsNinePatchedBitmap(), null, E_INVALID_ARG, "[E_INVALID_ARG] The given bitmap is not a nine-patched bitmap");
1728
1729         BitmapPixelFormat pixelFormat = pSrcBitmapImpl->GetPixelColorFormat();
1730
1731         switch (pixelFormat)
1732         {
1733         case BITMAP_PIXEL_FORMAT_RGB565:
1734         case BITMAP_PIXEL_FORMAT_ARGB8888:
1735                 break;
1736         default:
1737                 SysTryReturn(NID_GRP, false, null, E_UNSUPPORTED_FORMAT, "[E_UNSUPPORTED_FORMAT] Pixel format of the given bitmap is invalid (%d)", pixelFormat);
1738                 break;
1739         }
1740
1741         std::auto_ptr<Bitmap> expandedBitmap(new (std::nothrow) Bitmap);
1742
1743         SysTryReturn(NID_GRP, expandedBitmap.get(), null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed (new Bitmap)");
1744
1745         result r = expandedBitmap->Construct(FloatDimension(width, height), pixelFormat);
1746
1747         SysTryReturn(NID_GRP, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
1748
1749         _BitmapImpl* pDstBitmapImpl = _BitmapImpl::GetInstance(*expandedBitmap.get());
1750
1751         SysAssert(pDstBitmapImpl != null);
1752
1753         {
1754                 _Util::LockManager srcBitmap(*pSrcBitmapImpl);
1755                 _Util::LockManager dstBitmap(*pDstBitmapImpl);
1756
1757                 SysTryReturn(NID_GRP, srcBitmap.IsValid(), null, srcBitmap.GetResult(), "[%s] Buffer locking of the source bitmap failed", srcBitmap.GetResult());
1758                 SysTryReturn(NID_GRP, dstBitmap.IsValid(), null, dstBitmap.GetResult(), "[%s] Buffer locking of the target bitmap failed", dstBitmap.GetResult());
1759
1760                 if (dstBitmap.GetBufferInfo().width < srcBitmap.GetBufferInfo().width - 2 ||
1761                         dstBitmap.GetBufferInfo().height < srcBitmap.GetBufferInfo().height - 2)
1762                 {
1763                         // down-scales from the source bitmap only
1764                         const BufferInfo& srcBufferInfo = srcBitmap.GetBufferInfo();
1765                         const BufferInfo& dstBufferInfo = dstBitmap.GetBufferInfo();
1766
1767                         memset(dstBufferInfo.pPixels, 0, dstBufferInfo.pitch * dstBufferInfo.height);
1768
1769                         _Util::Pixmap dstImage(dstBufferInfo.width, dstBufferInfo.height, dstBufferInfo.bitsPerPixel, (void*) dstBufferInfo.pPixels, dstBufferInfo.pitch);
1770
1771                         Rectangle sourRect(1, 1, srcBufferInfo.width - 2, srcBufferInfo.height - 2);
1772                         Rectangle destRect(0, 0, dstBufferInfo.width, dstBufferInfo.height);
1773
1774                         unsigned char* pSrcPixels = (unsigned char*) srcBufferInfo.pPixels + sourRect.y * srcBufferInfo.pitch + sourRect.x * (srcBufferInfo.bitsPerPixel / 8);
1775                         _Util::Pixmap srcImage(sourRect.width, sourRect.height, srcBufferInfo.bitsPerPixel, (void*) pSrcPixels, srcBufferInfo.pitch);
1776
1777                         Tizen::Graphics::_Effect::ScaleImage(dstImage, destRect.x, destRect.y, destRect.width, destRect.height, srcImage, Tizen::Graphics::_Effect::ROP_COPY);
1778                 }
1779                 else
1780                 {
1781                         const BufferInfo& srcBufferInfo = srcBitmap.GetBufferInfo();
1782                         const BufferInfo& dstBufferInfo = dstBitmap.GetBufferInfo();
1783
1784                         memset(dstBufferInfo.pPixels, 0, dstBufferInfo.pitch * dstBufferInfo.height);
1785
1786                         _Util::Pixmap dstImage(dstBufferInfo.width, dstBufferInfo.height, dstBufferInfo.bitsPerPixel, (void*) dstBufferInfo.pPixels, dstBufferInfo.pitch);
1787
1788                         _Util::AccumList<_Util::Pair<_Util::Rectangle<int>, _Util::Rectangle<int> > > boundsList;
1789
1790                         Rectangle destRect(0, 0, dstBufferInfo.width, dstBufferInfo.height);
1791
1792                         // assert(pSrcBitmapImpl->_nativeBitmap);
1793                         r = _Util::GetPatchList(boundsList, destRect, *pSrcBitmapImpl->_sharedItem->nativeBitmap.get());
1794
1795                         SysTryReturn(NID_GRP, r == E_SUCCESS, null, E_SYSTEM, "[E_SYSTEM] _Util::GetPatchList() failed (error = %#x)", r);
1796
1797                         _Util::AccumList<_Util::Pair<_Util::Rectangle<int>, _Util::Rectangle<int> > >::Iterator iter = boundsList.Begin();
1798
1799                         while (iter != boundsList.End())
1800                         {
1801                                 Rectangle destRect(iter->first.x, iter->first.y, iter->first.w, iter->first.h);
1802                                 Rectangle sourRect(iter->second.x, iter->second.y, iter->second.w, iter->second.h);
1803
1804                                 {
1805                                         unsigned char* pSrcPixels = (unsigned char*) srcBufferInfo.pPixels + sourRect.y * srcBufferInfo.pitch + sourRect.x * (srcBufferInfo.bitsPerPixel / 8);
1806                                         _Util::Pixmap srcImage(sourRect.width, sourRect.height, srcBufferInfo.bitsPerPixel, (void*) pSrcPixels, srcBufferInfo.pitch);
1807
1808                                         Tizen::Graphics::_Effect::ScaleImage(dstImage, destRect.x, destRect.y, destRect.width, destRect.height, srcImage, Tizen::Graphics::_Effect::ROP_COPY);
1809                                 }
1810
1811                                 ++iter;
1812                         }
1813                 }
1814         }
1815
1816         return expandedBitmap.release();
1817 }
1818
1819 Bitmap*
1820 _BitmapImpl::GetColorReplacedBitmapN(const Bitmap& bitmap, const Color& replacedColor, const Color& newColor)
1821 {
1822         SysTryReturn(NID_GRP, &bitmap, null, E_INVALID_ARG, "[E_INVALID_ARG] The given bitmap is invalid (null reference passed)");
1823
1824         std::auto_ptr<Bitmap> pRetBitmap;
1825
1826         {
1827                 Bitmap* pSrcBitmap = const_cast<Bitmap*>(&bitmap);
1828
1829                 BufferInfo biSrc;
1830                 pSrcBitmap->Lock(biSrc);
1831                 {
1832                         pRetBitmap.reset(_BitmapUtil::CreateBitmapN(Dimension(biSrc.width, biSrc.height), biSrc.bitsPerPixel));
1833
1834                         if (pRetBitmap.get())
1835                         {
1836                                 BufferInfo biDst;
1837                                 pRetBitmap->Lock(biDst);
1838
1839                                 if ((biSrc.pitch == biDst.pitch) && (biSrc.height == biDst.height))
1840                                 {
1841                                         memcpy(biDst.pPixels, biSrc.pPixels, biDst.pitch * biDst.height);
1842                                 }
1843
1844                                 pRetBitmap->Unlock();
1845                         }
1846                 }
1847                 pSrcBitmap->Unlock();
1848
1849                 SysTryReturn(NID_GRP, pRetBitmap.get(), null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] New bitmap construction failed");
1850         }
1851
1852         BufferInfo bufferInfo;
1853
1854         result r = pRetBitmap->Lock(bufferInfo);
1855
1856         SysTryReturn(NID_GRP, r == E_SUCCESS, null, E_SYSTEM, "[E_SYSTEM] The allocated bitmap cannot retrieve the own buffer address");
1857
1858         if (bufferInfo.bitsPerPixel == 32)
1859         {
1860                 typedef unsigned long Pixel;
1861
1862                 Pixel keyColor = replacedColor.GetRGB32() & 0x00FFFFFF;
1863                 Pixel chgColor = newColor.GetRGB32() & 0x00FFFFFF;
1864                 Pixel* pBuffer = reinterpret_cast<Pixel*>(bufferInfo.pPixels);
1865                 int padding = bufferInfo.pitch * 8 / bufferInfo.bitsPerPixel - bufferInfo.width;
1866
1867                 Pixel keyAlpha = (newColor.GetRGB32() & 0xFF000000) >> 24;
1868                 keyAlpha += (keyAlpha >> 7);
1869
1870                 if (keyAlpha < 256)
1871                 {
1872                         for (int y = 0; y < bufferInfo.height; y++)
1873                         {
1874                                 for (int x = 0; x < bufferInfo.width; x++)
1875                                 {
1876                                         // if buffer.rgb = replacedColor.rgb then begin
1877                                         //    buffer.a <- buffer.a * newColor.a;
1878                                         //    buffer.r <- newColor.r;
1879                                         //    buffer.g <- newColor.g;
1880                                         //    buffer.b <- newColor.b;
1881                                         // end if
1882
1883                                         if ((*pBuffer & 0x00FFFFFF) == keyColor)
1884                                         {
1885                                                 Pixel alpha = (*pBuffer >> 8) & 0x00FF0000;
1886                                                 alpha = (alpha * keyAlpha) & 0xFF000000;
1887
1888                                                 *pBuffer = alpha | chgColor;
1889                                         }
1890
1891                                         ++pBuffer;
1892                                 }
1893
1894                                 pBuffer += padding;
1895                         }
1896                 }
1897                 else
1898                 {
1899                         for (int y = 0; y < bufferInfo.height; y++)
1900                         {
1901                                 for (int x = 0; x < bufferInfo.width; x++)
1902                                 {
1903                                         // if buffer.rgb = replacedColor.rgb then begin
1904                                         //    buffer.a <- buffer.a;
1905                                         //    buffer.r <- newColor.r;
1906                                         //    buffer.g <- newColor.g;
1907                                         //    buffer.b <- newColor.b;
1908                                         // end if
1909
1910                                         if ((*pBuffer & 0x00FFFFFF) == keyColor)
1911                                         {
1912                                                 *pBuffer = (*pBuffer & 0xFF000000) | chgColor;
1913                                         }
1914
1915                                         ++pBuffer;
1916                                 }
1917
1918                                 pBuffer += padding;
1919                         }
1920                 }
1921         }
1922         else if (bufferInfo.bitsPerPixel == 16)
1923         {
1924                 typedef unsigned short Pixel;
1925
1926                 Pixel keyColor = 0;
1927                 Pixel chgColor = 0;
1928                 Pixel* pBuffer = reinterpret_cast<Pixel*>(bufferInfo.pPixels);
1929                 int padding = bufferInfo.pitch * 8 / bufferInfo.bitsPerPixel - bufferInfo.width;
1930
1931                 {
1932                         unsigned long color32 = replacedColor.GetRGB32();
1933                         _Effect::Func::ConvertColorFormatFast(&keyColor, &color32);
1934                 }
1935
1936                 {
1937                         unsigned long color32 = newColor.GetRGB32() & 0x00FFFFFF;
1938                         _Effect::Func::ConvertColorFormatFast(&chgColor, &color32);
1939                 }
1940
1941                 for (int y = 0; y < bufferInfo.height; y++)
1942                 {
1943                         for (int x = 0; x < bufferInfo.width; x++)
1944                         {
1945                                 if (*pBuffer == keyColor)
1946                                 {
1947                                         *pBuffer = chgColor;
1948                                 }
1949
1950                                 ++pBuffer;
1951                         }
1952
1953                         pBuffer += padding;
1954                 }
1955         }
1956         else
1957         {
1958                 return null;
1959         }
1960
1961         pRetBitmap->Unlock();
1962
1963         return pRetBitmap.release();
1964 }
1965
1966 Bitmap*
1967 _BitmapImpl::CloneN(const Bitmap& bitmap)
1968 {
1969         const _BitmapImpl* pSrcBitmapImpl = null;
1970         _BitmapImpl* pDstBitmapImpl = null;
1971
1972         // source bitmap verification
1973         {
1974                 SysTryReturn(NID_GRP, &bitmap, null, E_INVALID_ARG, "[E_INVALID_ARG] The given bitmap is invalid (null reference passed)");
1975
1976                 pSrcBitmapImpl = _BitmapImpl::GetInstance(bitmap);
1977
1978                 SysTryReturn(NID_GRP, IS_BITMAPIMPL_VALID(pSrcBitmapImpl), null, E_INVALID_ARG, "[E_INVALID_ARG] The given bitmap is invalid");
1979         }
1980
1981         // destination bitmap allocation
1982         std::auto_ptr<Bitmap> pRetBitmap(new (std::nothrow) Bitmap);
1983
1984         {
1985                 SysTryReturn(NID_GRP, pRetBitmap.get(), null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed (new Bitmap)");
1986
1987                 pDstBitmapImpl = _BitmapImpl::GetInstance(*pRetBitmap.get());
1988
1989                 SysTryReturn(NID_GRP, pDstBitmapImpl && pDstBitmapImpl->_sharedItem.get() && !pDstBitmapImpl->_sharedItem->nativeBitmap->IsValid(), null, E_SYSTEM, "[E_SYSTEM] The allocated bitmap is invalid");
1990         }
1991
1992         pDstBitmapImpl->_sharedItem = pSrcBitmapImpl->_sharedItem;
1993
1994         return pRetBitmap.release();
1995 }
1996
1997 _BitmapImpl*
1998 _BitmapImpl::GetNonScaledBitmapImplN(const Tizen::Base::ByteBuffer& buffer, const Dimension& dim, BitmapPixelFormat pixelFormat)
1999 {
2000         return _NonScale::CreateBitmapN(buffer, dim, pixelFormat);
2001 }
2002
2003 Bitmap*
2004 _BitmapImpl::GetNonScaledBitmapN(const Tizen::Base::ByteBuffer& buffer, const Dimension& dim, BitmapPixelFormat pixelFormat)
2005 {
2006         _BitmapImpl* pBitmapImpl = _BitmapImpl::GetNonScaledBitmapImplN(buffer, dim, pixelFormat);
2007
2008         if (pBitmapImpl == null)
2009         {
2010                 return null;
2011         }
2012
2013         return Tizen::Graphics::_BitmapUtil::CreateBitmapN(pBitmapImpl);
2014 }
2015
2016 Bitmap*
2017 _BitmapImpl::GetNonScaledBitmapN(const Tizen::Base::ByteBuffer& buffer, const Dimension& dim, BitmapPixelFormat pixelFormat, const FloatDimension& logicalSize)
2018 {
2019         Bitmap* pBitmap = GetNonScaledBitmapN(buffer, dim, pixelFormat);
2020
2021         if (pBitmap)
2022         {
2023                 _BitmapImpl* pBitmapImpl = _BitmapImpl::GetInstance(*pBitmap);
2024
2025                 if (pBitmapImpl)
2026                 {
2027                         pBitmapImpl->_sharedItem->coordHolder->size.vcFloat.w = logicalSize.width;
2028                         pBitmapImpl->_sharedItem->coordHolder->size.vcFloat.h = logicalSize.height;
2029                 }
2030                 else
2031                 {
2032                         delete pBitmap;
2033                         pBitmap = null;
2034                 }
2035         }
2036
2037         return pBitmap;
2038 }
2039
2040 bool
2041 _BitmapImpl::HasNinePatchedBitmapTag(Tizen::Base::String fileName)
2042 {
2043         const wchar_t* NINE_PATCHED_TAG = L".#.png"; // it must consist of lower-case characters
2044         const int NINE_PATCHED_TAG_LENGTH = 6;
2045
2046         struct Temp
2047         {
2048                 static wchar_t ToLower(wchar_t ch)
2049                 {
2050                         return (ch >= L'A' && ch <= L'Z') ? ch + 'a' - 'A' : ch;
2051                 }
2052         };
2053
2054         _Util::String tempStr(fileName.GetPointer(), fileName.GetLength());
2055
2056         while (tempStr.length > 0 && tempStr.pStart[tempStr.length - 1] == L' ')
2057         {
2058                 --tempStr.length;
2059         }
2060
2061         _Util::String testStr(tempStr.pStart, tempStr.length, tempStr.length - NINE_PATCHED_TAG_LENGTH, NINE_PATCHED_TAG_LENGTH);
2062
2063         if (testStr.length == NINE_PATCHED_TAG_LENGTH)
2064         {
2065                 for (int i = 0; i < NINE_PATCHED_TAG_LENGTH; i++)
2066                 {
2067                         if (Temp::ToLower(testStr.pStart[i]) == NINE_PATCHED_TAG[i])
2068                         {
2069                                 continue;
2070                         }
2071
2072                         return false;
2073                 }
2074
2075                 return true;
2076         }
2077
2078         return false;
2079 }
2080
2081 void
2082 _BitmapImpl::SetAsPremultiplied(void)
2083 {
2084         if (IS_INSTANCE_VALID)
2085         {
2086                 this->_sharedItem->isMutable = false;
2087                 this->_sharedItem->nativeBitmap->__isPremultiplied = true;
2088         }
2089 }
2090
2091 void
2092 _BitmapImpl::SetAsNonpremultiplied(void)
2093 {
2094         if (IS_INSTANCE_VALID)
2095         {
2096                 this->_sharedItem->isMutable = true;
2097                 this->_sharedItem->nativeBitmap->__isPremultiplied = false;
2098         }
2099 }
2100
2101 result
2102 _BitmapImpl::ConvertToNonpremultiplied(Bitmap& bitmap, bool forceConversion)
2103 {
2104         _BitmapImpl* pImpl = null;
2105
2106         // bitmap verification
2107         {
2108                 SysTryReturn(NID_GRP, &bitmap, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The given bitmap is invalid (null reference passed)");
2109
2110                 pImpl = _BitmapImpl::GetInstance(bitmap);
2111
2112                 SysTryReturn(NID_GRP, IS_BITMAPIMPL_VALID(pImpl), E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The given bitmap is invalid");
2113         }
2114
2115         if (!forceConversion)
2116         {
2117                 SysTryReturn(NID_GRP, !pImpl->_sharedItem->isMutable, E_INVALID_CONDITION, E_INVALID_CONDITION, "[E_INVALID_CONDITION] The given bitmap is already non-premultipied");
2118         }
2119
2120         {
2121                 BufferInfo bi;
2122
2123                 if (pImpl->Lock(bi) == E_SUCCESS)
2124                 {
2125                         _Util::Pixmap dstImage(bi.width, bi.height, bi.bitsPerPixel, (void*)bi.pPixels, bi.pitch);
2126                         dstImage.isPremultiplied = true;
2127                         dstImage.ConvertNonpremultiplied();
2128
2129                         pImpl->Unlock();
2130                 }
2131
2132                 pImpl->_sharedItem->isMutable = true;
2133                 pImpl->_sharedItem->nativeBitmap->__isPremultiplied = false;
2134
2135                 //?? this->_sharedItem->scaledNativeBitmap
2136         }
2137
2138         return E_SUCCESS;
2139 }
2140
2141 _BitmapImpl*&
2142 _BitmapImpl::_GetBitmapImpl(Bitmap* pBitmap)
2143 {
2144         return pBitmap->__pImpl;
2145 }
2146
2147 _BitmapImpl*
2148 _BitmapImpl::GetInstance(Bitmap& bitmap)
2149 {
2150         return (&bitmap != null) ? bitmap.__pImpl : null;
2151 }
2152
2153 const _BitmapImpl*
2154 _BitmapImpl::GetInstance(const Bitmap& bitmap)
2155 {
2156         return (&bitmap != null) ? bitmap.__pImpl : null;
2157 }
2158
2159 bool
2160 _BitmapImpl::__CheckValidity(bool canBufferExpand)
2161 {
2162         if (this->_sharedItem.get())
2163         {
2164                 if (this->_sharedItem->nativeBitmap->IsValid())
2165                 {
2166                         return true;
2167                 }
2168
2169                 if (!this->_sharedItem->associated.fileName.IsEmpty())
2170                 {
2171                         if (canBufferExpand)
2172                         {
2173                                 if (!__RealizeBuffer())
2174                                 {
2175                                         // linkedFileName does not exist or is not a image file.
2176                                         this->Construct(Dimension(1, 1), BITMAP_PIXEL_FORMAT_ARGB8888);
2177                                 }
2178
2179                                 this->_sharedItem->associated.fileName.Clear();
2180                         }
2181
2182                         return true;
2183                 }
2184         }
2185
2186         return false;
2187 }
2188
2189 bool
2190 _BitmapImpl::__RealizeBuffer(void)
2191 {
2192         int imageWidth = 0;
2193         int imageHeight = 0;
2194
2195         Tizen::Media::MediaPixelFormat format = Tizen::Media::MEDIA_PIXEL_FORMAT_BGRA8888;
2196
2197         // The following does not consider the case of big-endian
2198         switch (this->_sharedItem->associated.pixelFormat)
2199         {
2200         case BITMAP_PIXEL_FORMAT_RGB565:
2201                 format = Tizen::Media::MEDIA_PIXEL_FORMAT_RGB565LE;
2202                 break;
2203         case BITMAP_PIXEL_FORMAT_R8G8B8A8:
2204                 format = Tizen::Media::MEDIA_PIXEL_FORMAT_RGBA8888;
2205                 break;
2206         case BITMAP_PIXEL_FORMAT_ARGB8888:
2207         default:
2208                 format = Tizen::Media::MEDIA_PIXEL_FORMAT_BGRA8888;
2209                 break;
2210         }
2211
2212         std::auto_ptr<ByteBuffer> pImageBuffer(Tizen::Media::_ImageDecoder::DecodeToBufferN(this->_sharedItem->associated.fileName, format, imageWidth, imageHeight));
2213
2214         if (pImageBuffer.get() == null)
2215         {
2216                 return false;
2217         }
2218
2219         std::auto_ptr<_BitmapImpl> pTempBitmapImpl(_BitmapImpl::GetNonScaledBitmapImplN(*pImageBuffer, Dimension(imageWidth, imageHeight), this->_sharedItem->associated.pixelFormat));
2220
2221         if (pTempBitmapImpl.get() == null || pTempBitmapImpl->_sharedItem.get() == null)
2222         {
2223                 return false;
2224         }
2225
2226         pImageBuffer.reset();
2227
2228         this->_sharedItem->Move(*(pTempBitmapImpl->_sharedItem.get()));
2229
2230         return true;
2231 }
2232
2233 result
2234 _BitmapImpl::__Scale(const float width, const float height)
2235 {
2236         result r = E_SUCCESS;
2237
2238         _Util::Dimension<float> vcUtilDimF = { width, height };
2239         _BitmapCoordinateHolder tempCoordinateHolder;
2240
2241         tempCoordinateHolder.ResetFromVc(vcUtilDimF);
2242
2243         Dimension vcDim(tempCoordinateHolder.size.vcInt.w, tempCoordinateHolder.size.vcInt.h);
2244
2245         if (_ResUtil::NeedToConvertCoord())
2246         {
2247                 if (this->_sharedItem->lazyScaling && this->_sharedItem->scaledNativeBitmap.get())
2248                 {
2249                         r = this->_sharedItem->nativeBitmap->Scale(vcDim);
2250
2251                         if (!IsFailed(r))
2252                         {
2253                                 Dimension pcDim(tempCoordinateHolder.size.pcInt.w, tempCoordinateHolder.size.pcInt.h);
2254
2255                                 r = this->_sharedItem->scaledNativeBitmap->Scale(pcDim);
2256
2257                                 if (!IsFailed(r))
2258                                 {
2259                                         _UpdateScaledBitmapEx(this->_sharedItem->nativeBitmap.get(), this->_sharedItem->scaledNativeBitmap.get());
2260                                 }
2261                                 // @ykahn If it fails, then how to undo its status.
2262                         }
2263                 }
2264                 else
2265                 {
2266                         Dimension pcDim(tempCoordinateHolder.size.pcInt.w, tempCoordinateHolder.size.pcInt.h);
2267
2268                         r = this->_sharedItem->nativeBitmap->Scale(pcDim);
2269                 }
2270         }
2271         else
2272         {
2273                 r = this->_sharedItem->nativeBitmap->Scale(vcDim);
2274         }
2275
2276         if (r == E_SUCCESS)
2277         {
2278                 memcpy(this->_sharedItem->coordHolder.get(), &tempCoordinateHolder, sizeof(tempCoordinateHolder));
2279         }
2280
2281         return r;
2282 }
2283
2284 void _BitmapImpl::_SharedItem::Move(_BitmapImpl::_SharedItem& source)
2285 {
2286         std::swap(this->nativeBitmap, source.nativeBitmap);
2287         std::swap(this->coordHolder, source.coordHolder);
2288         std::swap(this->lazyScaling, source.lazyScaling);
2289         std::swap(this->scaledNativeBitmap, source.scaledNativeBitmap);
2290         std::swap(this->isMutable, source.isMutable);
2291 }
2292
2293 }} // Tizen::Graphics