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