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