Tizen 2.1 base
[framework/osp/uifw.git] / src / graphics / FGrp_Canvas.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Flora License, Version 1.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://floralicense.org/license/
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an AS IS BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /*
19  * @file        FGrp_Canvas.cpp
20  * @brief       This is the implementation file for _Canvas class.
21  *
22  */
23
24 #include <new>
25 #include <memory>
26
27 #include <cstdio>
28 #include <cmath>
29
30 #include <unique_ptr.h>
31
32 #include <Evas.h>
33
34 #include <FGrpBufferInfo.h>
35
36 #include <FBaseInternalTypes.h>
37 #include <FApp_AppInfo.h>
38
39 #include <FBaseSysLog.h>
40
41 #include "FGrp_BufferInfoImpl.h"
42 #include "FGrp_Callback.h"
43 #include "FGrp_Canvas.h"
44 #include "FGrp_CanvasGpPrimitive.h"
45 #include "FGrp_CanvasRasterOp.h"
46 #include "FGrp_Bitmap.h"
47 #include "FGrp_Font.h"
48 #include "FGrp_Screen.h"
49 #include "FGrp_ResUtil.h"
50 #include "FGrp_CanvasCairo.h"
51 #include "FGrp_CanvasPixman.h"
52 #include "util/FGrp_Util.h"
53 #include "effect/FGrp_Effect.h"
54
55 ////////////////////////////////////////////////////////////////////////////////
56
57 #if !defined(M_PI)
58 #define M_PI 3.14159265358979323846
59 #endif
60
61 #define USE_CAIRO
62
63 ////////////////////////////////////////////////////////////////////////////////
64
65 #define SET_CAIRO_DASH_STYLE \
66         _Cairo::SetDash(pCairo->pCairo, this->__dashData.pattern.Begin(), int(this->__dashData.pattern.Size()), this->__dashData.offset)
67
68 #define RESET_CAIRO_DASH_STYLE \
69         _Cairo::ResetDash(pCairo->pCairo)
70
71 #define SET_CAIRO_CLIPPING \
72         if (this->__isClipBoundsSet) \
73         { \
74                 _Cairo::SetClip(pCairo->pCairo, this->__clipBounds.x, this->__clipBounds.y, this->__clipBounds.width, this->__clipBounds.height); \
75         }
76
77 #define RESET_CAIRO_CLIPPING \
78         if (this->__isClipBoundsSet) \
79         { \
80                 _Cairo::ResetClip(pCairo->pCairo); \
81         }
82
83 #define SET_CAIRO_BLENDING \
84         _Cairo::SetBlending(pCairo->pCairo, _ConvertParam<cairo_operator_t>(this->__blendingMode));
85
86 #define RESET_CAIRO_BLENDING \
87         _Cairo::SetBlending(pCairo->pCairo, CAIRO_OPERATOR_OVER);
88
89
90 ////////////////////////////////////////////////////////////////////////////////
91
92 using namespace Tizen::Base;
93 using namespace Tizen::Base::Collection;
94 using namespace Tizen::Base::Utility;
95
96 ////////////////////////////////////////////////////////////////////////////////
97 // internal utility
98
99 namespace
100 {
101
102 template<typename Dest, typename Sour>
103 Dest _ConvertParam(Sour val);
104
105 template<>
106 Tizen::Graphics::_Effect::Rop
107 _ConvertParam(Tizen::Graphics::_Canvas::BlendOption blendOption)
108 {
109         switch (blendOption)
110         {
111         case Tizen::Graphics::_Canvas::BLEND_COPY:
112                 return Tizen::Graphics::_Effect::ROP_COPY;
113         case Tizen::Graphics::_Canvas::BLEND_ALPHABLEND:
114                 return Tizen::Graphics::_Effect::ROP_ALPHABLEND;
115         default:
116                 return Tizen::Graphics::_Effect::ROP_ALPHABLEND;
117         }
118 }
119
120 template<>
121 cairo_operator_t
122 _ConvertParam(Tizen::Graphics::BlendingMode blendingMode)
123 {
124         switch (blendingMode)
125         {
126         case Tizen::Graphics::BLENDING_MODE_CLEAR:
127                 return CAIRO_OPERATOR_CLEAR;
128         case Tizen::Graphics::BLENDING_MODE_SRC:
129                 return CAIRO_OPERATOR_SOURCE;
130         case Tizen::Graphics::BLENDING_MODE_DST:
131                 return CAIRO_OPERATOR_DEST;
132         case Tizen::Graphics::BLENDING_MODE_SRC_OVER:
133                 return CAIRO_OPERATOR_OVER;
134         case Tizen::Graphics::BLENDING_MODE_DST_OVER:
135                 return CAIRO_OPERATOR_DEST_OVER;
136         case Tizen::Graphics::BLENDING_MODE_SRC_IN:
137                 return CAIRO_OPERATOR_IN;
138         case Tizen::Graphics::BLENDING_MODE_DST_IN:
139                 return CAIRO_OPERATOR_DEST_IN;
140         case Tizen::Graphics::BLENDING_MODE_SRC_OUT:
141                 return CAIRO_OPERATOR_OUT;
142         case Tizen::Graphics::BLENDING_MODE_DST_OUT:
143                 return CAIRO_OPERATOR_DEST_OUT;
144         case Tizen::Graphics::BLENDING_MODE_SRC_ATOP:
145                 return CAIRO_OPERATOR_ATOP;
146         case Tizen::Graphics::BLENDING_MODE_DST_ATOP:
147                 return CAIRO_OPERATOR_DEST_ATOP;
148         case Tizen::Graphics::BLENDING_MODE_DST_XOR:
149                 return CAIRO_OPERATOR_XOR;
150         case Tizen::Graphics::BLENDING_MODE_ADD:
151                 return CAIRO_OPERATOR_ADD;
152         case Tizen::Graphics::BLENDING_MODE_SATURATE:
153                 return CAIRO_OPERATOR_SATURATE;
154         default:
155                 return CAIRO_OPERATOR_OVER;
156         }
157 }
158
159 inline unsigned short
160 _ConvertRGB888ToRGB565(unsigned char red, unsigned char green, unsigned char blue)
161 {
162         typedef unsigned short ColorType;
163
164         return (ColorType(red >> 3) << 11) | (ColorType(green >> 2) << 5) | ColorType(blue >> 3);
165 }
166
167 Evas_Object*
168 _GetWindowSourceObject(Handle handle)
169 {
170         Evas_Object* pSourceObject = evas_object_image_source_get((Evas_Object*) handle);
171
172         return (pSourceObject) ? pSourceObject : (Evas_Object*) handle;
173 }
174
175 int
176 _GetWindowWidth(Handle handle)
177 {
178         int width = 0;
179         int height = 0;
180
181         evas_object_image_size_get(_GetWindowSourceObject(handle), &width, &height);
182
183         return width;
184 }
185
186 int
187 _GetWindowHeight(Handle handle)
188 {
189         int width = 0;
190         int height = 0;
191
192         evas_object_image_size_get(_GetWindowSourceObject(handle), &width, &height);
193
194         return height;
195 }
196
197 ///////////////////////////////////////////////
198 // class _GenericBufferFrameBuffer
199
200 template<typename Pixel>
201 class _GenericBufferFrameBuffer
202         : public Tizen::Graphics::_Util::GenericBufferBase<Pixel>
203 {
204 public:
205         _GenericBufferFrameBuffer(Handle handle, int _width, int _height)
206         {
207                 this->__pAssociatedBuffer = this->_pBuffer = (Pixel*) evas_object_image_data_get(_GetWindowSourceObject(handle), EINA_TRUE);
208
209                 int pitch = evas_object_image_stride_get(_GetWindowSourceObject(handle)) / int(sizeof(Pixel));
210                 pitch = (pitch) ? pitch : _width;
211
212                 if (this->_pBuffer == null)
213                 {
214                         SysLog(NID_GRP, "[] evas_object_image_data_get(%d) failed!", handle);
215                 }
216
217                 this->_pitch = pitch;
218                 this->_padding = this->_pitch - _width;
219                 this->_rect.x = 0;
220                 this->_rect.y = 0;
221                 this->_rect.w = _width;
222                 this->_rect.h = _height;
223                 this->_pHandle = reinterpret_cast<void*>(handle);
224
225                 this->__associatedHandle = handle;
226                 this->__hasOwnership = false;
227         }
228
229         _GenericBufferFrameBuffer(Handle handle, int _x, int _y, int _width, int _height, int pitch)
230         {
231                 this->__pAssociatedBuffer = this->_pBuffer = (Pixel*) evas_object_image_data_get(_GetWindowSourceObject(handle), EINA_TRUE);
232
233                 if (pitch == 0)
234                 {
235                         pitch = evas_object_image_stride_get(_GetWindowSourceObject(handle)) / int(sizeof(Pixel));
236                         pitch = (pitch) ? pitch : _GetWindowWidth(handle);
237                 }
238
239                 if (this->_pBuffer == null)
240                 {
241                         SysLog(NID_GRP, "[] evas_object_image_data_get(%d) failed!", handle);
242                 }
243
244                 this->_pBuffer += (_y * pitch + _x);
245
246                 this->_pitch = pitch;
247                 this->_padding = this->_pitch - _width;
248                 this->_rect.x = _x;
249                 this->_rect.y = _y;
250                 this->_rect.w = _width;
251                 this->_rect.h = _height;
252                 this->_pHandle = reinterpret_cast<void*>(handle);
253
254                 this->__associatedHandle = handle;
255                 this->__hasOwnership = false;
256         }
257
258         _GenericBufferFrameBuffer(int width, int height)
259                 : __pAssociatedBuffer(0)
260         {
261                 this->_pBuffer = new (std::nothrow) Pixel[width * height];
262
263                 if (this->_pBuffer == null)
264                 {
265                         width = 0;
266                         height = 0;
267                 }
268
269                 this->_pitch = width;
270                 this->_padding = this->_pitch - width;
271                 this->_rect.x = 0;
272                 this->_rect.y = 0;
273                 this->_rect.w = width;
274                 this->_rect.h = height;
275                 this->_pHandle = 0;
276
277                 this->__associatedHandle = 0;
278                 this->__hasOwnership = (this->_pBuffer != null);
279         }
280
281         _GenericBufferFrameBuffer(Pixel* pBuffer, int width, int height, int pitch)
282                 : __pAssociatedBuffer(0)
283         {
284                 this->_pBuffer = pBuffer;
285
286                 this->_pitch = pitch;
287                 this->_padding = this->_pitch - width;
288                 this->_rect.x = 0;
289                 this->_rect.y = 0;
290                 this->_rect.w = width;
291                 this->_rect.h = height;
292                 this->_pHandle = 0;
293
294                 this->__associatedHandle = 0;
295                 this->__hasOwnership = false;
296         }
297
298         virtual ~_GenericBufferFrameBuffer(void)
299         {
300                 if (this->__associatedHandle != 0 && this->__pAssociatedBuffer != null)
301                 {
302                         evas_object_image_data_set(_GetWindowSourceObject(this->__associatedHandle), this->__pAssociatedBuffer);
303                 }
304
305                 if (this->__hasOwnership)
306                 {
307                         delete[] this->_pBuffer;
308                         this->_pBuffer = 0;
309                 }
310         }
311
312 private:
313         _GenericBufferFrameBuffer(const _GenericBufferFrameBuffer&);
314         _GenericBufferFrameBuffer& operator =(const _GenericBufferFrameBuffer&);
315
316         void* __pAssociatedBuffer;
317         Handle __associatedHandle;
318         bool __hasOwnership;
319
320 };
321
322 }
323
324
325 namespace
326 {
327
328 enum _ClipResult
329 {
330         CLIP_REJECT, // Clipped rejected
331         CLIP_CLIPPED, // Clipped accepted
332         CLIP_ACCEPT // Accepted
333 };
334
335 _ClipResult
336 _ClipRectangle(int& srcX, int& srcY, int& srcW, int& srcH, int clipX, int clipY, int clipW, int clipH)
337 {
338         if (clipW <= 0 || clipH <= 0)
339         {
340                 return CLIP_REJECT;
341         }
342
343         _ClipResult returnValue = CLIP_ACCEPT;
344
345         int srcEndX = srcX + srcW - 1;
346         int srcEndY = srcY + srcH - 1;
347         int clipEndX = clipX + clipW - 1;
348         int clipEndY = clipY + clipH - 1;
349
350         if (srcX > clipEndX || srcEndX < clipX)
351         {
352                 return CLIP_REJECT;
353         }
354
355         if (srcY > clipEndY || srcEndY < clipY)
356         {
357                 return CLIP_REJECT;
358         }
359
360         if (srcX < clipX)
361         {
362                 srcX = clipX;
363
364                 returnValue = CLIP_CLIPPED;
365         }
366
367         if (srcEndX > clipEndX)
368         {
369                 srcEndX = clipEndX;
370
371                 returnValue = CLIP_CLIPPED;
372         }
373
374         if (srcY < clipY)
375         {
376                 srcY = clipY;
377
378                 returnValue = CLIP_CLIPPED;
379         }
380
381         if (srcEndY > clipEndY)
382         {
383                 srcEndY = clipEndY;
384
385                 returnValue = CLIP_CLIPPED;
386         }
387
388         srcW = srcEndX - srcX + 1;
389         srcH = srcEndY - srcY + 1;
390
391         return returnValue;
392 }
393
394 unsigned long
395 _ComposeColor(unsigned long color32, int opacity)
396 {
397         unsigned char alpha = (unsigned char) (((color32) >> 24));
398         unsigned char red = (unsigned char) (((color32) >> 16));
399         unsigned char green = (unsigned char) (((color32) >> 8));
400         unsigned char blue = (unsigned char) ((color32));
401
402         alpha = (unsigned char) ((alpha * opacity + 255) >> 8);
403         red = (unsigned char) ((red * opacity + 255) >> 8);
404         green = (unsigned char) ((green * opacity + 255) >> 8);
405         blue = (unsigned char) ((blue * opacity + 255) >> 8);
406
407         return (unsigned long) (((unsigned long) (alpha) << 24) | ((unsigned long) (red) << 16) | ((unsigned long) (green) << 8) | (unsigned long) (blue));
408 }
409
410 template<typename Pixel>
411 void
412 _ClearRectangleWithClip(Tizen::Graphics::_Util::ScratchPad<Pixel>* pScratchPad, Pixel color, const Tizen::Graphics::_Util::Rectangle<int>& rect, const Tizen::Graphics::_Util::Rectangle<int>& clip)
413 {
414         if (pScratchPad == null)
415         {
416                 return;
417         }
418
419         // clipping
420         int x1 = rect.x;
421         int y1 = rect.y;
422         int x2 = x1 + rect.w;
423         int y2 = y1 + rect.h;
424
425         x1 = (x1 >= clip.x) ? x1 : clip.x;
426         y1 = (y1 >= clip.y) ? y1 : clip.y;
427
428         x2 = (x2 <= clip.x + clip.w) ? x2 : clip.x + clip.w;
429         y2 = (y2 <= clip.y + clip.h) ? y2 : clip.y + clip.h;
430
431         if ((x2 - x1) > 0 && (y2 - y1) > 0)
432         {
433                 pScratchPad->FillRect(x1, y1, x2 - x1, y2 - y1, color);
434         }
435 }
436
437 template<typename Pixel>
438 void
439 _FillRectangleWithClip(Tizen::Graphics::_Util::ScratchPad<Pixel>* pScratchPad, Pixel color, const Tizen::Graphics::_Util::Rectangle<int>& rect, const Tizen::Graphics::_Util::Rectangle<int>& clip)
440 {
441         if (pScratchPad == null)
442         {
443                 return;
444         }
445
446         // alpha-fill-rect() applied
447         pScratchPad->RegisterFillRect(Tizen::Graphics::_RasterOp::FnFillRectAlpha32Bit);
448         _ClearRectangleWithClip(pScratchPad, color, rect, clip);
449         pScratchPad->RegisterFillRect(null);
450 }
451
452 }
453
454 namespace
455 {
456
457 typedef Tizen::Graphics::_Canvas::SystemPixel _SystemPixel;
458 typedef Tizen::Graphics::_Util::ScratchPad<_SystemPixel> _ScratchPad32;
459
460 static std::unique_ptr<_SystemPixel[]> _systemFontBuffer;
461 static std::auto_ptr<_ScratchPad32> _systemFont;
462
463 }
464
465 ////////////////////////////////////////////////////////////////////////////////
466 // Tizen::Graphics::_Canvas
467
468 namespace Tizen { namespace Graphics
469 {
470
471 bool _CanvasShowFromMemory(int xDest, int yDest, int xSour, int ySour, int wSour, int hSour, void* pMemory, int width, int height, int depth, int bytesPerLine);
472 void _FlushCanvas(void);
473
474 namespace
475 {
476
477 void
478 _ApplySrcBitmapAttrib(_Util::Pixmap& srcImage, const _Bitmap& bitmap, long isOpaque)
479 {
480         Color maskingColor;
481
482         if (bitmap.GetBitsPerPixel() == 16)
483         {
484                 if (bitmap.GetMaskingColor(maskingColor) == E_SUCCESS)
485                 {
486                         srcImage.enableColorKey = 1;
487                         srcImage.colorKey = _ConvertRGB888ToRGB565(maskingColor.GetRed(), maskingColor.GetGreen(), maskingColor.GetBlue());
488                 }
489         }
490
491         srcImage.isOpaque = isOpaque;
492         srcImage.isPremultiplied = bitmap.IsPremultiplied();
493 }
494
495 // retrieving bounds rectangle which has (0,0,w,h).
496 Rectangle
497 _GetBoundsRel(const _Canvas& canvas)
498 {
499         Rectangle rect = canvas.GetBounds();
500         rect.x = 0;
501         rect.y = 0;
502
503         return rect;
504 }
505 }
506
507 void
508 _FillRectangleWithClip32(_Util::ScratchPad<unsigned long>* pScratchPad, unsigned long color, const _Util::Rectangle<int>& rect, const _Util::Rectangle<int>& clip)
509 {
510         _FillRectangleWithClip(pScratchPad, color, rect, clip);
511 }
512
513 struct _NativeGfxEngine
514 {
515         cairo_t* pCairo;
516         cairo_surface_t* pCairoSurface;
517
518         _NativeGfxEngine()
519                 : pCairo(0)
520                 , pCairoSurface(0)
521         {
522         }
523         ~_NativeGfxEngine()
524         {
525                 if (pCairo)
526                 {
527                         cairo_destroy(pCairo);
528                 }
529
530                 if (pCairoSurface)
531                 {
532                         cairo_surface_destroy(pCairoSurface);
533                 }
534         }
535 };
536
537
538 _Canvas::_Canvas(void)
539         : _pNativeGfxEngine(static_cast<void*>(new (std::nothrow)_NativeGfxEngine))
540         , __pParent(0)
541         , __pFont(0)
542         , __pPriorityFont(0)
543         , __windowHandle(INVALID_HANDLE)
544         , __blendOption(Tizen::Graphics::_Canvas::BLEND_ALPHABLEND)
545         , __pSurface(0)
546         , __pScratchPad(0)
547         , __xBufferPos(0)
548         , __yBufferPos(0)
549         , __pBuffer(0)
550         , __fgColor(0xFFFFFFFF)
551         , __bgColor(0x00000000)
552         , __fgOpacity(255)
553         , __bgOpacity(255)
554         , __lineWidth(1)
555         , __lineStyle(LINE_STYLE_SOLID)
556         , __isClipBoundsSet(false)
557         , __textOrigin(TEXT_ORIGIN_LEFT_TOP)
558         , __applyEmoji(true)
559         , __bitmapDrawingQuality(BITMAP_DRAWING_QUALITY_LOW)
560         , __blendingMode(BLENDING_MODE_SRC_OVER)
561         , __useStableRenderer(true)
562 {
563         __fgColorNative = Color(__fgColor);
564         __bgColorNative = Color(__bgColor);
565
566         __dashData.offset = 0;
567
568         __ComposeFgColor();
569         __ComposeBgColor();
570 }
571
572 _Canvas::~_Canvas(void)
573 {
574         delete __pScratchPad;
575         delete __pSurface;
576
577         if (_pNativeGfxEngine)
578         {
579                 delete static_cast<_NativeGfxEngine*>(_pNativeGfxEngine);
580         }
581 }
582
583 result
584 _Canvas::Construct(void)
585 {
586         return this->Construct(Rectangle(0, 0, _Screen::GetWidth(), _Screen::GetHeight()));
587 }
588
589 result
590 _Canvas::Construct(const Rectangle& rect)
591 {
592         result r = E_SUCCESS;
593
594         _GenericBufferFrameBuffer<SystemPixel>* pTemp = new (std::nothrow) _GenericBufferFrameBuffer<SystemPixel>(rect.width, rect.height);
595
596         SysTryReturnResult(NID_GRP, pTemp, E_OUT_OF_MEMORY, " _GenericBufferFrameBuffer<> cannot be allocated.");
597
598         this->__pSurface = new (std::nothrow) _Util::GenericBuffer<SystemPixel>(pTemp);
599
600         SysTryCatch(NID_GRP, this->__pSurface, delete pTemp;
601                            r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] _Util::GenericBuffer<> cannot be allocated.");
602
603         this->__pBuffer = (unsigned long*) __pSurface->GetBufferAddr();
604         this->__pScratchPad = new (std::nothrow) _Util::ScratchPad<SystemPixel>(__pBuffer, rect.width, rect.height, rect.width);
605
606         SysTryCatch(NID_GRP, this->__pScratchPad, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] _Util::ScratchPad<> cannot be allocated.");
607
608         this->__pScratchPad->FillRect(0, 0, this->__pScratchPad->GetWidth(), this->__pScratchPad->GetHeight(), 0x00000000);
609
610         this->__xBufferPos = rect.x;
611         this->__yBufferPos = rect.y;
612
613 #if defined(USE_CAIRO)
614         {
615                 _NativeGfxEngine* pCairo = static_cast<_NativeGfxEngine*>(_pNativeGfxEngine);
616
617                 if (pCairo)
618                 {
619                         pCairo->pCairoSurface = cairo_image_surface_create_for_data((unsigned char*) this->__pBuffer, CAIRO_FORMAT_ARGB32, rect.width, rect.height, rect.width * 4);
620                         pCairo->pCairo = cairo_create(pCairo->pCairoSurface);
621                 }
622         }
623 #endif
624
625         __InitFgBgColorFromTheme();
626
627         return E_SUCCESS;
628
629 CATCH:
630         delete this->__pScratchPad;
631         this->__pScratchPad = null;
632
633         delete this->__pSurface;
634         this->__pSurface = null;
635
636         return r;
637 }
638
639 result
640 _Canvas::Construct(Handle windowHandle, const Rectangle& rect)
641 {
642         SysTryReturnResult(NID_GRP, rect.width >= 0 && rect.height >= 0, E_OUT_OF_RANGE, "The given rectangle(width:%d,height:%d) is out of range.\n", rect.width, rect.height);
643
644         result r = E_SUCCESS;
645
646         int x1 = rect.x;
647         int y1 = rect.y;
648         int x2 = x1 + rect.width;
649         int y2 = y1 + rect.height;
650
651         if (x1 < 0)
652         {
653                 x1 = 0;
654         }
655
656         if (y1 < 0)
657         {
658                 y1 = 0;
659         }
660
661         if (x2 > _GetWindowWidth(windowHandle))
662         {
663                 x2 = _GetWindowWidth(windowHandle);
664         }
665
666         if (y2 > _GetWindowHeight(windowHandle))
667         {
668                 y2 = _GetWindowHeight(windowHandle);
669         }
670
671         SysTryReturnResult(NID_GRP, (x2 - x1 >= 0) && (y2 - y1 >= 0), E_OUT_OF_RANGE, "The given rectangle(x1:%d,y1:%d,x2:%d,y2:%d) is out of range.", x1, y1, x2, y2);
672
673         int bufferWidth = x2 - x1;
674         int bufferHeight = y2 - y1;
675         int sourcePitch = 0;
676
677         _GenericBufferFrameBuffer<SystemPixel>* pTemp = new (std::nothrow) _GenericBufferFrameBuffer<SystemPixel>(windowHandle, x1, y1, bufferWidth, bufferHeight, 0);
678
679         SysTryReturnResult(NID_GRP, pTemp, E_OUT_OF_MEMORY, "_GenericBufferFrameBuffer<> cannot be allocated.");
680
681         this->__pSurface = new (std::nothrow) _Util::GenericBuffer<SystemPixel>(pTemp);
682
683         SysTryCatch(NID_GRP, this->__pSurface, delete pTemp;
684                            r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] _Util::GenericBuffer<> cannot be allocated.");
685
686         this->__pBuffer = (unsigned long*) __pSurface->GetBufferAddr();
687         sourcePitch = __pSurface->GetPitch();
688
689         this->__pScratchPad = new (std::nothrow) _Util::ScratchPad<SystemPixel>(__pBuffer, bufferWidth, bufferHeight, sourcePitch);
690
691         SysTryCatch(NID_GRP, this->__pScratchPad, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] _Util::ScratchPad<> cannot be allocated.");
692
693         this->__windowHandle = windowHandle;
694
695         this->__xBufferPos = x1;
696         this->__yBufferPos = y1;
697
698 #if defined(USE_CAIRO)
699         {
700                 _NativeGfxEngine* pCairo = static_cast<_NativeGfxEngine*>(_pNativeGfxEngine);
701
702                 if (pCairo)
703                 {
704                         pCairo->pCairoSurface = cairo_image_surface_create_for_data((unsigned char*) this->__pBuffer, CAIRO_FORMAT_ARGB32, bufferWidth, bufferHeight, sourcePitch * 4);
705                         pCairo->pCairo = cairo_create(pCairo->pCairoSurface);
706                 }
707         }
708 #endif
709
710         __InitFgBgColorFromTheme();
711
712         return E_SUCCESS;
713
714 CATCH:
715         delete this->__pScratchPad;
716         this->__pScratchPad = null;
717
718         delete this->__pSurface;
719         this->__pSurface = null;
720
721         return r;
722 }
723
724 result
725 _Canvas::Construct(_Canvas* pSourceCanvas, const Rectangle& subRegion)
726 {
727         SysTryReturnResult(NID_GRP, pSourceCanvas, E_INVALID_ARG, "The source canvas is invalid");
728
729         SysTryReturnResult(NID_GRP, pSourceCanvas->IsValid(), E_INVALID_ARG, "The source canvas is invalid");
730
731         result r = E_SUCCESS;
732
733         int x1 = subRegion.x;
734         int y1 = subRegion.y;
735         int x2 = x1 + subRegion.width;
736         int y2 = y1 + subRegion.height;
737
738         if (x1 < 0)
739         {
740                 x1 = 0;
741         }
742
743         if (y1 < 0)
744         {
745                 y1 = 0;
746         }
747
748         if (x2 > pSourceCanvas->GetBounds().width)
749         {
750                 x2 = pSourceCanvas->GetBounds().width;
751         }
752
753         if (y2 > pSourceCanvas->GetBounds().height)
754         {
755                 y2 = pSourceCanvas->GetBounds().height;
756         }
757
758         SysTryReturnResult(NID_GRP, (x2 - x1 > 0) && (y2 - y1 > 0), E_OUT_OF_RANGE, "The given rectangle(x1:%d,y1:%d,x2:%d,y2:%d) is out of range.", subRegion.x, subRegion.y, subRegion.width, subRegion.height);
759
760         int bufferWidth = x2 - x1;
761         int bufferHeight = y2 - y1;
762
763         int sourcePitch = pSourceCanvas->__pSurface->GetPitch();
764
765         if (pSourceCanvas->__windowHandle != INVALID_HANDLE)
766         {
767                 _GenericBufferFrameBuffer<SystemPixel>* pTemp = new (std::nothrow) _GenericBufferFrameBuffer<SystemPixel>(pSourceCanvas->__windowHandle, x1, y1, bufferWidth, bufferHeight, sourcePitch);
768
769                 SysTryReturnResult(NID_GRP, pTemp, E_OUT_OF_MEMORY, "_GenericBufferFrameBuffer<> cannot be allocated.");
770
771                 this->__pSurface = new (std::nothrow) _Util::GenericBuffer<SystemPixel>(pTemp);
772
773                 if (this->__pSurface == null)
774                 {
775                         delete pTemp;
776                         SysTryReturnResult(NID_GRP, false, E_OUT_OF_MEMORY, "_Util::GenericBuffer<> cannot be allocated.");
777                 }
778         }
779         else
780         {
781                 SystemPixel* pBuffer = pSourceCanvas->__pSurface->GetBufferAddr();
782                 pBuffer += y1 * sourcePitch + x1;
783
784                 _GenericBufferFrameBuffer<SystemPixel>* pTemp = new (std::nothrow) _GenericBufferFrameBuffer<SystemPixel>(pBuffer, bufferWidth, bufferHeight, sourcePitch);
785
786                 SysTryReturnResult(NID_GRP, pTemp, E_OUT_OF_MEMORY, "_GenericBufferFrameBuffer<> cannot be allocated.");
787
788                 this->__pSurface = new (std::nothrow) _Util::GenericBuffer<SystemPixel>(pTemp);
789
790                 if (this->__pSurface == null)
791                 {
792                         delete pTemp;
793                         SysTryReturnResult(NID_GRP, false, E_OUT_OF_MEMORY, "_Util::GenericBuffer<> cannot be allocated.");
794                 }
795         }
796
797         this->__pBuffer = (unsigned long*) __pSurface->GetBufferAddr();
798         this->__pScratchPad = new (std::nothrow) _Util::ScratchPad<SystemPixel>(__pBuffer, bufferWidth, bufferHeight, sourcePitch);
799
800         SysTryCatch(NID_GRP, this->__pScratchPad, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] _Util::ScratchPad<> cannot be allocated.");
801
802         this->__pParent = pSourceCanvas;
803         this->__xBufferPos = x1;
804         this->__yBufferPos = y1;
805
806         // duplicate
807         // must re-assign by _CanvasImpl::GetSubCanvasN()
808         this->__pFont = pSourceCanvas->__pFont;
809
810         this->__pPriorityFont = pSourceCanvas->__pPriorityFont;
811
812         // copy directly
813         this->__windowHandle = pSourceCanvas->__windowHandle;
814         this->__blendOption = pSourceCanvas->__blendOption;
815         this->__fgColor = pSourceCanvas->__fgColor;
816         this->__bgColor = pSourceCanvas->__bgColor;
817         this->__fgColorNative = pSourceCanvas->__fgColorNative;
818         this->__bgColorNative = pSourceCanvas->__bgColorNative;
819         this->__fgOpacity = pSourceCanvas->__fgOpacity;
820         this->__bgOpacity = pSourceCanvas->__bgOpacity;
821         this->__lineWidth = pSourceCanvas->__lineWidth;
822         this->__lineStyle = pSourceCanvas->__lineStyle;
823
824         // copy exception
825         this->__isClipBoundsSet = false;
826         this->__clipBounds = Rectangle(0, 0, bufferWidth, bufferHeight);
827
828 #if defined(USE_CAIRO)
829         {
830                 _NativeGfxEngine* pCairo = static_cast<_NativeGfxEngine*>(_pNativeGfxEngine);
831
832                 if (pCairo)
833                 {
834                         pCairo->pCairoSurface = cairo_image_surface_create_for_data((unsigned char*) this->__pBuffer, CAIRO_FORMAT_ARGB32, bufferWidth, bufferHeight, sourcePitch * 4);
835                         pCairo->pCairo = cairo_create(pCairo->pCairoSurface);
836                 }
837         }
838 #endif
839
840         return E_SUCCESS;
841
842 CATCH:
843         delete this->__pScratchPad;
844         this->__pScratchPad = null;
845
846         delete this->__pSurface;
847         this->__pSurface = null;
848
849         return r;
850 }
851
852 result
853 _Canvas::Construct(const BufferInfo& bufferInfo)
854 {
855         // all parameters checked
856
857         result r = E_SUCCESS;
858
859         _GenericBufferFrameBuffer<SystemPixel>* pTemp = new (std::nothrow) _GenericBufferFrameBuffer<SystemPixel>(static_cast<SystemPixel*>(bufferInfo.pPixels), bufferInfo.width, bufferInfo.height, bufferInfo.pitch * 8 / bufferInfo.bitsPerPixel);
860
861         SysTryReturnResult(NID_GRP
862                 , pTemp
863                 , E_OUT_OF_MEMORY
864                 , " _GenericBufferFrameBuffer<> cannot be allocated.");
865
866         this->__pSurface = new (std::nothrow) _Util::GenericBuffer<SystemPixel>(pTemp);
867
868         SysTryCatch(NID_GRP
869                 , this->__pSurface
870                 , delete pTemp; r = E_OUT_OF_MEMORY
871                 , E_OUT_OF_MEMORY
872                 , "[E_OUT_OF_MEMORY] _Util::GenericBuffer<> cannot be allocated.");
873
874         this->__pBuffer = (unsigned long*) __pSurface->GetBufferAddr();
875         this->__pScratchPad = new (std::nothrow) _Util::ScratchPad<SystemPixel>(__pBuffer, bufferInfo.width, bufferInfo.height, bufferInfo.pitch * 8 / bufferInfo.bitsPerPixel);
876
877         SysTryCatch(NID_GRP
878                 , this->__pScratchPad
879                 , r = E_OUT_OF_MEMORY
880                 , E_OUT_OF_MEMORY
881                 , "[E_OUT_OF_MEMORY] _Util::ScratchPad<> cannot be allocated.");
882
883         this->__xBufferPos = 0;
884         this->__yBufferPos = 0;
885
886 #if defined(USE_CAIRO)
887         {
888                 _NativeGfxEngine* pCairo = static_cast<_NativeGfxEngine*>(_pNativeGfxEngine);
889
890                 if (pCairo)
891                 {
892                         pCairo->pCairoSurface = cairo_image_surface_create_for_data((unsigned char*) this->__pBuffer, CAIRO_FORMAT_ARGB32, bufferInfo.width, bufferInfo.height, bufferInfo.pitch);
893                         pCairo->pCairo = cairo_create(pCairo->pCairoSurface);
894                 }
895         }
896 #endif
897
898         __InitFgBgColorFromTheme();
899
900         return E_SUCCESS;
901
902 CATCH:
903         delete this->__pScratchPad;
904         this->__pScratchPad = null;
905
906         delete this->__pSurface;
907         this->__pSurface = null;
908
909         return r;
910 }
911
912 bool
913 _Canvas::IsValid() const
914 {
915         return (this && this->__pSurface);
916 }
917
918 result
919 _Canvas::Clear(void)
920 {
921         if (this->__isClipBoundsSet)
922         {
923                 _Util::Rectangle<int> clip =
924                 {
925                         this->__clipBounds.x,
926                         this->__clipBounds.y,
927                         this->__clipBounds.width,
928                         this->__clipBounds.height
929                 };
930
931                 _Util::Rectangle<int> rect =
932                 {
933                         0,
934                         0,
935                         __pScratchPad->GetWidth(),
936                         __pScratchPad->GetHeight()
937                 };
938
939                 _ClearRectangleWithClip(__pScratchPad, __bgColor, rect, clip);
940         }
941         else
942         {
943                 __pScratchPad->FillRect(0, 0, __pScratchPad->GetWidth(), __pScratchPad->GetHeight(), __bgColor);
944         }
945
946         return E_SUCCESS;
947 }
948
949 result
950 _Canvas::Clear(const Rectangle& rect)
951 {
952         if ((rect.width == 0) || (rect.height == 0))
953         {
954                 return E_SUCCESS;
955         }
956
957         if (this->__isClipBoundsSet)
958         {
959                 _Util::Rectangle<int> clip =
960                 {
961                         this->__clipBounds.x,
962                         this->__clipBounds.y,
963                         this->__clipBounds.width,
964                         this->__clipBounds.height
965                 };
966
967                 _Util::Rectangle<int> rect1 =
968                 {
969                         rect.x,
970                         rect.y,
971                         rect.width,
972                         rect.height
973                 };
974
975                 _ClearRectangleWithClip(__pScratchPad, __bgColor, rect1, clip);
976         }
977         else
978         {
979                 __pScratchPad->FillRect(rect.x, rect.y, rect.width, rect.height, __bgColor);
980         }
981
982         return E_SUCCESS;
983 }
984
985 result
986 _Canvas::Copy(const Point& destPoint, const _Canvas& canvas, const Rectangle& srcRect)
987 {
988         // special case
989         if (srcRect.width == 0 || srcRect.height == 0)
990         {
991                 return E_SUCCESS;
992         }
993
994         return this->__Copy(destPoint, canvas, srcRect);
995 }
996
997 result
998 _Canvas::Copy(const Rectangle& destRect, const _Canvas& canvas, const Rectangle& srcRect)
999 {
1000         // special case
1001         if (srcRect.width == 0 || srcRect.height == 0 || destRect.width == 0 || destRect.height == 0)
1002         {
1003                 return E_SUCCESS;
1004         }
1005
1006         return this->__Copy(destRect, canvas, srcRect);
1007 }
1008
1009 result
1010 _Canvas::Copy(const Point& destPoint, const _Canvas& canvas, const Rectangle& srcRect, BlendingMode blendingMode)
1011 {
1012         _Util::LockManager srcLock(canvas);
1013         _Util::LockManager dstLock(*this);
1014
1015         SysTryReturnResult(NID_GRP, srcLock.IsValid(), E_OPERATION_FAILED, "The source canvas cannot be locked.");
1016         SysTryReturnResult(NID_GRP, dstLock.IsValid(), E_OPERATION_FAILED, "The canvas cannot be locked");
1017
1018         const BufferInfo& srcBufferInfo = srcLock.GetBufferInfo();
1019         const BufferInfo& dstBufferInfo = dstLock.GetBufferInfo();
1020
1021         {
1022                 _Util::Pixmap srcImageUnclipped(srcBufferInfo.width, srcBufferInfo.height, srcBufferInfo.bitsPerPixel, srcBufferInfo.pPixels, srcBufferInfo.pitch);
1023                 _Util::Pixmap srcImage = srcImageUnclipped.GetSubBitmap(srcRect.x, srcRect.y, srcRect.width, srcRect.height);
1024
1025                 _Util::Pixmap dstImageUnclipped(dstBufferInfo.width, dstBufferInfo.height, dstBufferInfo.bitsPerPixel, dstBufferInfo.pPixels, dstBufferInfo.pitch);
1026                 _Util::Pixmap dstImage = dstImageUnclipped.GetSubBitmap(destPoint.x, destPoint.y, srcRect.width, srcRect.height);
1027
1028                 _Pixman::CopyPixmap(dstImage, srcImage, GetDrawingQuality(), blendingMode);
1029         }
1030
1031         return E_SUCCESS;
1032 }
1033
1034 result
1035 _Canvas::CopyReverse(const Point& destPoint, const _Canvas& srcCanvas, const Rectangle& srcRect)
1036 {
1037         // special case
1038         if (srcRect.width == 0 || srcRect.height == 0)
1039         {
1040                 return E_SUCCESS;
1041         }
1042
1043         if (__pScratchPad == null)
1044         {
1045                 return E_SYSTEM;
1046         }
1047
1048         const _Canvas* pSrcCanvas = &srcCanvas;
1049
1050         if (pSrcCanvas == null)
1051         {
1052                 return E_SYSTEM;
1053         }
1054
1055         if (pSrcCanvas->__pScratchPad == null)
1056         {
1057                 return E_SYSTEM;
1058         }
1059
1060         Rectangle clippedSrcRect(srcRect);
1061
1062         if (_ClipRectangle(clippedSrcRect.x, clippedSrcRect.y, clippedSrcRect.width, clippedSrcRect.height, 0, 0, pSrcCanvas->__pScratchPad->GetWidth(), pSrcCanvas->__pScratchPad->GetHeight()) == CLIP_REJECT)
1063         {
1064                 return E_SYSTEM;
1065         }
1066
1067         __pScratchPad->RegisterBitBlt(_RasterOp::FnBitBlt32BitCopyReverse);
1068         __pScratchPad->BitBlt(destPoint.x, destPoint.y, pSrcCanvas->__pScratchPad, clippedSrcRect.x, clippedSrcRect.y, clippedSrcRect.width, clippedSrcRect.height);
1069         __pScratchPad->RegisterBitBlt(null);
1070
1071         return E_SUCCESS;
1072 }
1073
1074 namespace
1075 {
1076
1077 // spec. from SDK 1.0
1078
1079 template<typename T>
1080 void
1081 _ReviseAngle(T& startAngle, T& endAngle)
1082 {
1083         T zeroPi = T(0);
1084         T twoPi = T(360);
1085
1086         {
1087                 // startAngle = startAngle % twoPi;
1088                 int mod = int(startAngle / twoPi);
1089                 startAngle = startAngle - twoPi * mod;
1090
1091                 //endAngle = endAngle % twoPi;
1092                 mod = int(endAngle / twoPi);
1093                 endAngle = endAngle - twoPi * mod;
1094         }
1095
1096         if (startAngle < zeroPi || endAngle < zeroPi)
1097         {
1098                 startAngle += twoPi;
1099                 endAngle += twoPi;
1100         }
1101
1102         if (startAngle > endAngle)
1103         {
1104                 endAngle += twoPi;
1105         }
1106 }
1107
1108 }
1109
1110 result
1111 _Canvas::DrawArc(const _Util::Rectangle<double>& bounds, double startAngle, double endAngle, ArcStyle arcStyle)
1112 {
1113         if ((bounds.w <= 0.0) || (bounds.h <= 0.0))
1114         {
1115                 return E_SUCCESS;
1116         }
1117
1118         // this->__lineWidth is always greater than 0
1119
1120         unsigned long composedColor = _ComposeColor(this->__fgColor, this->__fgOpacity);
1121
1122         _NativeGfxEngine* pCairo = static_cast<_NativeGfxEngine*>(_pNativeGfxEngine);
1123
1124         if (pCairo && pCairo->pCairo)
1125         {
1126                 SET_CAIRO_DASH_STYLE;
1127                 SET_CAIRO_CLIPPING;
1128
1129                 double startDstAngle = (180.0 / M_PI) * atan2(sin(startAngle*M_PI / 180.0) * bounds.w / bounds.h, cos(startAngle * M_PI / 180.0));
1130                 double endDstAngle = (180.0 / M_PI) * atan2(sin(endAngle * M_PI / 180.0) * bounds.w / bounds.h, cos(endAngle * M_PI / 180.0));
1131
1132                 startDstAngle += (abs(startAngle - startDstAngle) <= 90.0) ? 0.0 : (startDstAngle < 0.0 && startAngle >= 0.0) ? 360.0 : (startDstAngle >= 0.0 && startAngle < 0.0) ? -360.0 : 0.0;
1133                 endDstAngle += (abs(endAngle - endDstAngle) <= 90.0) ? 0.0 : (endDstAngle < 0.0 && endAngle >= 0.0) ? 360.0 : (endDstAngle >= 0.0 && endAngle < 0.0) ? -360.0 : 0.0;
1134
1135                 _ReviseAngle(startDstAngle, endDstAngle);
1136
1137                 switch (arcStyle)
1138                 {
1139                 case ARC_STYLE_ONLY:
1140                         if (__lineWidth.applied != _Util::ScalarHolder::AS_INTEGER)
1141                         {
1142                                 _Cairo::DrawArc(pCairo->pCairo, this->__lineWidth.asDouble, composedColor, bounds, startDstAngle, endDstAngle, _Cairo::DRAW_ARC_STYLE_ARC);
1143                         }
1144                         else
1145                         {
1146                                 _Cairo::DrawArc(pCairo->pCairo, this->__lineWidth.asInteger, composedColor, bounds, startDstAngle, endDstAngle, _Cairo::DRAW_ARC_STYLE_ARC);
1147                         }
1148                         break;
1149
1150                 case ARC_STYLE_PIE:
1151                         if (__lineWidth.applied != _Util::ScalarHolder::AS_INTEGER)
1152                         {
1153                                 _Cairo::DrawArc(pCairo->pCairo, this->__lineWidth.asDouble, composedColor, bounds, startDstAngle, endDstAngle, _Cairo::DRAW_ARC_STYLE_PIE);
1154                         }
1155                         else
1156                         {
1157                                 _Cairo::DrawArc(pCairo->pCairo, this->__lineWidth.asInteger, composedColor, bounds, startDstAngle, endDstAngle, _Cairo::DRAW_ARC_STYLE_PIE);
1158                         }
1159                         break;
1160
1161                 case ARC_STYLE_CHORD:
1162                         if (__lineWidth.applied != _Util::ScalarHolder::AS_INTEGER)
1163                         {
1164                                 _Cairo::DrawArc(pCairo->pCairo, this->__lineWidth.asDouble, composedColor, bounds, startDstAngle, endDstAngle, _Cairo::DRAW_ARC_STYLE_CHORD);
1165                         }
1166                         else
1167                         {
1168                                 _Cairo::DrawArc(pCairo->pCairo, this->__lineWidth.asInteger, composedColor, bounds, startDstAngle, endDstAngle, _Cairo::DRAW_ARC_STYLE_CHORD);
1169                         }
1170                         break;
1171
1172                 case ARC_STYLE_FILLED_PIE:
1173                         _Cairo::FillArc(pCairo->pCairo, composedColor, bounds, startDstAngle, endDstAngle, _Cairo::FILL_ARC_STYLE_PIE);
1174                         break;
1175
1176                 case ARC_STYLE_FILLED_CHORD:
1177                         _Cairo::FillArc(pCairo->pCairo, composedColor, bounds, startDstAngle, endDstAngle, _Cairo::FILL_ARC_STYLE_CHORD);
1178                         break;
1179
1180                 default:
1181                         return E_SYSTEM;
1182                 }
1183
1184                 RESET_CAIRO_CLIPPING;
1185                 RESET_CAIRO_DASH_STYLE;
1186
1187                 return E_SUCCESS;
1188         }
1189         else
1190         {
1191                 _CanvasArc arc;
1192                 _GpBufferInfo info;
1193
1194                 memset(&info, 0, sizeof(info));
1195
1196                 SystemPixel* pBufferAddr = null;
1197                 int bufferPitch = 0;
1198
1199                 __pScratchPad->GetBuffer(pBufferAddr, bufferPitch);
1200
1201                 info.width = __pScratchPad->GetWidth();
1202                 info.height = __pScratchPad->GetHeight();
1203                 info.bitsPerPixel = 32;
1204                 info.pixelPerLine = bufferPitch;
1205                 info.pPixels = (void*) pBufferAddr;
1206                 info.color32 = composedColor;
1207                 info.isClipBoundsSet = this->__isClipBoundsSet;
1208                 info.clipBounds.SetBounds(this->__clipBounds.x, this->__clipBounds.y, this->__clipBounds.width, this->__clipBounds.height);
1209
1210                 arc.SetLineWidth(this->__lineWidth.asInteger);
1211
1212                 _ReviseAngle(startAngle, endAngle);
1213
1214                 return arc.DrawArc(int(bounds.x), int(bounds.y), int(bounds.w), int(bounds.h), int(startAngle), int(endAngle), arcStyle, info);
1215         }
1216 }
1217
1218 result
1219 _Canvas::DrawBitmap(const Rectangle& rect, const _Bitmap& bitmap)
1220 {
1221         SysTryReturnResult(NID_GRP, &bitmap && bitmap.IsValid(), E_INVALID_ARG, "The source bitmap is invalid.\n");
1222
1223         if (rect.width <= 0 || rect.height <= 0)
1224         {
1225                 return E_SUCCESS;
1226         }
1227
1228         int alphaConstant = this->_GetAlphaAttenuation(bitmap);
1229
1230         Rectangle clipRect;
1231
1232         this->__GetClipBounds(clipRect);
1233
1234         if (alphaConstant >= 255)
1235         {
1236                 bool pass = false;
1237
1238                 _Util::LockManager srcLock(bitmap);
1239                 _Util::LockManager dstLock(*this);
1240
1241                 SysTryReturnResult(NID_GRP, srcLock.IsValid(), E_OPERATION_FAILED, "The source bitmap cannot be locked.\n");
1242                 SysTryReturnResult(NID_GRP, dstLock.IsValid(), E_OPERATION_FAILED, "The canvas cannot be locked.\n");
1243
1244                 const BufferInfo& srcBufferInfo = srcLock.GetBufferInfo();
1245                 const BufferInfo& dstBufferInfo = dstLock.GetBufferInfo();
1246
1247                 {
1248                         if (!this->__useStableRenderer && srcBufferInfo.bitsPerPixel == 32)
1249                         {
1250                                 _Util::Rectangle<int> outRect = { 0, 0, -1, -1 };
1251                                 _Util::Rectangle<int> dstRect = { rect.x, rect.y, rect.width, rect.height };
1252                                 _Util::Rectangle<int> tgtRect = { clipRect.x, clipRect.y, clipRect.width, clipRect.height };
1253
1254                                 _Util::IntersectRect(outRect, tgtRect, dstRect);
1255
1256                                 // assert(rect.width > 0 && rect.height > 0);
1257
1258                                 _Util::Bounds<int> outBounds = { outRect.x, outRect.y, outRect.x + outRect.w, outRect.y + outRect.h };
1259                                 _Util::Bounds<int> dstBounds = { dstRect.x, dstRect.y, dstRect.x + dstRect.w, dstRect.y + dstRect.h };
1260                                 _Util::Bounds<int> srcBounds =
1261                                 {
1262                                         (outBounds.x1 - dstBounds.x1) * srcBufferInfo.width / (dstBounds.x2 - dstBounds.x1),
1263                                         (outBounds.y1 - dstBounds.y1) * srcBufferInfo.height / (dstBounds.y2 - dstBounds.y1),
1264                                         srcBufferInfo.width + (outBounds.x2 - dstBounds.x2) * srcBufferInfo.width / (dstBounds.x2 - dstBounds.x1),
1265                                         srcBufferInfo.height + (outBounds.y2 - dstBounds.y2) * srcBufferInfo.height / (dstBounds.y2 - dstBounds.y1),
1266                                 };
1267
1268                                 srcBounds.x1 = (srcBounds.x1 >= 0) ? srcBounds.x1 : 0;
1269                                 srcBounds.y1 = (srcBounds.y1 >= 0) ? srcBounds.y1 : 0;
1270                                 srcBounds.x2 = (srcBounds.x2 <= srcBufferInfo.width) ? srcBounds.x2 : srcBufferInfo.width;
1271                                 srcBounds.y2 = (srcBounds.y2 <= srcBufferInfo.height) ? srcBounds.y2 : srcBufferInfo.height;
1272
1273                                 _Util::Pixmap srcImageUnclipped(srcBufferInfo.width, srcBufferInfo.height, srcBufferInfo.bitsPerPixel, srcBufferInfo.pPixels, srcBufferInfo.pitch);
1274                                 _Util::Pixmap srcImage = srcImageUnclipped.GetSubBitmap(srcBounds.x1, srcBounds.y1, srcBounds.x2 - srcBounds.x1, srcBounds.y2 - srcBounds.y1);
1275                                 _ApplySrcBitmapAttrib(srcImage, bitmap, bitmap.__isOpaqueAllOver);
1276
1277                                 _Util::Pixmap dstImageUnclipped(dstBufferInfo.width, dstBufferInfo.height, dstBufferInfo.bitsPerPixel, dstBufferInfo.pPixels, dstBufferInfo.pitch);
1278                                 _Util::Pixmap dstImage = dstImageUnclipped.GetSubBitmap(outRect.x, outRect.y, outRect.w, outRect.h);
1279
1280                                 pass = _Pixman::ScalePixmap(dstImage, srcImage, GetDrawingQuality());
1281                         }
1282
1283                         if (!pass)
1284                         {
1285                                 _Util::Pixmap srcImage(srcBufferInfo.width, srcBufferInfo.height, srcBufferInfo.bitsPerPixel, srcBufferInfo.pPixels, srcBufferInfo.pitch);
1286                                 _ApplySrcBitmapAttrib(srcImage, bitmap, bitmap.__isOpaqueAllOver);
1287
1288                                 _Util::Pixmap dstImageUnclipped(dstBufferInfo.width, dstBufferInfo.height, dstBufferInfo.bitsPerPixel, dstBufferInfo.pPixels, dstBufferInfo.pitch);
1289                                 _Util::Pixmap dstImage = dstImageUnclipped.GetSubBitmap(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
1290
1291                                 pass = Tizen::Graphics::_Effect::ScaleImage(dstImage, rect.x - clipRect.x, rect.y - clipRect.y, rect.width, rect.height, srcImage, _ConvertParam<_Effect::Rop>(this->__blendOption));
1292                         }
1293
1294                 }
1295
1296                 SysTryReturnResult(NID_GRP, pass, E_INVALID_ARG, "The source bitmap is invalid.\n");
1297
1298                 return E_SUCCESS;
1299         }
1300         else
1301         {
1302                 _Util::Pixmap tmpImage(rect.width, rect.height, bitmap.GetBitsPerPixel());
1303
1304                 // copies the source bitmap to the scaled bitmap
1305                 {
1306                         // ykahn, 2011/10/11 patched
1307                         {
1308                                 _ApplySrcBitmapAttrib(tmpImage, bitmap, bitmap.__isOpaqueAllOver);
1309
1310                                 if (tmpImage.depth == 16)
1311                                 {
1312                                         if (tmpImage.enableColorKey)
1313                                         {
1314                                                 typedef unsigned short Pixel;
1315
1316                                                 Pixel colorKey = (Pixel) tmpImage.colorKey;
1317                                                 Pixel* pDest = (Pixel*) tmpImage.pBitmap;
1318                                                 Pixel* pDestEnd = pDest + (tmpImage.bytesPerLine * tmpImage.height / (tmpImage.depth / 8));
1319
1320                                                 while (pDest < pDestEnd)
1321                                                 {
1322                                                         *pDest++ = colorKey;
1323                                                 }
1324                                         }
1325                                         else
1326                                         {
1327                                                 ;
1328                                         }
1329                                 }
1330                                 else if (tmpImage.depth == 32)
1331                                 {
1332                                         typedef unsigned long Pixel;
1333
1334                                         Pixel fillColor = 0;
1335                                         Pixel* pDest = (Pixel*) tmpImage.pBitmap;
1336                                         Pixel* pDestEnd = pDest + (tmpImage.bytesPerLine * tmpImage.height / (tmpImage.depth / 8));
1337
1338                                         while (pDest < pDestEnd)
1339                                         {
1340                                                 *pDest++ = fillColor;
1341                                         }
1342                                 }
1343                         }
1344
1345                         bool pass = false;
1346
1347                         {
1348                                 _Util::LockManager srcLock(bitmap);
1349                                 SysTryReturnResult(NID_GRP, srcLock.IsValid(), E_OPERATION_FAILED, "The source bitmap cannot be locked.\n");
1350
1351                                 const BufferInfo& srcBufferInfo = srcLock.GetBufferInfo();
1352
1353                                 {
1354                                         _Util::Pixmap srcImage(srcBufferInfo.width, srcBufferInfo.height, srcBufferInfo.bitsPerPixel, srcBufferInfo.pPixels, srcBufferInfo.pitch);
1355                                         _ApplySrcBitmapAttrib(srcImage, bitmap, bitmap.__isOpaqueAllOver);
1356
1357                                         pass = Tizen::Graphics::_Effect::ScaleImage(tmpImage, 0, 0, rect.width, rect.height, srcImage, Tizen::Graphics::_Effect::ROP_COPY);
1358                                 }
1359                         }
1360
1361                         SysTryReturnResult(NID_GRP, pass, E_INVALID_ARG, "The source bitmap is invalid.\n");
1362                 }
1363
1364                 {
1365                         bool pass = false;
1366
1367                         {
1368                                 _Util::LockManager dstLock(*this);
1369                                 SysTryReturnResult(NID_GRP, dstLock.IsValid(), E_OPERATION_FAILED, "The canvas cannot be locked.\n");
1370
1371                                 const BufferInfo& dstBufferInfo = dstLock.GetBufferInfo();
1372
1373                                 {
1374                                         _Util::Pixmap dstImageUnclipped(dstBufferInfo.width, dstBufferInfo.height, dstBufferInfo.bitsPerPixel, dstBufferInfo.pPixels, dstBufferInfo.pitch);
1375                                         _Util::Pixmap dstImage = dstImageUnclipped.GetSubBitmap(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
1376
1377                                         pass = Tizen::Graphics::_Effect::DrawImageWithAlpha(dstImage, rect.x - clipRect.x, rect.y - clipRect.y, tmpImage, alphaConstant);
1378                                 }
1379                         }
1380
1381                         SysTryReturnResult(NID_GRP, pass, E_INVALID_ARG, "The source bitmap is invalid.\n");
1382                 }
1383
1384                 return E_SUCCESS;
1385         }
1386 }
1387
1388
1389 result
1390 _Canvas::DrawBitmap(const Point& point, const _Bitmap& bitmap)
1391 {
1392         SysTryReturnResult(NID_GRP, &bitmap && bitmap.IsValid(), E_INVALID_ARG, "The source bitmap is invalid.\n");
1393
1394         int alphaConstant = this->_GetAlphaAttenuation(bitmap);
1395
1396         {
1397                 Rectangle clipRect;
1398
1399                 this->__GetClipBounds(clipRect);
1400
1401                 bool pass = false;
1402
1403                 {
1404                         _Util::LockManager srcLock(bitmap);
1405                         _Util::LockManager dstLock(*this);
1406
1407                         SysTryReturnResult(NID_GRP, srcLock.IsValid(), E_OPERATION_FAILED, "The source bitmap cannot be locked.\n");
1408                         SysTryReturnResult(NID_GRP, dstLock.IsValid(), E_OPERATION_FAILED, "The canvas cannot be locked.\n");
1409
1410                         const BufferInfo& srcBufferInfo = srcLock.GetBufferInfo();
1411                         const BufferInfo& dstBufferInfo = dstLock.GetBufferInfo();
1412
1413                         {
1414                                 _Util::Pixmap srcImage(srcBufferInfo.width, srcBufferInfo.height, srcBufferInfo.bitsPerPixel, srcBufferInfo.pPixels, srcBufferInfo.pitch);
1415                                 _ApplySrcBitmapAttrib(srcImage, bitmap, bitmap.__isOpaqueAllOver);
1416
1417                                 _Util::Pixmap dstImageUnclipped(dstBufferInfo.width, dstBufferInfo.height, dstBufferInfo.bitsPerPixel, dstBufferInfo.pPixels, dstBufferInfo.pitch);
1418                                 _Util::Pixmap dstImage = dstImageUnclipped.GetSubBitmap(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
1419
1420                                 if (srcBufferInfo.pixelFormat == PIXEL_FORMAT_RGB565 && srcImage.enableColorKey == 0 && dstBufferInfo.pixelFormat == PIXEL_FORMAT_ARGB8888 && !this->__isClipBoundsSet)
1421                                 {
1422                                         pixman_image_t* pPixmanSrc = pixman_image_create_bits(PIXMAN_r5g6b5, srcBufferInfo.width, srcBufferInfo.height, (uint32_t*)srcBufferInfo.pPixels, srcBufferInfo.pitch);
1423                                         pixman_image_t* pPixmanDst = pixman_image_create_bits(PIXMAN_a8r8g8b8, dstBufferInfo.width, dstBufferInfo.height, (uint32_t*)dstBufferInfo.pPixels, dstBufferInfo.pitch);
1424
1425                                         if (pPixmanSrc && pPixmanDst)
1426                                         {
1427                                                 pixman_image_composite32(PIXMAN_OP_SRC, pPixmanSrc, NULL, pPixmanDst, 0, 0, 0, 0, point.x, point.y, srcBufferInfo.width, srcBufferInfo.height);
1428                                                 pass = true;
1429                                         }
1430
1431                                         if (pPixmanDst)
1432                                         {
1433                                                 pixman_image_unref(pPixmanDst);
1434                                         }
1435
1436                                         if (pPixmanSrc)
1437                                         {
1438                                                 pixman_image_unref(pPixmanSrc);
1439                                         }
1440                                 }
1441                         }
1442                         {
1443                                 Color color;
1444                                 bool isPixmanSupported = !this->__useStableRenderer && bitmap.GetMaskingColor(color ) != E_SUCCESS && alphaConstant >= 255;
1445                                 if (isPixmanSupported)
1446                                 {
1447                                         _Util::Rectangle<int> outRect = { 0, 0, -1, -1 };
1448                                         _Util::Rectangle<int> dstRect = { point.x, point.y, srcBufferInfo.width, srcBufferInfo.height };
1449                                         _Util::Rectangle<int> tgtRect = { clipRect.x, clipRect.y, clipRect.width, clipRect.height };
1450
1451                                         if (_Util::IntersectRect(outRect, tgtRect, dstRect))
1452                                         {
1453                                                 // assert(rect.width > 0 && rect.height > 0);
1454
1455                                                 _Util::Bounds<int> outBounds = { outRect.x, outRect.y, outRect.x + outRect.w, outRect.y + outRect.h };
1456                                                 _Util::Bounds<int> dstBounds = { dstRect.x, dstRect.y, dstRect.x + dstRect.w, dstRect.y + dstRect.h };
1457                                                 _Util::Bounds<int> srcBounds =
1458                                                 {
1459                                                         (outBounds.x1 - dstBounds.x1),
1460                                                         (outBounds.y1 - dstBounds.y1),
1461                                                         srcBufferInfo.width + (outBounds.x2 - dstBounds.x2),
1462                                                         srcBufferInfo.height + (outBounds.y2 - dstBounds.y2),
1463                                                 };
1464
1465                                                 srcBounds.x1 = (srcBounds.x1 >= 0) ? srcBounds.x1 : 0;
1466                                                 srcBounds.y1 = (srcBounds.y1 >= 0) ? srcBounds.y1 : 0;
1467                                                 srcBounds.x2 = (srcBounds.x2 <= srcBufferInfo.width) ? srcBounds.x2 : srcBufferInfo.width;
1468                                                 srcBounds.y2 = (srcBounds.y2 <= srcBufferInfo.height) ? srcBounds.y2 : srcBufferInfo.height;
1469
1470                                                 _Util::Pixmap srcImageUnclipped(srcBufferInfo.width, srcBufferInfo.height, srcBufferInfo.bitsPerPixel, srcBufferInfo.pPixels, srcBufferInfo.pitch);
1471                                                 _Util::Pixmap srcImage = srcImageUnclipped.GetSubBitmap(srcBounds.x1, srcBounds.y1, srcBounds.x2 - srcBounds.x1, srcBounds.y2 - srcBounds.y1);
1472                                                 _ApplySrcBitmapAttrib(srcImage, bitmap, bitmap.__isOpaqueAllOver);
1473
1474                                                 _Util::Pixmap dstImageUnclipped(dstBufferInfo.width, dstBufferInfo.height, dstBufferInfo.bitsPerPixel, dstBufferInfo.pPixels, dstBufferInfo.pitch);
1475                                                 _Util::Pixmap dstImage = dstImageUnclipped.GetSubBitmap(outRect.x, outRect.y, outRect.w, outRect.h);
1476
1477                                                 pass = _Pixman::CopyPixmap(dstImage, srcImage, GetDrawingQuality(), BLENDING_MODE_SRC_OVER);
1478                                         }
1479                                 }
1480
1481                                 if (!pass)
1482                                 {
1483                                         _Util::Pixmap srcImage(srcBufferInfo.width, srcBufferInfo.height, srcBufferInfo.bitsPerPixel, srcBufferInfo.pPixels, srcBufferInfo.pitch);
1484                                         _ApplySrcBitmapAttrib(srcImage, bitmap, bitmap.__isOpaqueAllOver);
1485
1486                                         _Util::Pixmap dstImageUnclipped(dstBufferInfo.width, dstBufferInfo.height, dstBufferInfo.bitsPerPixel, dstBufferInfo.pPixels, dstBufferInfo.pitch);
1487                                         _Util::Pixmap dstImage = dstImageUnclipped.GetSubBitmap(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
1488
1489                                         pass = Tizen::Graphics::_Effect::DrawImageWithAlpha(dstImage, point.x - clipRect.x, point.y - clipRect.y, srcImage, alphaConstant);
1490                                 }
1491                         }
1492                 }
1493
1494                 SysTryReturnResult(NID_GRP, pass, E_INVALID_ARG, "The source bitmap is invalid.\n");
1495
1496                 return E_SUCCESS;
1497         }
1498 }
1499
1500 result
1501 _Canvas::DrawBitmap(const Rectangle& destRect, const _Bitmap& srcBitmap, const Rectangle& srcRect)
1502 {
1503         SysTryReturnResult(NID_GRP, &srcBitmap && srcBitmap.IsValid(), E_INVALID_ARG, "The source bitmap is invalid.\n");
1504
1505         if (srcRect.width == 0 || srcRect.height == 0)
1506         {
1507                 return E_SUCCESS;
1508         }
1509
1510         if (destRect.width == 0 || destRect.height == 0)
1511         {
1512                 return E_SUCCESS;
1513         }
1514
1515         int alphaConstant = this->_GetAlphaAttenuation(srcBitmap);
1516
1517         Rectangle clipRect;
1518
1519         this->__GetClipBounds(clipRect);
1520
1521         if (alphaConstant >= 255)
1522         {
1523                 bool pass = false;
1524
1525                 _Util::LockManager srcLock(srcBitmap);
1526                 _Util::LockManager dstLock(*this);
1527
1528                 SysTryReturnResult(NID_GRP, srcLock.IsValid(), E_OPERATION_FAILED, "The source bitmap cannot be locked.\n");
1529                 SysTryReturnResult(NID_GRP, dstLock.IsValid(), E_OPERATION_FAILED, "The canvas cannot be locked.\n");
1530
1531                 const BufferInfo& srcBufferInfo = srcLock.GetBufferInfo();
1532                 const BufferInfo& dstBufferInfo = dstLock.GetBufferInfo();
1533
1534                 {
1535                         if (!this->__useStableRenderer && srcBufferInfo.bitsPerPixel == 32)
1536                         {
1537                                 _Util::Rectangle<int> outRect = { 0, 0, -1, -1 };
1538                                 _Util::Rectangle<int> dstRect = { destRect.x, destRect.y, destRect.width, destRect.height };
1539                                 _Util::Rectangle<int> tgtRect = { clipRect.x, clipRect.y, clipRect.width, clipRect.height };
1540
1541                                 _Util::IntersectRect(outRect, tgtRect, dstRect);
1542
1543                                 // assert(destRect.width > 0 && destRect.height > 0);
1544
1545                                 _Util::Bounds<int> outBounds = { outRect.x, outRect.y, outRect.x + outRect.w, outRect.y + outRect.h };
1546                                 _Util::Bounds<int> dstBounds = { dstRect.x, dstRect.y, dstRect.x + dstRect.w, dstRect.y + dstRect.h };
1547                                 _Util::Bounds<int> srcBounds =
1548                                 {
1549                                         srcRect.x + (outBounds.x1 - dstBounds.x1) * srcRect.width / (dstBounds.x2 - dstBounds.x1),
1550                                         srcRect.y + (outBounds.y1 - dstBounds.y1) * srcRect.height / (dstBounds.y2 - dstBounds.y1),
1551                                         (srcRect.x + srcRect.width) + (outBounds.x2 - dstBounds.x2) * srcRect.width / (dstBounds.x2 - dstBounds.x1),
1552                                         (srcRect.y + srcRect.height) + (outBounds.y2 - dstBounds.y2) * srcRect.height / (dstBounds.y2 - dstBounds.y1),
1553                                 };
1554
1555                                 srcBounds.x1 = (srcBounds.x1 >= srcRect.x) ? srcBounds.x1 : srcRect.x;
1556                                 srcBounds.y1 = (srcBounds.y1 >= srcRect.y) ? srcBounds.y1 : srcRect.y;
1557                                 srcBounds.x2 = (srcBounds.x2 <= (srcRect.x + srcRect.width)) ? srcBounds.x2 : (srcRect.x + srcRect.width);
1558                                 srcBounds.y2 = (srcBounds.y2 <= (srcRect.y + srcRect.height)) ? srcBounds.y2 : (srcRect.y + srcRect.height);
1559
1560                                 _Util::Pixmap srcImageUnclipped(srcBufferInfo.width, srcBufferInfo.height, srcBufferInfo.bitsPerPixel, srcBufferInfo.pPixels, srcBufferInfo.pitch);
1561                                 _Util::Pixmap srcImage = srcImageUnclipped.GetSubBitmap(srcBounds.x1, srcBounds.y1, srcBounds.x2 - srcBounds.x1, srcBounds.y2 - srcBounds.y1);
1562                                 _ApplySrcBitmapAttrib(srcImage, srcBitmap, srcBitmap.__isOpaqueAllOver);
1563
1564                                 _Util::Pixmap dstImageUnclipped(dstBufferInfo.width, dstBufferInfo.height, dstBufferInfo.bitsPerPixel, dstBufferInfo.pPixels, dstBufferInfo.pitch);
1565                                 _Util::Pixmap dstImage = dstImageUnclipped.GetSubBitmap(outRect.x, outRect.y, outRect.w, outRect.h);
1566
1567                                 pass = _Pixman::ScalePixmap(dstImage, srcImage, GetDrawingQuality());
1568                         }
1569
1570                         if (!pass)
1571                         {
1572                                 unsigned char* pPixels = (unsigned char*) srcBufferInfo.pPixels + srcRect.y * srcBufferInfo.pitch + srcRect.x * (srcBufferInfo.bitsPerPixel / 8);
1573
1574                                 _Util::Pixmap srcImage(srcRect.width, srcRect.height, srcBufferInfo.bitsPerPixel, (void*) pPixels, srcBufferInfo.pitch);
1575                                 _ApplySrcBitmapAttrib(srcImage, srcBitmap, srcBitmap.__isOpaqueAllOver);
1576
1577                                 _Util::Pixmap dstImageUnclipped(dstBufferInfo.width, dstBufferInfo.height, dstBufferInfo.bitsPerPixel, dstBufferInfo.pPixels, dstBufferInfo.pitch);
1578                                 _Util::Pixmap dstImage = dstImageUnclipped.GetSubBitmap(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
1579
1580                                 pass = Tizen::Graphics::_Effect::ScaleImage(dstImage, destRect.x - clipRect.x, destRect.y - clipRect.y, destRect.width, destRect.height, srcImage, _ConvertParam<_Effect::Rop>(this->__blendOption));
1581                         }
1582
1583                 }
1584
1585                 SysTryReturnResult(NID_GRP, pass, E_INVALID_ARG, "The source bitmap is invalid.\n");
1586
1587                 return E_SUCCESS;
1588         }
1589         else
1590         {
1591                 _Util::Pixmap tmpImage(destRect.width, destRect.height, srcBitmap.GetBitsPerPixel());
1592
1593                 // copies the source bitmap to the scaled bitmap
1594                 {
1595                         // ykahn, 2011/10/11 patched
1596                         {
1597                                 _ApplySrcBitmapAttrib(tmpImage, srcBitmap, srcBitmap.__isOpaqueAllOver);
1598
1599                                 if (tmpImage.depth == 16)
1600                                 {
1601                                         if (tmpImage.enableColorKey)
1602                                         {
1603                                                 typedef unsigned short Pixel;
1604
1605                                                 Pixel colorKey = (Pixel) tmpImage.colorKey;
1606                                                 Pixel* pDest = (Pixel*) tmpImage.pBitmap;
1607                                                 Pixel* pDestEnd = pDest + (tmpImage.bytesPerLine * tmpImage.height / (tmpImage.depth / 8));
1608
1609                                                 while (pDest < pDestEnd)
1610                                                 {
1611                                                         *pDest++ = colorKey;
1612                                                 }
1613                                         }
1614                                         else
1615                                         {
1616                                         }
1617                                 }
1618                                 else if (tmpImage.depth == 32)
1619                                 {
1620                                         typedef unsigned long Pixel;
1621
1622                                         Pixel fillColor = 0;
1623                                         Pixel* pDest = (Pixel*) tmpImage.pBitmap;
1624                                         Pixel* pDestEnd = pDest + (tmpImage.bytesPerLine * tmpImage.height / (tmpImage.depth / 8));
1625
1626                                         while (pDest < pDestEnd)
1627                                         {
1628                                                 *pDest++ = fillColor;
1629                                         }
1630                                 }
1631                         }
1632
1633                         bool pass = false;
1634
1635                         {
1636                                 _Util::LockManager srcLock(srcBitmap);
1637                                 SysTryReturnResult(NID_GRP, srcLock.IsValid(), E_OPERATION_FAILED, "The source bitmap cannot be locked.\n");
1638
1639                                 const BufferInfo& srcBufferInfo = srcLock.GetBufferInfo();
1640
1641                                 {
1642                                         unsigned char* pPixels = (unsigned char*) srcBufferInfo.pPixels + srcRect.y * srcBufferInfo.pitch + srcRect.x * (srcBufferInfo.bitsPerPixel / 8);
1643
1644                                         _Util::Pixmap srcImage(srcRect.width, srcRect.height, srcBufferInfo.bitsPerPixel, (void*) pPixels, srcBufferInfo.pitch);
1645                                         _ApplySrcBitmapAttrib(srcImage, srcBitmap, srcBitmap.__isOpaqueAllOver);
1646
1647                                         pass = Tizen::Graphics::_Effect::ScaleImage(tmpImage, 0, 0, destRect.width, destRect.height, srcImage, Tizen::Graphics::_Effect::ROP_COPY);
1648                                 }
1649                         }
1650
1651                         SysTryReturnResult(NID_GRP, pass, E_INVALID_ARG, "The source bitmap is invalid.\n");
1652                 }
1653
1654                 {
1655                         bool pass = false;
1656
1657                         {
1658                                 _Util::LockManager dstLock(*this);
1659                                 SysTryReturnResult(NID_GRP, dstLock.IsValid(), E_OPERATION_FAILED, "The canvas cannot be locked.\n");
1660
1661                                 const BufferInfo& dstBufferInfo = dstLock.GetBufferInfo();
1662
1663                                 {
1664                                         _Util::Pixmap dstImageUnclipped(dstBufferInfo.width, dstBufferInfo.height, dstBufferInfo.bitsPerPixel, dstBufferInfo.pPixels, dstBufferInfo.pitch);
1665                                         _Util::Pixmap dstImage = dstImageUnclipped.GetSubBitmap(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
1666
1667                                         pass = Tizen::Graphics::_Effect::DrawImageWithAlpha(dstImage, destRect.x - clipRect.x, destRect.y - clipRect.y, tmpImage, alphaConstant);
1668                                 }
1669                         }
1670
1671                         SysTryReturnResult(NID_GRP, pass, E_INVALID_ARG, "The source bitmap is invalid.\n");
1672                 }
1673
1674                 return E_SUCCESS;
1675         }
1676 }
1677
1678 result
1679 _Canvas::DrawBitmapForNinePatchedBitmap(const Rectangle& destRect, const _Bitmap& srcBitmap, const Rectangle& srcRect)
1680 {
1681         SysTryReturnResult(NID_GRP, &srcBitmap && srcBitmap.IsValid(), E_INVALID_ARG, "The source bitmap is invalid.\n");
1682
1683         if (srcRect.width == 0 || srcRect.height == 0)
1684         {
1685                 return E_SUCCESS;
1686         }
1687
1688         if (destRect.width == 0 || destRect.height == 0)
1689         {
1690                 return E_SUCCESS;
1691         }
1692
1693         int alphaConstant = this->_GetAlphaAttenuation(srcBitmap);
1694
1695         Rectangle clipRect;
1696
1697         this->__GetClipBounds(clipRect);
1698
1699         if (alphaConstant >= 255)
1700         {
1701                 bool pass = false;
1702
1703                 _Util::LockManager srcLock(srcBitmap);
1704                 _Util::LockManager dstLock(*this);
1705
1706                 SysTryReturnResult(NID_GRP, srcLock.IsValid(), E_OPERATION_FAILED, "The source bitmap cannot be locked.\n");
1707                 SysTryReturnResult(NID_GRP, dstLock.IsValid(), E_OPERATION_FAILED, "The canvas cannot be locked.\n");
1708
1709                 const BufferInfo& srcBufferInfo = srcLock.GetBufferInfo();
1710                 const BufferInfo& dstBufferInfo = dstLock.GetBufferInfo();
1711
1712                 {
1713                         if (srcBufferInfo.bitsPerPixel == 32)
1714                         {
1715                                 _Util::Rectangle<int> outRect = { 0, 0, -1, -1 };
1716                                 _Util::Rectangle<int> dstRect = { destRect.x, destRect.y, destRect.width, destRect.height };
1717                                 _Util::Rectangle<int> tgtRect = { clipRect.x, clipRect.y, clipRect.width, clipRect.height };
1718
1719                                 _Util::IntersectRect(outRect, tgtRect, dstRect);
1720
1721                                 // assert(destRect.width > 0 && destRect.height > 0);
1722
1723                                 _Util::Bounds<int> outBounds = { outRect.x, outRect.y, outRect.x + outRect.w, outRect.y + outRect.h };
1724                                 _Util::Bounds<int> dstBounds = { dstRect.x, dstRect.y, dstRect.x + dstRect.w, dstRect.y + dstRect.h };
1725                                 _Util::Bounds<int> srcBounds =
1726                                 {
1727                                         srcRect.x + (outBounds.x1 - dstBounds.x1) * srcRect.width / (dstBounds.x2 - dstBounds.x1),
1728                                         srcRect.y + (outBounds.y1 - dstBounds.y1) * srcRect.height / (dstBounds.y2 - dstBounds.y1),
1729                                         (srcRect.x + srcRect.width) + (outBounds.x2 - dstBounds.x2) * srcRect.width / (dstBounds.x2 - dstBounds.x1),
1730                                         (srcRect.y + srcRect.height) + (outBounds.y2 - dstBounds.y2) * srcRect.height / (dstBounds.y2 - dstBounds.y1),
1731                                 };
1732
1733                                 srcBounds.x1 = (srcBounds.x1 >= srcRect.x) ? srcBounds.x1 : srcRect.x;
1734                                 srcBounds.y1 = (srcBounds.y1 >= srcRect.y) ? srcBounds.y1 : srcRect.y;
1735                                 srcBounds.x2 = (srcBounds.x2 <= (srcRect.x + srcRect.width)) ? srcBounds.x2 : (srcRect.x + srcRect.width);
1736                                 srcBounds.y2 = (srcBounds.y2 <= (srcRect.y + srcRect.height)) ? srcBounds.y2 : (srcRect.y + srcRect.height);
1737
1738                                 _Util::Pixmap srcImageUnclipped(srcBufferInfo.width, srcBufferInfo.height, srcBufferInfo.bitsPerPixel, srcBufferInfo.pPixels, srcBufferInfo.pitch);
1739                                 _Util::Pixmap srcImage = srcImageUnclipped.GetSubBitmap(srcBounds.x1, srcBounds.y1, srcBounds.x2 - srcBounds.x1, srcBounds.y2 - srcBounds.y1);
1740                                 _ApplySrcBitmapAttrib(srcImage, srcBitmap, srcBitmap.__isOpaqueAllOver);
1741
1742                                 _Util::Pixmap dstImageUnclipped(dstBufferInfo.width, dstBufferInfo.height, dstBufferInfo.bitsPerPixel, dstBufferInfo.pPixels, dstBufferInfo.pitch);
1743                                 _Util::Pixmap dstImage = dstImageUnclipped.GetSubBitmap(outRect.x, outRect.y, outRect.w, outRect.h);
1744
1745                                 pass = _Pixman::ScalePixmap(dstImage, srcImage, GetDrawingQuality(), GetBlendingMode());
1746                         }
1747
1748                         if (!pass)
1749                         {
1750                                 unsigned char* pPixels = (unsigned char*) srcBufferInfo.pPixels + srcRect.y * srcBufferInfo.pitch + srcRect.x * (srcBufferInfo.bitsPerPixel / 8);
1751
1752                                 _Util::Pixmap srcImage(srcRect.width, srcRect.height, srcBufferInfo.bitsPerPixel, (void*) pPixels, srcBufferInfo.pitch);
1753                                 _ApplySrcBitmapAttrib(srcImage, srcBitmap, srcBitmap.__isOpaqueAllOver);
1754
1755                                 _Util::Pixmap dstImageUnclipped(dstBufferInfo.width, dstBufferInfo.height, dstBufferInfo.bitsPerPixel, dstBufferInfo.pPixels, dstBufferInfo.pitch);
1756                                 _Util::Pixmap dstImage = dstImageUnclipped.GetSubBitmap(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
1757
1758                                 pass = Tizen::Graphics::_Effect::ScaleImage(dstImage, destRect.x - clipRect.x, destRect.y - clipRect.y, destRect.width, destRect.height, srcImage, _ConvertParam<_Effect::Rop>(this->__blendOption));
1759                         }
1760
1761                 }
1762
1763                 SysTryReturnResult(NID_GRP, pass, E_INVALID_ARG, "The source bitmap is invalid.\n");
1764
1765                 return E_SUCCESS;
1766         }
1767         else
1768         {
1769                 _Util::Pixmap tmpImage(destRect.width, destRect.height, srcBitmap.GetBitsPerPixel());
1770
1771                 // copies the source bitmap to the scaled bitmap
1772                 {
1773                         // ykahn, 2011/10/11 patched
1774                         {
1775                                 _ApplySrcBitmapAttrib(tmpImage, srcBitmap, srcBitmap.__isOpaqueAllOver);
1776
1777                                 if (tmpImage.depth == 16)
1778                                 {
1779                                         if (tmpImage.enableColorKey)
1780                                         {
1781                                                 typedef unsigned short Pixel;
1782
1783                                                 Pixel colorKey = (Pixel) tmpImage.colorKey;
1784                                                 Pixel* pDest = (Pixel*) tmpImage.pBitmap;
1785                                                 Pixel* pDestEnd = pDest + (tmpImage.bytesPerLine * tmpImage.height / (tmpImage.depth / 8));
1786
1787                                                 while (pDest < pDestEnd)
1788                                                 {
1789                                                         *pDest++ = colorKey;
1790                                                 }
1791                                         }
1792                                         else
1793                                         {
1794                                         }
1795                                 }
1796                                 else if (tmpImage.depth == 32)
1797                                 {
1798                                         typedef unsigned long Pixel;
1799
1800                                         Pixel fillColor = 0;
1801                                         Pixel* pDest = (Pixel*) tmpImage.pBitmap;
1802                                         Pixel* pDestEnd = pDest + (tmpImage.bytesPerLine * tmpImage.height / (tmpImage.depth / 8));
1803
1804                                         while (pDest < pDestEnd)
1805                                         {
1806                                                 *pDest++ = fillColor;
1807                                         }
1808                                 }
1809                         }
1810
1811                         bool pass = false;
1812
1813                         {
1814                                 _Util::LockManager srcLock(srcBitmap);
1815                                 SysTryReturnResult(NID_GRP, srcLock.IsValid(), E_OPERATION_FAILED, "The source bitmap cannot be locked.\n");
1816
1817                                 const BufferInfo& srcBufferInfo = srcLock.GetBufferInfo();
1818
1819                                 {
1820                                         unsigned char* pPixels = (unsigned char*) srcBufferInfo.pPixels + srcRect.y * srcBufferInfo.pitch + srcRect.x * (srcBufferInfo.bitsPerPixel / 8);
1821
1822                                         _Util::Pixmap srcImage(srcRect.width, srcRect.height, srcBufferInfo.bitsPerPixel, (void*) pPixels, srcBufferInfo.pitch);
1823                                         _ApplySrcBitmapAttrib(srcImage, srcBitmap, srcBitmap.__isOpaqueAllOver);
1824
1825                                         pass = Tizen::Graphics::_Effect::ScaleImage(tmpImage, 0, 0, destRect.width, destRect.height, srcImage, Tizen::Graphics::_Effect::ROP_COPY);
1826                                 }
1827                         }
1828
1829                         SysTryReturnResult(NID_GRP, pass, E_INVALID_ARG, "The source bitmap is invalid.\n");
1830                 }
1831
1832                 {
1833                         bool pass = false;
1834
1835                         {
1836                                 _Util::LockManager dstLock(*this);
1837                                 SysTryReturnResult(NID_GRP, dstLock.IsValid(), E_OPERATION_FAILED, "The canvas cannot be locked.\n");
1838
1839                                 const BufferInfo& dstBufferInfo = dstLock.GetBufferInfo();
1840
1841                                 {
1842                                         _Util::Pixmap dstImageUnclipped(dstBufferInfo.width, dstBufferInfo.height, dstBufferInfo.bitsPerPixel, dstBufferInfo.pPixels, dstBufferInfo.pitch);
1843                                         _Util::Pixmap dstImage = dstImageUnclipped.GetSubBitmap(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
1844
1845                                         pass = Tizen::Graphics::_Effect::DrawImageWithAlpha(dstImage, destRect.x - clipRect.x, destRect.y - clipRect.y, tmpImage, alphaConstant);
1846                                 }
1847                         }
1848
1849                         SysTryReturnResult(NID_GRP, pass, E_INVALID_ARG, "The source bitmap is invalid.\n");
1850                 }
1851
1852                 return E_SUCCESS;
1853         }
1854 }
1855
1856 result
1857 _Canvas::DrawBitmap(const Point& point, const _Bitmap& bitmap, FlipDirection dir)
1858 {
1859         SysTryReturnResult(NID_GRP, &bitmap && bitmap.IsValid(), E_INVALID_ARG, "The source bitmap is invalid.\n");
1860
1861         int alphaConstant = this->_GetAlphaAttenuation(bitmap);
1862
1863         Rectangle clipRect;
1864
1865         this->__GetClipBounds(clipRect);
1866
1867         {
1868                 _Util::Pixmap* pFlippedImage = 0;
1869
1870                 {
1871                         _Util::LockManager srcLock(bitmap);
1872                         SysTryReturnResult(NID_GRP, srcLock.IsValid(), E_OPERATION_FAILED, "The source bitmap cannot be locked.\n");
1873
1874                         const BufferInfo& srcBufferInfo = srcLock.GetBufferInfo();
1875
1876                         Tizen::Graphics::_Effect::Flip flip = (dir == FLIP_DIRECTION_HORIZONTAL) ? Tizen::Graphics::_Effect::FLIP_HORIZONTAL : Tizen::Graphics::_Effect::FLIP_VERTICAL;
1877
1878                         {
1879                                 _Util::Pixmap srcImage(srcBufferInfo.width, srcBufferInfo.height, srcBufferInfo.bitsPerPixel, srcBufferInfo.pPixels, srcBufferInfo.pitch);
1880
1881                                 pFlippedImage = Tizen::Graphics::_Effect::GetFlippedImage(srcImage, flip);
1882                         }
1883                 }
1884
1885                 SysTryReturnResult(NID_GRP, pFlippedImage, E_INVALID_ARG, "The source bitmap is invalid.\n");
1886
1887                 _ApplySrcBitmapAttrib(*pFlippedImage, bitmap, bitmap.__isOpaqueAllOver);
1888
1889                 std::auto_ptr<_Util::Pixmap> autoReleasingImage(pFlippedImage);
1890
1891                 {
1892                         bool pass = false;
1893
1894                         {
1895                                 _Util::LockManager dstLock(*this);
1896                                 SysTryReturnResult(NID_GRP, dstLock.IsValid(), E_OPERATION_FAILED, "The canvas cannot be locked.\n");
1897
1898                                 const BufferInfo& dstBufferInfo = dstLock.GetBufferInfo();
1899
1900                                 {
1901                                         _Util::Pixmap dstImageUnclipped(dstBufferInfo.width, dstBufferInfo.height, dstBufferInfo.bitsPerPixel, dstBufferInfo.pPixels, dstBufferInfo.pitch);
1902                                         _Util::Pixmap dstImage = dstImageUnclipped.GetSubBitmap(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
1903
1904                                         pass = Tizen::Graphics::_Effect::DrawImageWithAlpha(dstImage, point.x - clipRect.x, point.y - clipRect.y, *pFlippedImage, alphaConstant);
1905                                 }
1906                         }
1907
1908                         SysTryReturnResult(NID_GRP, pass, E_INVALID_ARG, "The source bitmap is invalid.\n");
1909                 }
1910
1911                 return E_SUCCESS;
1912         }
1913 }
1914
1915 result
1916 _Canvas::DrawBitmap(const Point& point, const _Bitmap& bitmap, const Point& pivot, int degree)
1917 {
1918         SysTryReturnResult(NID_GRP, &bitmap && bitmap.IsValid(), E_INVALID_ARG, "The source bitmap is invalid.\n");
1919
1920         Rectangle clipRect;
1921
1922         this->__GetClipBounds(clipRect);
1923
1924         int alphaConstant = this->_GetAlphaAttenuation(bitmap);
1925
1926         if (alphaConstant >= 255 && !bitmap.__hasMaskingColor)
1927         {
1928                 bool pass = false;
1929
1930                 _Util::LockManager srcLock(bitmap);
1931                 _Util::LockManager dstLock(*this);
1932
1933                 SysTryReturnResult(NID_GRP, srcLock.IsValid(), E_OPERATION_FAILED, "The source bitmap cannot be locked.");
1934                 SysTryReturnResult(NID_GRP, dstLock.IsValid(), E_OPERATION_FAILED, "The canvas cannot be locked.");
1935
1936                 const BufferInfo& srcBufferInfo = srcLock.GetBufferInfo();
1937                 const BufferInfo& dstBufferInfo = dstLock.GetBufferInfo();
1938
1939                 if (!this->__useStableRenderer)
1940                 {
1941                         _Util::Pixmap srcImage(srcBufferInfo.width, srcBufferInfo.height, srcBufferInfo.bitsPerPixel, srcBufferInfo.pPixels, srcBufferInfo.pitch);
1942                         _ApplySrcBitmapAttrib(srcImage, bitmap, bitmap.__isOpaqueAllOver);
1943
1944                         _Util::Pixmap dstImageUnclipped(dstBufferInfo.width, dstBufferInfo.height, dstBufferInfo.bitsPerPixel, dstBufferInfo.pPixels, dstBufferInfo.pitch);
1945                         _Util::Pixmap dstImage = dstImageUnclipped.GetSubBitmap(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
1946
1947                         pass = _Pixman::RotatePixmap(dstImage, srcImage, GetDrawingQuality(), point.x - clipRect.x, point.y - clipRect.y, double(degree), pivot.x, pivot.y);
1948                 }
1949
1950                 if (pass)
1951                 {
1952                         return E_SUCCESS;
1953                 }
1954         }
1955
1956 /*
1957     if (alphaConstant >= 255)
1958     {
1959         return pCanvasInterface->DrawBitmap(point.x, point.y, *((IBitmapPi*)*(IBitmapPi**)bitmap.__pImpl), pivot.x, pivot.y, degree);
1960     }
1961     else
1962 */
1963         {
1964                 _Util::LockManager srcLock(bitmap);
1965                 _Util::LockManager dstLock(*this);
1966
1967                 SysTryReturnResult(NID_GRP, srcLock.IsValid(), E_OPERATION_FAILED, "The source bitmap cannot be locked.\n");
1968                 SysTryReturnResult(NID_GRP, dstLock.IsValid(), E_OPERATION_FAILED, "The canvas cannot be locked.\n");
1969
1970                 const BufferInfo& srcBufferInfo = srcLock.GetBufferInfo();
1971                 const BufferInfo& dstBufferInfo = dstLock.GetBufferInfo();
1972
1973                 _Util::Pixmap srcImage(srcBufferInfo.width, srcBufferInfo.height, srcBufferInfo.bitsPerPixel, srcBufferInfo.pPixels, srcBufferInfo.pitch);
1974                 _Util::Pixmap dstImageUnclipped(dstBufferInfo.width, dstBufferInfo.height, dstBufferInfo.bitsPerPixel, dstBufferInfo.pPixels, dstBufferInfo.pitch);
1975                 _Util::Pixmap dstImage = dstImageUnclipped.GetSubBitmap(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
1976
1977                 _ApplySrcBitmapAttrib(srcImage, bitmap, bitmap.__isOpaqueAllOver);
1978
1979                 // angle, xOffset, yOffset
1980                 Tizen::Graphics::_Effect::RotateDesc rotateDesc = { degree, pivot.x, pivot.y };
1981                 bool pass = Tizen::Graphics::_Effect::RotateImage(dstImage, point.x - clipRect.x, point.y - clipRect.y, srcImage, rotateDesc, alphaConstant);
1982
1983                 SysTryReturnResult(NID_GRP, pass, E_INVALID_ARG, "The source bitmap is invalid.\n");
1984
1985                 return E_SUCCESS;
1986         }
1987 }
1988
1989 result
1990 _Canvas::DrawNinePatchedBitmap(const Rectangle& rect, const _Bitmap& bitmap)
1991 {
1992         SysTryReturnResult(NID_GRP, &bitmap && bitmap.IsValid(), E_INVALID_ARG, "The source bitmap is invalid.\n");
1993
1994         // down-scales the source bitmap
1995         if (rect.width < bitmap.GetWidth() - 2 || rect.height < bitmap.GetHeight() - 2)
1996         {
1997 #if 1
1998                 int dstW = rect.width;
1999                 int dstH = rect.height;
2000                 int srcW = bitmap.GetWidth() - 2;
2001                 int srcH = bitmap.GetHeight() - 2;
2002
2003                 if (dstW <= 0 || dstH <= 0)
2004                 {
2005                         return E_SUCCESS;
2006                 }
2007
2008                 if (dstW * srcH < dstH * srcW)
2009                 {
2010                         // fit to width
2011                         dstW = srcW;
2012                         dstH = dstH * srcW / dstW;
2013                 }
2014                 else
2015                 {
2016                         // fit to height
2017                         dstW = dstW * srcH / dstH;
2018                         dstH = srcH;
2019                 }
2020
2021                 result r;
2022
2023                 {
2024                         const int PADDING = 1;
2025
2026                         _Bitmap expandedBitmap;
2027
2028                         r = expandedBitmap.Construct(Dimension(dstW + PADDING * 2, dstH + PADDING * 2), BITMAP_PIXEL_FORMAT_ARGB8888);
2029
2030                         SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
2031
2032                         _Util::LockManager dstBitmap(expandedBitmap);
2033
2034                         {
2035                                 const BufferInfo& dstBufferInfo = dstBitmap.GetBufferInfo();
2036
2037                                 memset(dstBufferInfo.pPixels, 0, dstBufferInfo.pitch * dstBufferInfo.height);
2038
2039                                 _Canvas expandedCanvas;
2040
2041                                 r = expandedCanvas.Construct(dstBufferInfo);
2042
2043                                 SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
2044
2045                                 expandedCanvas.SetDrawingQuality(BITMAP_DRAWING_QUALITY_HIGH);
2046                                 expandedCanvas.SetBlendingMode(BLENDING_MODE_SRC);
2047
2048                                 _Util::Pixmap dstImage(dstBufferInfo.width, dstBufferInfo.height, dstBufferInfo.bitsPerPixel, (void*) dstBufferInfo.pPixels, dstBufferInfo.pitch);
2049
2050                                 _Util::AccumList<_Util::Pair<_Util::Rectangle<int>, _Util::Rectangle<int> > > boundsList;
2051
2052                                 r = _Util::GetPatchList(boundsList, Rectangle(PADDING, PADDING, dstBufferInfo.width - PADDING * 2, dstBufferInfo.height - PADDING * 2), bitmap);
2053
2054                                 SysTryReturn(NID_GRP, r == E_SUCCESS, null, E_SYSTEM, "[E_SYSTEM] _Util::GetPatchList() failed (error = %#x)", r);
2055
2056                                 _Util::AccumList<_Util::Pair<_Util::Rectangle<int>, _Util::Rectangle<int> > >::Iterator iter = boundsList.Begin();
2057
2058                                 int alphaConstant = bitmap.GetAlphaConstant();
2059                                 const_cast<_Bitmap*>(&bitmap)->SetAlphaConstant(255);
2060
2061                                 while (iter != boundsList.End())
2062                                 {
2063                                         Rectangle destRect(iter->first.x, iter->first.y, iter->first.w, iter->first.h);
2064                                         Rectangle sourRect(iter->second.x, iter->second.y, iter->second.w, iter->second.h);
2065
2066                                         expandedCanvas.DrawBitmapForNinePatchedBitmap(destRect, bitmap, sourRect);
2067
2068                                         ++iter;
2069                                 }
2070
2071                                 const_cast<_Bitmap*>(&bitmap)->SetAlphaConstant(alphaConstant);
2072                                 expandedBitmap.SetAlphaConstant(alphaConstant);
2073                         }
2074
2075                         // not <- PADDING * 2>
2076                         Tizen::Graphics::Rectangle srcRect(PADDING, PADDING, expandedBitmap.GetWidth() - PADDING, expandedBitmap.GetHeight() - PADDING);
2077
2078                         return this->DrawBitmap(rect, expandedBitmap, srcRect);
2079                 }
2080
2081 #else // old spec.
2082                 Tizen::Graphics::Rectangle srcRect(1, 1, bitmap.GetWidth() - 2, bitmap.GetHeight() - 2);
2083
2084                 return this->DrawBitmap(rect, bitmap, srcRect);
2085 #endif
2086         }
2087
2088         _Util::AccumList<_Util::Pair<_Util::Rectangle<int>, _Util::Rectangle<int> > > boundsList;
2089
2090         result r = _Util::GetPatchList(boundsList, rect, bitmap);
2091
2092         if (r == E_SUCCESS)
2093         {
2094                 _Util::AccumList<_Util::Pair<_Util::Rectangle<int>, _Util::Rectangle<int> > >::Iterator iter = boundsList.Begin();
2095
2096                 while (iter != boundsList.End())
2097                 {
2098                         Rectangle destRect(iter->first.x, iter->first.y, iter->first.w, iter->first.h);
2099                         Rectangle sourRect(iter->second.x, iter->second.y, iter->second.w, iter->second.h);
2100
2101                         DrawBitmapForNinePatchedBitmap(destRect, bitmap, sourRect);
2102
2103                         ++iter;
2104                 }
2105         }
2106
2107         return r;
2108 }
2109
2110 result
2111 _Canvas::DrawEllipse(const _Util::Rectangle<int>& bounds)
2112 {
2113         _Util::Rectangle<double> doubleBounds =
2114         {
2115                 double(bounds.x),
2116                 double(bounds.y),
2117                 double(bounds.w),
2118                 double(bounds.h)
2119         };
2120
2121         return this->DrawEllipse(doubleBounds);
2122 }
2123
2124 result
2125 _Canvas::DrawEllipse(const _Util::Rectangle<double>& bounds)
2126 {
2127         if ((bounds.w <= 0.0) || (bounds.h <= 0.0))
2128         {
2129                 return E_SUCCESS;
2130         }
2131
2132         // this->__lineWidth is always greater than 0
2133
2134         unsigned long composedColor = _ComposeColor(this->__fgColor, this->__fgOpacity);
2135
2136         _NativeGfxEngine* pCairo = static_cast<_NativeGfxEngine*>(_pNativeGfxEngine);
2137
2138         int x1 = this->GetBounds().x;
2139         int y1 = this->GetBounds().y;
2140         int x2 = x1 + this->GetBounds().width;
2141         int y2 = y1 + this->GetBounds().height;
2142
2143         if (this->__isClipBoundsSet)
2144         {
2145                 x1 = (this->__clipBounds.x > x1) ? this->__clipBounds.x : x1;
2146                 y1 = (this->__clipBounds.y > y1) ? this->__clipBounds.y : y1;
2147                 x2 = (this->__clipBounds.x + this->__clipBounds.width < x2) ? this->__clipBounds.x + this->__clipBounds.width : x2;
2148                 y2 = (this->__clipBounds.y + this->__clipBounds.height < y2) ? this->__clipBounds.y + this->__clipBounds.height : y2;
2149         }
2150
2151         bool shouldWorkaround = ((bounds.x < x1) || (bounds.y < y1) || (bounds.x + bounds.w > x2) || (bounds.y + bounds.h > y2)) && (__dashData.pattern.Size() == 0);
2152
2153         if (!shouldWorkaround && pCairo && pCairo->pCairo)
2154         {
2155                 SET_CAIRO_DASH_STYLE;
2156                 SET_CAIRO_CLIPPING;
2157
2158                 if (__lineWidth.applied != _Util::ScalarHolder::AS_INTEGER)
2159                 {
2160                         _Cairo::DrawEllipse(pCairo->pCairo, this->__lineWidth.asDouble, composedColor, bounds);
2161                 }
2162                 else
2163                 {
2164                         _Cairo::DrawEllipse(pCairo->pCairo, this->__lineWidth.asInteger, composedColor, bounds);
2165                 }
2166
2167                 RESET_CAIRO_CLIPPING;
2168                 RESET_CAIRO_DASH_STYLE;
2169
2170                 return E_SUCCESS;
2171         }
2172         else
2173         {
2174                 _CanvasEllipse ellipse;
2175                 _GpBufferInfo info;
2176
2177                 memset(&info, 0, sizeof(info));
2178
2179                 SystemPixel* pBufferAddr = null;
2180                 int bufferPitch = 0;
2181
2182                 __pScratchPad->GetBuffer(pBufferAddr, bufferPitch);
2183
2184                 info.width = __pScratchPad->GetWidth();
2185                 info.height = __pScratchPad->GetHeight();
2186                 info.bitsPerPixel = 32;
2187                 info.pixelPerLine = bufferPitch;
2188                 info.pPixels = (void*) pBufferAddr;
2189                 info.color32 = composedColor;
2190                 info.isClipBoundsSet = this->__isClipBoundsSet;
2191                 info.clipBounds.SetBounds(this->__clipBounds.x, this->__clipBounds.y, this->__clipBounds.width, this->__clipBounds.height);
2192
2193                 ellipse.SetLineWidth(this->__lineWidth.asInteger);
2194
2195                 return ellipse.DrawEllipse(int(bounds.x), int(bounds.y), int(bounds.w), int(bounds.h), info);
2196         }
2197 }
2198
2199 result
2200 _Canvas::DrawLine(const _Util::Point<int>& point1, const _Util::Point<int>& point2)
2201 {
2202         _Util::Point<double> doublePoint1 =
2203         {
2204                 double(point1.x),
2205                 double(point1.y)
2206         };
2207
2208         _Util::Point<double> doublePoint2 =
2209         {
2210                 double(point2.x),
2211                 double(point2.y)
2212         };
2213
2214         return this->DrawLine(doublePoint1, doublePoint2);
2215 }
2216
2217 result
2218 _Canvas::DrawLine(const _Util::Point<double>& point1, const _Util::Point<double>& point2)
2219 {
2220         // this->__lineWidth is always greater than 0
2221
2222         unsigned long composedColor = _ComposeColor(this->__fgColor, this->__fgOpacity);
2223
2224         _NativeGfxEngine* pCairo = static_cast<_NativeGfxEngine*>(_pNativeGfxEngine);
2225
2226         if (pCairo && pCairo->pCairo)
2227         {
2228                 _Util::Point<double> point[] =
2229                 {
2230                         { point1.x, point1.y },
2231                         { point2.x, point2.y }
2232                 };
2233
2234                 SET_CAIRO_DASH_STYLE;
2235                 SET_CAIRO_CLIPPING;
2236
2237                 if (__lineWidth.applied != _Util::ScalarHolder::AS_INTEGER)
2238                 {
2239                         _Cairo::Drawline(pCairo->pCairo, this->__lineWidth.asDouble, composedColor, point, 2);
2240                 }
2241                 else
2242                 {
2243                         _Cairo::Drawline(pCairo->pCairo, this->__lineWidth.asInteger, composedColor, point, 2);
2244                 }
2245
2246                 RESET_CAIRO_CLIPPING;
2247                 RESET_CAIRO_DASH_STYLE;
2248
2249                 return E_SUCCESS;
2250         }
2251         else
2252         {
2253                 _CanvasLine line;
2254                 _GpBufferInfo info;
2255
2256                 _GpPoint startPt =
2257                 {
2258                         int(point1.x),
2259                         int(point1.y)
2260                 };
2261
2262                 _GpPoint endPt =
2263                 {
2264                         int(point2.x),
2265                         int(point2.y)
2266                 };
2267
2268                 memset(&info, 0, sizeof(info));
2269
2270                 SystemPixel* pBufferAddr = null;
2271                 int bufferPitch = 0;
2272
2273                 __pScratchPad->GetBuffer(pBufferAddr, bufferPitch);
2274
2275                 info.width = __pScratchPad->GetWidth();
2276                 info.height = __pScratchPad->GetHeight();
2277                 info.bitsPerPixel = 32;
2278                 info.pixelPerLine = bufferPitch;
2279                 info.pPixels = (void*) pBufferAddr;
2280                 info.color32 = composedColor;
2281                 info.isClipBoundsSet = this->__isClipBoundsSet;
2282                 info.clipBounds.SetBounds(this->__clipBounds.x, this->__clipBounds.y, this->__clipBounds.width, this->__clipBounds.height);
2283
2284                 line.SetLineWidth(this->__lineWidth.asInteger);
2285
2286                 if (this->__lineWidth.asInteger == 1)
2287                 {
2288                         if ((startPt.x == endPt.x) && (startPt.y == endPt.y))
2289                         {
2290                                 this->SetPixel(point1);
2291                                 return E_SUCCESS;
2292                         }
2293                 }
2294
2295                 return line.DrawLine(startPt, endPt, info);
2296         }
2297 }
2298
2299 result
2300 _Canvas::DrawPolygon(const _Util::Point<double>* pPoints, unsigned int pointCount)
2301 {
2302         // this->__lineWidth is always greater than 0
2303
2304         if (pointCount == 1)
2305         {
2306                 return this->SetPixel(pPoints[0]);
2307         }
2308
2309         unsigned long composedColor = _ComposeColor(this->__fgColor, this->__fgOpacity);
2310
2311         _NativeGfxEngine* pCairo = static_cast<_NativeGfxEngine*>(_pNativeGfxEngine);
2312
2313         if (pCairo && pCairo->pCairo)
2314         {
2315                 SET_CAIRO_DASH_STYLE;
2316                 SET_CAIRO_CLIPPING;
2317
2318                 _Cairo::DrawPolygon(pCairo->pCairo, this->__lineWidth.asInteger, composedColor, pPoints, pointCount);
2319
2320                 RESET_CAIRO_CLIPPING;
2321                 RESET_CAIRO_DASH_STYLE;
2322
2323                 return E_SUCCESS;
2324         }
2325         else
2326         {
2327                 std::unique_ptr<_GpPoint[]> tempPoints(new (std::nothrow) _GpPoint[pointCount]);
2328
2329                 _GpPoint* pTempPoints = tempPoints.get();
2330
2331                 if (pTempPoints == null)
2332                 {
2333                         return E_SYSTEM;
2334                 }
2335
2336                 for (unsigned int i = 0; i < pointCount; i++)
2337                 {
2338                         pTempPoints[i].x = int(pPoints[i].x);
2339                         pTempPoints[i].y = int(pPoints[i].y);
2340                 }
2341
2342                 _CanvasLine line;
2343                 _GpBufferInfo info;
2344
2345                 memset(&info, 0, sizeof(info));
2346
2347                 SystemPixel* pBufferAddr = null;
2348                 int bufferPitch = 0;
2349
2350                 __pScratchPad->GetBuffer(pBufferAddr, bufferPitch);
2351
2352                 info.width = __pScratchPad->GetWidth();
2353                 info.height = __pScratchPad->GetHeight();
2354                 info.bitsPerPixel = 32;
2355                 info.pixelPerLine = bufferPitch;
2356                 info.pPixels = (void*) pBufferAddr;
2357                 info.color32 = composedColor;
2358                 info.isClipBoundsSet = this->__isClipBoundsSet;
2359                 info.clipBounds.SetBounds(this->__clipBounds.x, this->__clipBounds.y, this->__clipBounds.width, this->__clipBounds.height);
2360
2361                 line.SetLineWidth(this->__lineWidth.asInteger);
2362
2363                 result r = line.DrawPolygon(int(pointCount), pTempPoints, info);
2364
2365                 return r;
2366         }
2367 }
2368
2369 result
2370 _Canvas::DrawPolyline(const _Util::Point<double>* pPoints, unsigned int pointCount)
2371 {
2372         // this->__lineWidth is always greater than 0
2373
2374         if (pointCount == 1)
2375         {
2376                 return this->SetPixel(pPoints[0]);
2377         }
2378
2379         unsigned long composedColor = _ComposeColor(this->__fgColor, this->__fgOpacity);
2380
2381         _NativeGfxEngine* pCairo = static_cast<_NativeGfxEngine*>(_pNativeGfxEngine);
2382
2383         if (pCairo && pCairo->pCairo)
2384         {
2385                 SET_CAIRO_DASH_STYLE;
2386                 SET_CAIRO_CLIPPING;
2387
2388                 if (__lineWidth.applied != _Util::ScalarHolder::AS_INTEGER)
2389                 {
2390                         _Cairo::DrawPolyline(pCairo->pCairo, this->__lineWidth.asDouble, composedColor, pPoints, pointCount);
2391                 }
2392                 else
2393                 {
2394                         _Cairo::DrawPolyline(pCairo->pCairo, this->__lineWidth.asInteger, composedColor, pPoints, pointCount);
2395                 }
2396
2397                 RESET_CAIRO_CLIPPING;
2398                 RESET_CAIRO_DASH_STYLE;
2399
2400                 return E_SUCCESS;
2401         }
2402         else
2403         {
2404                 std::unique_ptr<_GpPoint[]> tempPoints(new (std::nothrow) _GpPoint[pointCount]);
2405
2406                 _GpPoint* pTempPoints = tempPoints.get();
2407
2408                 if (pTempPoints == null)
2409                 {
2410                         return E_SYSTEM;
2411                 }
2412
2413                 for (unsigned int i = 0; i < pointCount; i++)
2414                 {
2415                         pTempPoints[i].x = int(pPoints[i].x);
2416                         pTempPoints[i].y = int(pPoints[i].y);
2417                 }
2418
2419                 _CanvasLine line;
2420                 _GpBufferInfo info;
2421
2422                 memset(&info, 0, sizeof(info));
2423
2424                 SystemPixel* pBufferAddr = null;
2425                 int bufferPitch = 0;
2426
2427                 __pScratchPad->GetBuffer(pBufferAddr, bufferPitch);
2428
2429                 info.width = __pScratchPad->GetWidth();
2430                 info.height = __pScratchPad->GetHeight();
2431                 info.bitsPerPixel = 32;
2432                 info.pixelPerLine = bufferPitch;
2433                 info.pPixels = (void*) pBufferAddr;
2434                 info.color32 = composedColor;
2435                 info.isClipBoundsSet = this->__isClipBoundsSet;
2436                 info.clipBounds.SetBounds(this->__clipBounds.x, this->__clipBounds.y, this->__clipBounds.width, this->__clipBounds.height);
2437
2438                 line.SetLineWidth(this->__lineWidth.asInteger);
2439
2440                 result r = line.DrawPolyLine(int(pointCount), pTempPoints, info);
2441
2442                 return r;
2443         }
2444 }
2445
2446 result
2447 _Canvas::DrawRectangle(const _Util::Rectangle<int>& rect)
2448 {
2449         _Util::Rectangle<double> doubleRect =
2450         {
2451                 double(rect.x),
2452                 double(rect.y),
2453                 double(rect.w),
2454                 double(rect.h)
2455         };
2456
2457         return this->DrawRectangle(doubleRect);
2458 }
2459
2460 result
2461 _Canvas::DrawRectangle(const _Util::Rectangle<double>& rectangle)
2462 {
2463         if ((rectangle.w <= 0.0) || (rectangle.h <= 0.0))
2464         {
2465                 return E_SUCCESS;
2466         }
2467
2468         unsigned long composedColor = _ComposeColor(this->__fgColor, this->__fgOpacity);
2469
2470         bool tryToDrawWithCairo = (__lineWidth.applied == _Util::ScalarHolder::AS_DOUBLE || __lineWidth.asInteger > 1 || __dashData.pattern.Size() > 0);
2471
2472         if (tryToDrawWithCairo)
2473         {
2474                 _NativeGfxEngine* pCairo = static_cast<_NativeGfxEngine*>(_pNativeGfxEngine);
2475
2476                 if (pCairo && pCairo->pCairo)
2477                 {
2478                         SET_CAIRO_DASH_STYLE;
2479                         SET_CAIRO_CLIPPING;
2480
2481                         if (__lineWidth.applied != _Util::ScalarHolder::AS_INTEGER)
2482                         {
2483                                 _Cairo::DrawRectangle(pCairo->pCairo, this->__lineWidth.asDouble, composedColor, rectangle);
2484                         }
2485                         else
2486                         {
2487                                 _Cairo::DrawRectangle(pCairo->pCairo, this->__lineWidth.asInteger, composedColor, rectangle);
2488                         }
2489
2490                         RESET_CAIRO_CLIPPING;
2491                         RESET_CAIRO_DASH_STYLE;
2492
2493                         return E_SUCCESS;
2494                 }
2495         }
2496
2497         // falls through legacy drawing solution
2498
2499         int x1 = static_cast<int>(rectangle.x);
2500         int y1 = static_cast<int>(rectangle.y);
2501         int x2 = x1 + static_cast<int>(rectangle.w) - 1;
2502         int y2 = y1 + static_cast<int>(rectangle.h) - 1;
2503
2504         if (this->__lineWidth.asInteger == 1)
2505         {
2506                 if (!this->__isClipBoundsSet)
2507                 {
2508                         __pScratchPad->RegisterFillRect(_RasterOp::FnFillRectAlpha32Bit);
2509
2510                         if (x2 > x1 && y2 > y1)
2511                         {
2512                                 __pScratchPad->FillRect(x1, y1, x2 - x1, 1, composedColor);
2513                                 __pScratchPad->FillRect(x2, y1, 1, y2 - y1, composedColor);
2514
2515                                 __pScratchPad->FillRect(x1 + 1, y2, x2 - x1, 1, composedColor);
2516                                 __pScratchPad->FillRect(x1, y1 + 1, 1, y2 - y1, composedColor);
2517                         }
2518                         else
2519                         {
2520                                 __pScratchPad->FillRect(x1, y1, static_cast<int>(rectangle.w), static_cast<int>(rectangle.h), composedColor);
2521                         }
2522
2523                         __pScratchPad->RegisterFillRect(null);
2524                 }
2525                 else
2526                 {
2527                         _Util::Rectangle<int> clip = { this->__clipBounds.x, this->__clipBounds.y, this->__clipBounds.width, this->__clipBounds.height };
2528
2529                         if (x2 > x1 && y2 > y1)
2530                         {
2531                                 _Util::Rectangle<int> rect1 = { x1, y1, x2 - x1, 1 };
2532                                 _Util::Rectangle<int> rect2 = { x2, y1, 1, y2 - y1 };
2533                                 _Util::Rectangle<int> rect3 = { x1 + 1, y2, x2 - x1, 1 };
2534                                 _Util::Rectangle<int> rect4 = { x1, y1 + 1, 1, y2 - y1 };
2535
2536                                 _FillRectangleWithClip(__pScratchPad, composedColor, rect1, clip);
2537                                 _FillRectangleWithClip(__pScratchPad, composedColor, rect2, clip);
2538                                 _FillRectangleWithClip(__pScratchPad, composedColor, rect3, clip);
2539                                 _FillRectangleWithClip(__pScratchPad, composedColor, rect4, clip);
2540                         }
2541                         else
2542                         {
2543                                 _Util::Rectangle<int> rect1 = { x1, y1, static_cast<int>(rectangle.w), static_cast<int>(rectangle.h) };
2544
2545                                 _FillRectangleWithClip(__pScratchPad, composedColor, rect1, clip);
2546                         }
2547                 }
2548
2549                 return E_SUCCESS;
2550         }
2551         else if (this->__lineWidth.asInteger > 1)
2552         {
2553                 _GpPoint tempPoints[4] =
2554                 {
2555                         { x1, y1 },
2556                         { x2, y1 },
2557                         { x2, y2 },
2558                         { x1, y2 }
2559                 };
2560
2561                 _CanvasLine line;
2562                 _GpBufferInfo info;
2563
2564                 memset(&info, 0, sizeof(info));
2565
2566                 SystemPixel* pBufferAddr = null;
2567                 int bufferPitch = 0;
2568
2569                 __pScratchPad->GetBuffer(pBufferAddr, bufferPitch);
2570
2571                 info.width = __pScratchPad->GetWidth();
2572                 info.height = __pScratchPad->GetHeight();
2573                 info.bitsPerPixel = 32;
2574                 info.pixelPerLine = bufferPitch;
2575                 info.pPixels = (void*) pBufferAddr;
2576                 info.color32 = composedColor;
2577                 info.isClipBoundsSet = this->__isClipBoundsSet;
2578                 info.clipBounds.SetBounds(this->__clipBounds.x, this->__clipBounds.y, this->__clipBounds.width, this->__clipBounds.height);
2579
2580                 line.SetLineWidth(this->__lineWidth.asInteger);
2581
2582                 result r = line.DrawPolygon(4, tempPoints, info);
2583
2584                 return r;
2585         }
2586
2587         // this->__lineWidth is always greater than 0
2588         return E_SUCCESS;
2589 }
2590
2591 result
2592 _Canvas::DrawRoundRectangle(const _Util::Rectangle<int>& rect, const _Util::Dimension<int>& arcDim)
2593 {
2594         _Util::Rectangle<double> doubleRect =
2595         {
2596                 double(rect.x),
2597                 double(rect.y),
2598                 double(rect.w),
2599                 double(rect.h)
2600         };
2601
2602         _Util::Dimension<double> doubleArcDim =
2603         {
2604                 double(rect.w),
2605                 double(rect.h)
2606         };
2607
2608         return this->DrawRoundRectangle(doubleRect, doubleArcDim);
2609 }
2610
2611 result
2612 _Canvas::DrawRoundRectangle(const _Util::Rectangle<double>& rect, const _Util::Dimension<double>& arcDim)
2613 {
2614         if ((rect.w <= 0.0) || (rect.h <= 0))
2615         {
2616                 return E_SUCCESS;
2617         }
2618
2619         if ((int(arcDim.w) == 0) || (int(arcDim.h) == 0))
2620         {
2621                 return this->DrawRectangle(rect);
2622         }
2623
2624         _Util::Dimension<double> revisedArcDim =
2625         {
2626                 (arcDim.w <= rect.w / 2.0) ? arcDim.w : rect.w / 2.0,
2627                 (arcDim.h <= rect.h / 2.0) ? arcDim.h : rect.h / 2.0
2628         };
2629
2630         // this->__lineWidth is always greater than 0
2631
2632         unsigned long composedColor = _ComposeColor(this->__fgColor, this->__fgOpacity);
2633
2634         _NativeGfxEngine* pCairo = static_cast<_NativeGfxEngine*>(_pNativeGfxEngine);
2635
2636         if (pCairo && pCairo->pCairo)
2637         {
2638                 SET_CAIRO_DASH_STYLE;
2639                 SET_CAIRO_CLIPPING;
2640
2641                 if (__lineWidth.applied != _Util::ScalarHolder::AS_INTEGER)
2642                 {
2643                         _Cairo::DrawRoundRectangle(pCairo->pCairo, this->__lineWidth.asDouble, composedColor, rect, revisedArcDim);
2644                 }
2645                 else
2646                 {
2647                         _Cairo::DrawRoundRectangle(pCairo->pCairo, this->__lineWidth.asInteger, composedColor, rect, revisedArcDim);
2648                 }
2649
2650                 RESET_CAIRO_CLIPPING;
2651                 RESET_CAIRO_DASH_STYLE;
2652
2653                 return E_SUCCESS;
2654         }
2655         else
2656         {
2657                 _CanvasRoundRect roundRect;
2658                 _GpBufferInfo info;
2659
2660                 memset(&info, 0, sizeof(info));
2661
2662                 SystemPixel* pBufferAddr = null;
2663                 int bufferPitch = 0;
2664
2665                 __pScratchPad->GetBuffer(pBufferAddr, bufferPitch);
2666
2667                 info.width = __pScratchPad->GetWidth();
2668                 info.height = __pScratchPad->GetHeight();
2669                 info.bitsPerPixel = 32;
2670                 info.pixelPerLine = bufferPitch;
2671                 info.pPixels = (void*) pBufferAddr;
2672                 info.color32 = composedColor;
2673                 info.isClipBoundsSet = this->__isClipBoundsSet;
2674                 info.clipBounds.SetBounds(this->__clipBounds.x, this->__clipBounds.y, this->__clipBounds.width, this->__clipBounds.height);
2675
2676                 roundRect.SetLineWidth(this->__lineWidth.asInteger);
2677
2678                 return roundRect.DrawRoundRect(int(rect.x), int(rect.y), int(rect.w), int(rect.h), int(revisedArcDim.w), int(revisedArcDim.h), info);
2679         }
2680 }
2681
2682 result
2683 _Canvas::DrawTriangle(const _Util::Point<double>& point1, const _Util::Point<double>& point2, const _Util::Point<double>& point3)
2684 {
2685         // this->__lineWidth is always greater than 0
2686
2687         unsigned long composedColor = _ComposeColor(this->__fgColor, this->__fgOpacity);
2688
2689         _NativeGfxEngine* pCairo = static_cast<_NativeGfxEngine*>(_pNativeGfxEngine);
2690
2691         if (pCairo && pCairo->pCairo)
2692         {
2693                 _Util::Point<double> point[] =
2694                 {
2695                         { point1.x, point1.y },
2696                         { point2.x, point2.y },
2697                         { point3.x, point3.y }
2698                 };
2699
2700                 SET_CAIRO_DASH_STYLE;
2701                 SET_CAIRO_CLIPPING;
2702
2703                 if (__lineWidth.applied != _Util::ScalarHolder::AS_INTEGER)
2704                 {
2705                         _Cairo::DrawPolygon(pCairo->pCairo, this->__lineWidth.asDouble, composedColor, point, 3);
2706                 }
2707                 else
2708                 {
2709                         _Cairo::DrawPolygon(pCairo->pCairo, this->__lineWidth.asInteger, composedColor, point, 3);
2710                 }
2711
2712                 RESET_CAIRO_CLIPPING;
2713                 RESET_CAIRO_DASH_STYLE;
2714
2715                 return E_SUCCESS;
2716         }
2717         else
2718         {
2719                 _CanvasTriangle triangle;
2720                 _GpBufferInfo info;
2721
2722                 memset(&info, 0, sizeof(info));
2723
2724                 SystemPixel* pBufferAddr = null;
2725                 int bufferPitch = 0;
2726
2727                 __pScratchPad->GetBuffer(pBufferAddr, bufferPitch);
2728
2729                 info.width = __pScratchPad->GetWidth();
2730                 info.height = __pScratchPad->GetHeight();
2731                 info.bitsPerPixel = 32;
2732                 info.pixelPerLine = bufferPitch;
2733                 info.pPixels = (void*) pBufferAddr;
2734                 info.color32 = composedColor;
2735                 info.isClipBoundsSet = this->__isClipBoundsSet;
2736                 info.clipBounds.SetBounds(this->__clipBounds.x, this->__clipBounds.y, this->__clipBounds.width, this->__clipBounds.height);
2737
2738                 triangle.SetLineWidth(this->__lineWidth.asInteger);
2739
2740                 _GpPoint p1 = { int(point1.x), int(point1.y) };
2741                 _GpPoint p2 = { int(point2.x), int(point2.y) };
2742                 _GpPoint p3 = { int(point3.x), int(point3.y) };
2743
2744                 return triangle.DrawTriangle(p1, p2, p3, info);
2745         }
2746 }
2747
2748 result
2749 _Canvas::FillTriangle(const Color& color, const _Util::Point<int>& point1, const _Util::Point<int>& point2, const _Util::Point<int>& point3)
2750 {
2751         unsigned long composedColor = _ComposeColor(color.GetRGB32(), this->__fgOpacity);
2752
2753         _Util::Point<double> doublePoint1 =
2754         {
2755                 double(point1.x),
2756                 double(point1.y)
2757         };
2758
2759         _Util::Point<double> doublePoint2 =
2760         {
2761                 double(point1.x),
2762                 double(point1.y)
2763         };
2764
2765         _Util::Point<double> doublePoint3 =
2766         {
2767                 double(point1.x),
2768                 double(point1.y)
2769         };
2770
2771         return this->__FillTriangle(composedColor, doublePoint1, doublePoint2, doublePoint3);
2772 }
2773
2774 result
2775 _Canvas::FillTriangle(const Color& color, const _Util::Point<double>& point1, const _Util::Point<double>& point2, const _Util::Point<double>& point3)
2776 {
2777         unsigned long composedColor = _ComposeColor(color.GetRGB32(), this->__fgOpacity);
2778
2779         return this->__FillTriangle(composedColor, point1, point2, point3);
2780 }
2781
2782 result
2783 _Canvas::__FillTriangle(unsigned long composedColor, const _Util::Point<double>& point1, const _Util::Point<double>& point2, const _Util::Point<double>& point3)
2784 {
2785         // this->__lineWidth is always greater than 0
2786
2787         _NativeGfxEngine* pCairo = static_cast<_NativeGfxEngine*>(_pNativeGfxEngine);
2788
2789         if (pCairo && pCairo->pCairo)
2790         {
2791                 _Util::Point<double> point[] =
2792                 {
2793                         { point1.x, point1.y },
2794                         { point2.x, point2.y },
2795                         { point3.x, point3.y }
2796                 };
2797
2798                 SET_CAIRO_CLIPPING;
2799
2800                 _Cairo::FillPolygon(pCairo->pCairo, composedColor, point, 3);
2801
2802                 RESET_CAIRO_CLIPPING;
2803
2804                 return E_SUCCESS;
2805         }
2806         else
2807         {
2808                 _CanvasTriangle triangle;
2809                 _GpBufferInfo info;
2810
2811                 memset(&info, 0, sizeof(info));
2812
2813                 SystemPixel* pBufferAddr = null;
2814                 int bufferPitch = 0;
2815
2816                 __pScratchPad->GetBuffer(pBufferAddr, bufferPitch);
2817
2818                 info.width = __pScratchPad->GetWidth();
2819                 info.height = __pScratchPad->GetHeight();
2820                 info.bitsPerPixel = 32;
2821                 info.pixelPerLine = bufferPitch;
2822                 info.pPixels = (void*) pBufferAddr;
2823                 info.color32 = composedColor;
2824                 info.isClipBoundsSet = this->__isClipBoundsSet;
2825                 info.clipBounds.SetBounds(this->__clipBounds.x, this->__clipBounds.y, this->__clipBounds.width, this->__clipBounds.height);
2826
2827                 triangle.SetLineWidth(this->__lineWidth.asInteger);
2828
2829                 return triangle.FillTriangle(int(point1.x), int(point1.y), int(point2.x), int(point2.y), int(point3.x), int(point3.y), info);
2830         }
2831 }
2832
2833 result
2834 _Canvas::__FillEllipse(unsigned long composedColor, const _Util::Rectangle<double>& bounds)
2835 {
2836         if ((bounds.w <= 0.0) || (bounds.h <= 0.0))
2837         {
2838                 return E_SUCCESS;
2839         }
2840
2841         // this->__lineWidth is always greater than 0
2842
2843         _NativeGfxEngine* pCairo = static_cast<_NativeGfxEngine*>(_pNativeGfxEngine);
2844
2845         if (pCairo && pCairo->pCairo)
2846         {
2847                 SET_CAIRO_CLIPPING;
2848
2849                 _Cairo::FillEllipse(pCairo->pCairo, composedColor, bounds);
2850
2851                 RESET_CAIRO_CLIPPING;
2852
2853                 return E_SUCCESS;
2854         }
2855         else
2856         {
2857                 _CanvasEllipse ellipse;
2858                 _GpBufferInfo info;
2859
2860                 memset(&info, 0, sizeof(info));
2861
2862                 SystemPixel* pBufferAddr = null;
2863                 int bufferPitch = 0;
2864
2865                 __pScratchPad->GetBuffer(pBufferAddr, bufferPitch);
2866
2867                 info.width = __pScratchPad->GetWidth();
2868                 info.height = __pScratchPad->GetHeight();
2869                 info.bitsPerPixel = 32;
2870                 info.pixelPerLine = bufferPitch;
2871                 info.pPixels = (void*) pBufferAddr;
2872                 info.color32 = composedColor;
2873                 info.isClipBoundsSet = this->__isClipBoundsSet;
2874                 info.clipBounds.SetBounds(this->__clipBounds.x, this->__clipBounds.y, this->__clipBounds.width, this->__clipBounds.height);
2875
2876                 ellipse.SetLineWidth(this->__lineWidth.asInteger);
2877
2878                 return ellipse.FillElliepse(int(bounds.x), int(bounds.y), int(bounds.w), int(bounds.h), info);
2879         }
2880 }
2881
2882 result
2883 _Canvas::FillEllipse(const Color& color, const _Util::Rectangle<int>& bounds)
2884 {
2885         unsigned long composedColor = _ComposeColor(color.GetRGB32(), this->__fgOpacity);
2886
2887         _Util::Rectangle<double> doubleBounds =
2888         {
2889                 double(bounds.x),
2890                 double(bounds.y),
2891                 double(bounds.w),
2892                 double(bounds.h)
2893         };
2894
2895         return this->__FillEllipse(composedColor, doubleBounds);
2896 }
2897
2898 result
2899 _Canvas::FillEllipse(const Color& color, const _Util::Rectangle<double>& bounds)
2900 {
2901         unsigned long composedColor = _ComposeColor(color.GetRGB32(), this->__fgOpacity);
2902
2903         return this->__FillEllipse(composedColor, bounds);
2904 }
2905
2906 result
2907 _Canvas::FillPolygon(const Color& color, const _Util::Point<double>* pPoints, unsigned int pointCount)
2908 {
2909         //
2910         // Implementation of this method in API versions prior to 2.0 has the following issue:
2911         //
2912         // -# If there are 4 input points and conditions below is satisfied, the drawing result does not match the expected behavior. @n
2913         //
2914         //   "point[0].x == point[3].x && point[1].x == point[2].x && point[0].y == point[1].y && point[2].y == point[3].y"
2915         //
2916         // there are 4 cases can be occurred.
2917         //
2918         // [case1] (p[0]->x > p[1]->x && p[0]->y > p[3]->y)
2919         //
2920         //              p2________p3
2921         //              |         |
2922         //              |         |
2923         //              |         |     <--- expected result
2924         //              |         |
2925         //              p1--------p0_________
2926         //                                 |         |
2927         //                                 |         |
2928         //                                 |         |   <--- wrong result
2929         //                                 |         |
2930         //                                  ---------
2931         //
2932         // [case2] (p[0]->x < p[1]->x && p[0]->y > p[3]->y)
2933         //
2934         //              p3________p2
2935         //              |         |
2936         //              |         |
2937         //              |         |   <--- expected result
2938         //              |         |
2939         //              p0--------p1
2940         //              |         |
2941         //              |         |
2942         //              |         |   <--- wrong result
2943         //              |         |
2944         //               ---------
2945         //
2946         // [case3] (p[0]->x < p[1]->x && p[0]->y < p[3]->y)
2947         //
2948         //              p0________p1
2949         //              |         |
2950         //              |         |
2951         //              |         |   <--- no problem.
2952         //              |         |
2953         //              p3--------p2
2954         //
2955         //
2956         // [case4] (p[0]->x > p[1]->x && p[0]->y < p[3]->y)
2957         //
2958         //              p1________p0________
2959         //              |         |         |
2960         //              |         |         |
2961         //              |         |         |    <--- wrong result
2962         //              |         |         |
2963         //              p2--------p3--------
2964         //                 ^
2965         //             |
2966         //              -- expected result
2967         //
2968         // The issue mentioned above is resolved in API version 2.0, So, check the SDK version and emulate problem before step forward furthermore.
2969         //
2970         // CR approved, no. EP-47D6817268074396919211307C39CA55
2971         //
2972
2973         // this->__lineWidth is always greater than 0
2974
2975         unsigned long composedColor = _ComposeColor(color.GetRGB32(), this->__fgOpacity);
2976
2977         _NativeGfxEngine* pCairo = static_cast<_NativeGfxEngine*>(_pNativeGfxEngine);
2978
2979         if (pCairo && pCairo->pCairo)
2980         {
2981                 SET_CAIRO_CLIPPING;
2982
2983                 _Cairo::FillPolygon(pCairo->pCairo, composedColor, pPoints, pointCount);
2984
2985                 RESET_CAIRO_CLIPPING;
2986
2987                 return E_SUCCESS;
2988         }
2989         else
2990         {
2991                 _CanvasFillPolygon polygon;
2992                 _GpBufferInfo info;
2993
2994                 memset(&info, 0, sizeof(info));
2995
2996                 SystemPixel* pBufferAddr = null;
2997                 int bufferPitch = 0;
2998
2999                 __pScratchPad->GetBuffer(pBufferAddr, bufferPitch);
3000
3001                 info.width = __pScratchPad->GetWidth();
3002                 info.height = __pScratchPad->GetHeight();
3003                 info.bitsPerPixel = 32;
3004                 info.pixelPerLine = bufferPitch;
3005                 info.pPixels = (void*) pBufferAddr;
3006                 info.color32 = composedColor;
3007                 info.isClipBoundsSet = this->__isClipBoundsSet;
3008                 info.clipBounds.SetBounds(this->__clipBounds.x, this->__clipBounds.y, this->__clipBounds.width, this->__clipBounds.height);
3009
3010                 polygon.SetLineWidth(this->__lineWidth.asInteger);
3011
3012                 std::unique_ptr<_GpPoint[]> tempPoints(new (std::nothrow) _GpPoint[pointCount]);
3013
3014                 _GpPoint* pTempPoints = tempPoints.get();
3015
3016                 if (pTempPoints == null)
3017                 {
3018                         return E_SYSTEM;
3019                 }
3020
3021                 for (unsigned int i = 0; i < pointCount; i++)
3022                 {
3023                         pTempPoints[i].x = int(pPoints[i].x);
3024                         pTempPoints[i].y = int(pPoints[i].y);
3025                 }
3026
3027                 result r = polygon.FillPolygon(int(pointCount), pTempPoints, info);
3028
3029                 return r;
3030         }
3031 }
3032
3033 result
3034 _Canvas::__FillRectangle(unsigned long composedColor, const _Util::Rectangle<double>& rectangle)
3035 {
3036         if ((rectangle.w <= 0.0) || (rectangle.h <= 0.0))
3037         {
3038                 return E_SUCCESS;
3039         }
3040
3041         _NativeGfxEngine* pCairo = static_cast<_NativeGfxEngine*>(_pNativeGfxEngine);
3042
3043         if (pCairo && pCairo->pCairo)
3044         {
3045                 SET_CAIRO_CLIPPING;
3046
3047                 _Cairo::FillRectangle(pCairo->pCairo, composedColor, rectangle);
3048
3049                 RESET_CAIRO_CLIPPING;
3050
3051                 return E_SUCCESS;
3052         }
3053         else
3054         {
3055                 _Util::Rectangle<int> rect =
3056                 {
3057                         static_cast<int>(rectangle.x),
3058                         static_cast<int>(rectangle.y),
3059                         static_cast<int>(rectangle.w),
3060                         static_cast<int>(rectangle.h)
3061                 };
3062
3063                 if (this->__isClipBoundsSet)
3064                 {
3065                         int x1 = rect.x;
3066                         int y1 = rect.y;
3067                         int x2 = x1 + rect.w;
3068                         int y2 = y1 + rect.h;
3069
3070                         x1 = (x1 >= this->__clipBounds.x) ? x1 : this->__clipBounds.x;
3071                         y1 = (y1 >= this->__clipBounds.y) ? y1 : this->__clipBounds.y;
3072
3073                         x2 = (x2 <= this->__clipBounds.x + this->__clipBounds.width) ? x2 : this->__clipBounds.x + this->__clipBounds.width;
3074                         y2 = (y2 <= this->__clipBounds.y + this->__clipBounds.height) ? y2 : this->__clipBounds.y + this->__clipBounds.height;
3075
3076                         rect.x = x1;
3077                         rect.y = y1;
3078                         rect.w = x2 - x1;
3079                         rect.h = y2 - y1;
3080                 }
3081
3082                 if (rect.w > 0 && rect.h > 0)
3083                 {
3084                         // alpha-fill-rect() applied
3085                         __pScratchPad->RegisterFillRect(_RasterOp::FnFillRectAlpha32Bit);
3086                         __pScratchPad->FillRect(rect.x, rect.y, rect.w, rect.h, composedColor);
3087                         __pScratchPad->RegisterFillRect(null);
3088                 }
3089         }
3090
3091         return E_SUCCESS;
3092 }
3093
3094 result
3095 _Canvas::FillRectangle(const Color& color, const Rectangle& rect)
3096 {
3097         unsigned long composedColor = _ComposeColor(color.GetRGB32(), this->__fgOpacity);
3098
3099         return this->__FillRectangle(composedColor, _Util::Convert<Rectangle, _Util::Rectangle<double> >(rect));
3100 }
3101
3102 result
3103 _Canvas::FillRectangle(const Color& color, const _Util::Rectangle<int>& rect)
3104 {
3105         unsigned long composedColor = _ComposeColor(color.GetRGB32(), this->__fgOpacity);
3106
3107         _Util::Rectangle<double> doubleRect =
3108         {
3109                 double(rect.x),
3110                 double(rect.y),
3111                 double(rect.w),
3112                 double(rect.h)
3113         };
3114
3115         return this->__FillRectangle(composedColor, doubleRect);
3116 }
3117
3118 result
3119 _Canvas::FillRectangle(const Color& color, const _Util::Rectangle<double>& rect)
3120 {
3121         unsigned long composedColor = _ComposeColor(color.GetRGB32(), this->__fgOpacity);
3122
3123         return this->__FillRectangle(composedColor, rect);
3124 }
3125
3126 result
3127 _Canvas::FillRoundRectangle(const Color& color, const _Util::Rectangle<int>& rect, const _Util::Dimension<int>& arcDim)
3128 {
3129         unsigned long composedColor = _ComposeColor(color.GetRGB32(), this->__fgOpacity);
3130
3131         _Util::Rectangle<double> doubleRect =
3132         {
3133                 double(rect.x),
3134                 double(rect.y),
3135                 double(rect.w),
3136                 double(rect.h)
3137         };
3138
3139         _Util::Dimension<double> doubleArcDim =
3140         {
3141                 double(rect.w),
3142                 double(rect.h)
3143         };
3144
3145         return this->__FillRoundRectangle(composedColor, doubleRect, doubleArcDim);
3146 }
3147
3148 result
3149 _Canvas::FillRoundRectangle(const Color& color, const _Util::Rectangle<double>& rect, const _Util::Dimension<double>& arcDim)
3150 {
3151         unsigned long composedColor = _ComposeColor(color.GetRGB32(), this->__fgOpacity);
3152
3153         return this->__FillRoundRectangle(composedColor, rect, arcDim);
3154 }
3155
3156 result
3157 _Canvas::__FillRoundRectangle(unsigned long composedColor, const _Util::Rectangle<double>& rect, const _Util::Dimension<double>& arcDim)
3158 {
3159         if ((rect.w <= 0.0) || (rect.h <= 0.0))
3160         {
3161                 return E_SUCCESS;
3162         }
3163
3164         if ((int(arcDim.w) <= 0) || (int(arcDim.h) <= 0))
3165         {
3166                 return this->__FillRectangle(composedColor, rect);
3167         }
3168
3169         _Util::Dimension<double> revisedArcDim =
3170         {
3171                 (arcDim.w <= rect.w / 2.0) ? arcDim.w : rect.w / 2.0,
3172                 (arcDim.h <= rect.h / 2.0) ? arcDim.h : rect.h / 2.0
3173         };
3174
3175         // this->__lineWidth is always greater than 0
3176
3177         _NativeGfxEngine* pCairo = static_cast<_NativeGfxEngine*>(_pNativeGfxEngine);
3178
3179         if (pCairo && pCairo->pCairo)
3180         {
3181                 SET_CAIRO_CLIPPING;
3182
3183                 _Cairo::FillRoundRectangle(pCairo->pCairo, composedColor, rect, revisedArcDim);
3184
3185                 RESET_CAIRO_CLIPPING;
3186
3187                 return E_SUCCESS;
3188         }
3189         else
3190         {
3191                 _CanvasRoundRect roundRect;
3192                 _GpBufferInfo info;
3193
3194                 memset(&info, 0, sizeof(info));
3195
3196                 SystemPixel* pBufferAddr = null;
3197                 int bufferPitch = 0;
3198
3199                 __pScratchPad->GetBuffer(pBufferAddr, bufferPitch);
3200
3201                 info.width = __pScratchPad->GetWidth();
3202                 info.height = __pScratchPad->GetHeight();
3203                 info.bitsPerPixel = 32;
3204                 info.pixelPerLine = bufferPitch;
3205                 info.pPixels = (void*) pBufferAddr;
3206                 info.color32 = composedColor;
3207                 info.isClipBoundsSet = this->__isClipBoundsSet;
3208                 info.clipBounds.SetBounds(this->__clipBounds.x, this->__clipBounds.y, this->__clipBounds.width, this->__clipBounds.height);
3209
3210                 roundRect.SetLineWidth(this->__lineWidth.asInteger);
3211
3212                 return roundRect.FillRoundRectangle(int(rect.x), int(rect.y), int(rect.w), int(rect.h), int(revisedArcDim.w), int(revisedArcDim.h), info);
3213         }
3214 }
3215
3216 result
3217 _Canvas::DrawText(const Point& point, const Tizen::Base::String& text)
3218 {
3219         return _Font::DrawText(*this, point, text, 0, text.GetLength());
3220 }
3221
3222 result
3223 _Canvas::DrawText(const Point& point, const Tizen::Base::String& text, int startIndex, int length)
3224 {
3225         return _Font::DrawText(*this, point, text, startIndex, length);
3226 }
3227
3228 result
3229 _Canvas::DrawText(const Point& point, const Tizen::Base::String& text, int startIndex, int length, const Color& outlineColor)
3230 {
3231         return _Font::DrawText(*this, point, text, startIndex, length, outlineColor);
3232 }
3233
3234 Rectangle
3235 _Canvas::GetBounds(void) const
3236 {
3237         Rectangle rect(this->__xBufferPos, this->__yBufferPos, __pScratchPad->GetWidth(), __pScratchPad->GetHeight());
3238
3239         if (this->__windowHandle != INVALID_HANDLE)
3240         {
3241                 rect.x = 0;
3242                 rect.y = 0;
3243         }
3244
3245         return rect;
3246 }
3247
3248 LineStyle
3249 _Canvas::GetLineStyle() const
3250 {
3251         SysTryReturn(NID_GRP, this && this->__pSurface, LINE_STYLE_MAX, E_OPERATION_FAILED, "[E_OPERATION_FAILED] This instance is not constructed yet.\n");
3252
3253         return this->__lineStyle;
3254 }
3255
3256 int
3257 _Canvas::GetLineWidth() const
3258 {
3259         SysTryReturn(NID_GRP, this && this->__pSurface, -1, E_OPERATION_FAILED, "[E_OPERATION_FAILED] This instance is not constructed yet.\n");
3260
3261         return this->__lineWidth.asInteger;
3262 }
3263
3264 result
3265 _Canvas::SetLineStyle(LineStyle style)
3266 {
3267         this->__lineStyle = style;
3268
3269         return E_SUCCESS;
3270 }
3271
3272 result
3273 _Canvas::SetLineWidth(int width, float widthAsFloat)
3274 {
3275         SysTryReturnResult(NID_GRP, width > 0, E_OUT_OF_RANGE, "The given line width(%d) is out of range.\n", width);
3276
3277         this->__lineWidth = width;
3278         this->__lineWidth.asDouble = double(widthAsFloat);
3279
3280         return E_SUCCESS;
3281 }
3282
3283 result
3284 _Canvas::SetLineWidth(float width)
3285 {
3286         SysTryReturnResult(NID_GRP, width > 0.0f, E_OUT_OF_RANGE, "The given line width(%f) is out of range.\n", width);
3287
3288         this->__lineWidth = width;
3289
3290         return E_SUCCESS;
3291 }
3292
3293 result
3294 _Canvas::SetDashPattern(const Tizen::Graphics::_Util::AccumList<double>& dashValueList, double offset)
3295 {
3296         SysTryReturn(NID_GRP, this && this->__pSurface, E_OPERATION_FAILED, E_OPERATION_FAILED, "[E_OPERATION_FAILED] This instance is not constructed yet.\n");
3297
3298         {
3299                 Tizen::Graphics::_Util::AccumList<double> listSwap;
3300                 this->__dashData.pattern.Swap(listSwap);
3301
3302                 this->__dashData.offset = 0.0;
3303         }
3304
3305         {
3306                 Tizen::Graphics::_Util::AccumList<double>::ConstIterator dashIterator = dashValueList.Begin();
3307
3308                 for (; dashIterator != dashValueList.End(); dashIterator++)
3309                 {
3310                         this->__dashData.pattern.Push(*dashIterator);
3311                 }
3312
3313                 this->__dashData.offset = offset;
3314         }
3315
3316         return E_SUCCESS;
3317 }
3318
3319 void
3320 _Canvas::SetDrawingQuality(BitmapDrawingQuality quality)
3321 {
3322         // 'quality' is verified in _CanvasImpl::SetDrawingQuality()
3323         this->__bitmapDrawingQuality = quality;
3324 }
3325
3326 BitmapDrawingQuality
3327 _Canvas::GetDrawingQuality(void) const
3328 {
3329         return this->__bitmapDrawingQuality;
3330 }
3331
3332 void
3333 _Canvas::SetBlendingMode(BlendingMode blendingMode)
3334 {
3335         // 'blendingMode' is verified in _CanvasImpl::SetBlendingMode()
3336         this->__blendingMode = blendingMode;
3337 }
3338
3339 BlendingMode
3340 _Canvas::GetBlendingMode(void) const
3341 {
3342         return this->__blendingMode;
3343 }
3344
3345 result
3346 _Canvas::GetPixel(const Point& point, Color& color) const
3347 {
3348         Point pos(point.x, point.y);
3349
3350         // [ykahn 2011.06.27] revise the value of 'point' if it goes out-of-range
3351         {
3352                 Rectangle rtCanvas = _GetBoundsRel(*this);
3353
3354                 SysTryReturnResult(NID_GRP, !rtCanvas.IsEmpty(), E_OUT_OF_RANGE, "Cannot get the bounds of the canvas.\n");
3355
3356                 if (pos.x >= rtCanvas.width && rtCanvas.width >= 1)
3357                 {
3358                         pos.x = rtCanvas.width - 1;
3359                 }
3360
3361                 if (pos.y >= rtCanvas.height && rtCanvas.height >= 1)
3362                 {
3363                         pos.y = rtCanvas.height - 1;
3364                 }
3365         }
3366
3367         {
3368                 result r = E_OUT_OF_RANGE;
3369
3370                 Rectangle rect = this->GetBounds();
3371
3372                 rect.x = 0;
3373                 rect.y = 0;
3374
3375                 if ((point.x >= rect.x && point.x < rect.x + rect.width) && (point.y >= rect.y && point.y < rect.y + rect.height))
3376                 {
3377                         BufferInfo info;
3378
3379                         (const_cast<_Canvas*>(this))->Lock(info);
3380
3381                         if (info.bitsPerPixel == 32)
3382                         {
3383                                 unsigned long* pDest32 = (unsigned long*) info.pPixels;
3384                                 long pitch = info.pitch / 4;
3385
3386                                 color.SetRGB32(pDest32[pitch * point.y + point.x], true);
3387
3388                                 r = E_SUCCESS;
3389                         }
3390                         else if (info.bitsPerPixel == 16)
3391                         {
3392                                 unsigned short* pDest16 = (unsigned short*) info.pPixels;
3393                                 long pitch = info.pitch / 2;
3394
3395                                 unsigned short color16 = pDest16[pitch * point.y + point.x];
3396
3397                                 unsigned long r = (color16 & 0xF800) >> 8;
3398                                 unsigned long g = (color16 & 0x07E0) >> 3;
3399                                 unsigned long b = (color16 & 0x001F) << 3;
3400
3401                                 r += (r >> 5);
3402                                 g += (g >> 6);
3403                                 b += (b >> 5);
3404
3405                                 unsigned long color32 = 0xFF000000 | (r << 16) | (g << 8) | (b);
3406
3407                                 color.SetRGB32(color32, true);
3408
3409                                 r = E_SUCCESS;
3410                         }
3411
3412                         (const_cast<_Canvas*>(this))->Unlock();
3413                 }
3414
3415                 return r;
3416         }
3417 }
3418
3419 result
3420 _Canvas::SetPixel(const _Util::Point<int>& point)
3421 {
3422         unsigned long composedColor = _ComposeColor(this->__fgColor, this->__fgOpacity);
3423
3424         if (!this->__isClipBoundsSet)
3425         {
3426                 __pScratchPad->FillRect(point.x, point.y, 1, 1, composedColor);
3427         }
3428         else
3429         {
3430                 _Util::Rectangle<int> rect = { point.x, point.y, 1, 1 };
3431                 _Util::Rectangle<int> clip = { this->__clipBounds.x, this->__clipBounds.y, this->__clipBounds.width, this->__clipBounds.height };
3432
3433                 _FillRectangleWithClip(__pScratchPad, composedColor, rect, clip);
3434         }
3435
3436         return E_SUCCESS;
3437 }
3438
3439 result
3440 _Canvas::SetPixel(const _Util::Point<double>& point)
3441 {
3442         _Util::Rectangle<double> doubleRect =
3443         {
3444                 point.x,
3445                 point.y,
3446                 1.0,
3447                 1.0
3448         };
3449
3450         unsigned long composedColor = _ComposeColor(this->__fgColor, this->__fgOpacity);
3451
3452         this->__FillRectangle(composedColor, doubleRect);
3453
3454         return E_SUCCESS;
3455 }
3456
3457 result
3458 _Canvas::Show()
3459 {
3460         int bufferWidth = __pSurface->GetWidth();
3461         int bufferHeight = __pSurface->GetHeight();
3462         int bufferPpl = __pSurface->GetPitch();
3463
3464         // cannot use 'if (__pSurface->GetHandle())'
3465         if (this->__windowHandle != INVALID_HANDLE)
3466         {
3467 #if 0
3468                 evas_object_image_pixels_dirty_set((Evas_Object*) this->__windowHandle, true);
3469 #else
3470                 Evas_Object* pSourceObject = _GetWindowSourceObject(this->__windowHandle);
3471                 evas_object_image_data_set(pSourceObject, evas_object_image_data_get(pSourceObject, EINA_TRUE));
3472                 evas_object_image_data_update_add(pSourceObject, 0, 0, bufferWidth, bufferHeight);
3473 #endif
3474
3475                 evas_object_show((Evas_Object*) this->__windowHandle);
3476
3477                 _FlushCanvas();
3478         }
3479         else
3480         {
3481                 SysTryReturnResult(NID_GRP, Tizen::App::_AppInfo::IsOspCompat(), E_UNSUPPORTED_OPERATION, "This method is unsupported in Tizen.");
3482
3483                 _CanvasShowFromMemory(this->__xBufferPos, this->__yBufferPos, 0, 0, bufferWidth, bufferHeight, __pBuffer, bufferWidth, bufferHeight, 32, bufferPpl * 4);
3484         }
3485
3486         return E_SUCCESS;
3487 }
3488
3489 result
3490 _Canvas::Show(const Rectangle& rect)
3491 {
3492         if ((rect.width == 0) || (rect.height == 0))
3493         {
3494                 return E_SUCCESS;
3495         }
3496
3497         if (this->__windowHandle != INVALID_HANDLE)
3498         {
3499                 int x1 = rect.x;
3500                 int x2 = rect.x + rect.width;
3501                 int y1 = rect.y;
3502                 int y2 = rect.y + rect.height;
3503
3504                 if (x1 + 1 < x2)
3505                 {
3506                         x1++;
3507                 }
3508
3509                 if (x2 - 1 > x1)
3510                 {
3511                         x2--;
3512                 }
3513
3514                 if (y1 + 1 < y2)
3515                 {
3516                         y1++;
3517                 }
3518
3519                 if (y2 - 1 > y1)
3520                 {
3521                         y2--;
3522                 }
3523
3524 #if 0
3525                 evas_object_image_pixels_dirty_set((Evas_Object*) this->__windowHandle, true);
3526                 // same as evas_object_image_data_update_add((Evas_Object*)this->__windowHandle, rect.x + 1, rect.y + 1, rect.width - 2, rect.height - 2), if (width >= 3) and (height >= 3)
3527                 evas_object_image_data_update_add((Evas_Object*) this->__windowHandle, x1, y1, x2 - x1, y2 - y1);
3528 #else
3529                 Evas_Object* pSourceObject = _GetWindowSourceObject(this->__windowHandle);
3530                 evas_object_image_data_set(pSourceObject, evas_object_image_data_get(pSourceObject, EINA_TRUE));
3531                 evas_object_image_data_update_add(pSourceObject, x1, y1, x2 - x1, y2 - y1);
3532 #endif
3533
3534                 evas_object_show((Evas_Object*) this->__windowHandle);
3535
3536                 _FlushCanvas();
3537         }
3538         else
3539         {
3540                 SysTryReturnResult(NID_GRP, Tizen::App::_AppInfo::IsOspCompat(), E_UNSUPPORTED_OPERATION, "This method is unsupported in Tizen.");
3541
3542                 int bufferWidth = __pSurface->GetWidth();
3543                 int bufferHeight = __pSurface->GetHeight();
3544                 int bufferPpl = __pSurface->GetPitch();
3545
3546                 _CanvasShowFromMemory(this->__xBufferPos + rect.x, this->__yBufferPos + rect.y, rect.x, rect.y, rect.width, rect.height, __pBuffer, bufferWidth, bufferHeight, 32, bufferPpl * 4);
3547         }
3548
3549         return E_SUCCESS;
3550 }
3551
3552 result
3553 _Canvas::SetFont(const _Font& font)
3554 {
3555         SysTryReturn(NID_GRP, this && this->__pSurface, E_OPERATION_FAILED, E_OPERATION_FAILED, "[E_OPERATION_FAILED] This instance is not constructed yet.");
3556
3557         // weak reference
3558         this->__pFont = const_cast<_Font*>(&font);
3559
3560         return E_SUCCESS;
3561 }
3562
3563 result
3564 _Canvas::SetPriorityFont(const _Font& font)
3565 {
3566         SysTryReturn(NID_GRP, this && this->__pSurface, E_OPERATION_FAILED, E_OPERATION_FAILED, "[E_OPERATION_FAILED] This instance is not constructed yet.");
3567
3568         // weak reference
3569         this->__pPriorityFont = const_cast<_Font*>(&font);
3570
3571         return E_SUCCESS;
3572 }
3573
3574 void
3575 _Canvas::ResetPriorityFont(void)
3576 {
3577         // nullify weak reference
3578         this->__pPriorityFont = null;
3579 }
3580
3581 result
3582 _Canvas::SetClipBounds(const Rectangle& rect)
3583 {
3584         if (__pScratchPad == null)
3585         {
3586                 return E_SYSTEM;
3587         }
3588
3589         int x1 = rect.x;
3590         int y1 = rect.y;
3591         int x2 = x1 + rect.width;
3592         int y2 = y1 + rect.height;
3593
3594         x1 = (x1 > 0) ? x1 : 0;
3595         y1 = (y1 > 0) ? y1 : 0;
3596         x2 = (x2 < __pScratchPad->GetWidth()) ? x2 : __pScratchPad->GetWidth();
3597         y2 = (y2 < __pScratchPad->GetHeight()) ? y2 : __pScratchPad->GetHeight();
3598
3599         x2 = (x1 > x2) ? x1 : x2;
3600         y2 = (y1 > y2) ? y1 : y2;
3601
3602         if (x1 == 0 && y1 == 0 && x2 == __pScratchPad->GetWidth() && y2 == __pScratchPad->GetHeight())
3603         {
3604                 this->__isClipBoundsSet = false;
3605         }
3606         else
3607         {
3608                 this->__isClipBoundsSet = true;
3609         }
3610
3611         this->__clipBounds.SetBounds(x1, y1, x2 - x1, y2 - y1);
3612
3613         return E_SUCCESS;
3614 }
3615
3616 Rectangle
3617 _Canvas::GetClipBounds(void) const
3618 {
3619         Rectangle rect;
3620
3621         SysTryReturn(NID_GRP, this && this->__pSurface, rect, E_OPERATION_FAILED, "[E_OPERATION_FAILED] This instance is not constructed yet.\n");
3622
3623         this->__GetClipBounds(rect);
3624
3625         return rect;
3626 }
3627
3628 result
3629 _Canvas::Lock(BufferInfo& info, long timeout)
3630 {
3631         if (__pScratchPad == null)
3632         {
3633                 return E_SYSTEM;
3634         }
3635
3636         if (_BufferInfoImpl::GetInstance(info) != null)
3637         {
3638                 _BufferInfoImpl::GetInstance(info)->SetHandle(_BufferInfoImpl::HANDLE_TYPE_NONE, 0);
3639         }
3640
3641         SystemPixel* pBufferAddr = null;
3642         int bufferPitch = 0;
3643
3644         __pScratchPad->GetBuffer(pBufferAddr, bufferPitch);
3645
3646         info.width = __pScratchPad->GetWidth();
3647         info.height = __pScratchPad->GetHeight();
3648         info.pitch = bufferPitch * sizeof(_SystemPixel);
3649         info.bitsPerPixel = sizeof(_SystemPixel) * 8;
3650         info.pixelFormat = PIXEL_FORMAT_ARGB8888;
3651         info.pPixels = (void*) pBufferAddr;
3652         //info.__handle   = INVALID_HANDLE;
3653
3654         return E_SUCCESS;
3655 }
3656
3657 result
3658 _Canvas::Unlock()
3659 {
3660         return E_SUCCESS;
3661 }
3662
3663 void
3664 _Canvas::SetForegroundColor(const Color& fgColor)
3665 {
3666         this->__fgColorNative = fgColor;
3667         this->__ComposeFgColor();
3668 }
3669
3670 Color
3671 _Canvas::GetForegroundColor(void)
3672 {
3673         return Color(this->__fgColor);
3674 }
3675
3676 void
3677 _Canvas::SetBackgroundColor(const Color& bgColor)
3678 {
3679         this->__bgColorNative = bgColor;
3680         this->__ComposeBgColor();
3681 }
3682
3683 Color
3684 _Canvas::GetBackgroundColor(void)
3685 {
3686         return Color(this->__bgColor);
3687 }
3688
3689 void
3690 _Canvas::SetForegroundOpacity(int level)
3691 {
3692         SysTryReturnVoidResult(NID_GRP, this && this->__pSurface, E_OPERATION_FAILED, "[E_OPERATION_FAILED] This instance is not constructed yet.\n");
3693
3694         if (level < 0)
3695         {
3696                 level = 0;
3697         }
3698
3699         if (level > 255)
3700         {
3701                 level = 255;
3702         }
3703
3704         this->__fgOpacity = level;
3705         this->__ComposeFgColor();
3706 }
3707
3708 int
3709 _Canvas::GetForegroundOpacity(void)
3710 {
3711         SysTryReturn(NID_GRP, this && this->__pSurface, 255, E_OPERATION_FAILED, "[E_OPERATION_FAILED] This instance is not constructed yet.\n");
3712
3713         return this->__fgOpacity;
3714 }
3715
3716 void
3717 _Canvas::SetBackgroundOpacity(int level)
3718 {
3719         SysTryReturnVoidResult(NID_GRP, this && this->__pSurface, E_OPERATION_FAILED, "[E_OPERATION_FAILED] This instance is not constructed yet.\n");
3720
3721         if (level < 0)
3722         {
3723                 level = 0;
3724         }
3725
3726         if (level > 255)
3727         {
3728                 level = 255;
3729         }
3730
3731         this->__bgOpacity = level;
3732         this->__ComposeBgColor();
3733 }
3734
3735 int
3736 _Canvas::GetBackgroundOpacity(void)
3737 {
3738         SysTryReturn(NID_GRP, this && this->__pSurface, 255, E_OPERATION_FAILED, "[E_OPERATION_FAILED] This instance is not constructed yet.\n");
3739
3740         return this->__bgOpacity;
3741 }
3742
3743 result
3744 _Canvas::SetPosition(int x, int y)
3745 {
3746         SysTryReturnResult(NID_GRP, this->__windowHandle == INVALID_HANDLE, E_UNSUPPORTED_OPERATION, "Window canvas does not support moving the position.\n");
3747
3748         __xBufferPos = x;
3749         __yBufferPos = y;
3750
3751         return E_SUCCESS;
3752 }
3753
3754 _Canvas*
3755 _Canvas::GetInstance(_CanvasImpl& canvas)
3756 {
3757         return (&canvas != null) ? canvas._pNativeCanvas : null;
3758 }
3759
3760 const _Canvas*
3761 _Canvas::GetInstance(const _CanvasImpl& canvas)
3762 {
3763         return (&canvas != null) ? canvas._pNativeCanvas : null;
3764 }
3765
3766 bool
3767 _Canvas::_IsWindowCanvas(void) const
3768 {
3769         if (!(this && this->__pSurface))
3770         {
3771                 return false;
3772         }
3773
3774         return (this->__windowHandle != INVALID_HANDLE);
3775 }
3776
3777 result
3778 _Canvas::_SetPosition(int x, int y)
3779 {
3780         if (!(this && this->__pSurface))
3781         {
3782                 return E_OPERATION_FAILED;
3783         }
3784
3785         if (this->__windowHandle != INVALID_HANDLE)
3786         {
3787                 return E_UNSUPPORTED_OPERATION;
3788         }
3789
3790         //?? what is this function ?
3791         __xBufferPos = x;
3792         __yBufferPos = y;
3793
3794         return E_SUCCESS;
3795 }
3796
3797 int
3798 _Canvas::_GetAlphaAttenuation(const _Bitmap& bitmap) const
3799 {
3800         // 'bitmap' and 'this' are always valid.
3801
3802         int alphaConstant = bitmap.GetAlphaConstant();
3803
3804         alphaConstant = (alphaConstant > 255) ? 255 : alphaConstant;
3805         alphaConstant = (alphaConstant < 0) ? 0 : alphaConstant;
3806
3807         int fgOpacity = this->__fgOpacity;
3808
3809         if (fgOpacity > 0 && fgOpacity < 255)
3810         {
3811                 fgOpacity += (fgOpacity >> 7);
3812                 alphaConstant = (alphaConstant * fgOpacity) >> 8;
3813         }
3814
3815         return alphaConstant;
3816 }
3817
3818 void
3819 _Canvas::_SetBlendOption(_Canvas::BlendOption blendOption)
3820 {
3821         if (!(this && this->__pSurface))
3822         {
3823                 return;
3824         }
3825
3826         if (blendOption < BLEND_MIN || blendOption >= BLEND_MAX)
3827         {
3828                 return;
3829         }
3830
3831         this->__blendOption = blendOption;
3832 }
3833
3834 _Canvas::BlendOption
3835 _Canvas::_GetBlendOption(void) const
3836 {
3837         if (!(this && this->__pSurface))
3838         {
3839                 // default
3840                 return BLEND_ALPHABLEND;
3841         }
3842
3843         return this->__blendOption;
3844 }
3845
3846 void
3847 _Canvas::__InitFgBgColorFromTheme(void)
3848 {
3849         __fgColorNative = (_GetDefaultForegroundColor) ? _GetDefaultForegroundColor() : Color(0xFF000000);
3850         __bgColorNative = (_GetDefaultBackgroundColor) ? _GetDefaultBackgroundColor() : Color(0xFFFFFFFF);
3851
3852         this->__ComposeFgColor();
3853         this->__ComposeBgColor();
3854 }
3855
3856 void
3857 _Canvas::__ComposeFgColor(void)
3858 {
3859         this->__fgColor = _ComposeColor(this->__fgColorNative.GetRGB32(), this->__fgOpacity);
3860 }
3861
3862 void
3863 _Canvas::__ComposeBgColor(void)
3864 {
3865         this->__bgColor = _ComposeColor(this->__bgColorNative.GetRGB32(), this->__bgOpacity);
3866 }
3867
3868 void
3869 _Canvas::__GetClipBounds(Rectangle& rect) const
3870 {
3871         if (this->__isClipBoundsSet)
3872         {
3873                 rect = this->__clipBounds;
3874         }
3875         else
3876         {
3877                 rect = Rectangle(0, 0, __pScratchPad->GetWidth(), __pScratchPad->GetHeight());
3878         }
3879 }
3880
3881 result
3882 _Canvas::__Copy(const Point& destPoint, const _Canvas& srcCanvas, const Rectangle& srcRect)
3883 {
3884         const _Canvas* pSrcCanvas = &srcCanvas;
3885
3886         Rectangle clippedSrcRect(srcRect);
3887
3888         if (_ClipRectangle(clippedSrcRect.x, clippedSrcRect.y, clippedSrcRect.width, clippedSrcRect.height, 0, 0, pSrcCanvas->__pScratchPad->GetWidth(), pSrcCanvas->__pScratchPad->GetHeight()) == CLIP_REJECT)
3889         {
3890                 return E_SUCCESS;
3891         }
3892
3893         __pScratchPad->BitBlt(destPoint.x, destPoint.y, pSrcCanvas->__pScratchPad, clippedSrcRect.x, clippedSrcRect.y, clippedSrcRect.width, clippedSrcRect.height);
3894
3895         return E_SUCCESS;
3896 }
3897
3898 result
3899 _Canvas::__Copy(const Rectangle& destRect, const _Canvas& srcCanvas, const Rectangle& srcRect)
3900 {
3901         const _Canvas* pSrcCanvas = &srcCanvas;
3902
3903         Rectangle clippedSrcRect(srcRect);
3904
3905         if (_ClipRectangle(clippedSrcRect.x, clippedSrcRect.y, clippedSrcRect.width, clippedSrcRect.height, 0, 0, pSrcCanvas->__pScratchPad->GetWidth(), pSrcCanvas->__pScratchPad->GetHeight()) == CLIP_REJECT)
3906         {
3907                 return E_SUCCESS;
3908         }
3909
3910         {
3911                 SystemPixel* pSrcAddr = null;
3912                 int srcPitch = 0;
3913
3914                 pSrcCanvas->__pScratchPad->GetBuffer(pSrcAddr, srcPitch);
3915                 pSrcAddr += srcPitch * clippedSrcRect.y + clippedSrcRect.x;
3916
3917                 SystemPixel* pDstAddr = null;
3918                 int dstPitch = 0;
3919
3920                 __pScratchPad->GetBuffer(pDstAddr, dstPitch);
3921
3922                 _Util::Pixmap srcImageEx(clippedSrcRect.width, clippedSrcRect.height, sizeof(SystemPixel) * 8, pSrcAddr, srcPitch * sizeof(SystemPixel));
3923                 _Util::Pixmap dstImageEx(__pScratchPad->GetWidth(), __pScratchPad->GetHeight(), sizeof(SystemPixel) * 8, pDstAddr, dstPitch * sizeof(SystemPixel));
3924
3925                 Tizen::Graphics::_Effect::ScaleImage(dstImageEx, destRect.x, destRect.y, destRect.width, destRect.height, srcImageEx);
3926         }
3927
3928         return E_SUCCESS;
3929 }
3930
3931 }} // Tizen::Graphics
3932