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