add patch
[framework/osp/uifw.git] / src / graphics / FGrp_CanvasCairo.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0/
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /*
19  * @file                FGrp_CanvasCairo.cpp
20  * @brief               This is the implementation file for the cairo solution.
21  *
22  */
23
24 #include "FGrp_CanvasCairo.h"
25 #include "util/FGrp_UtilTemplate.h"
26
27 namespace Tizen { namespace Graphics
28 {
29
30 namespace _Util
31 {
32
33 template <>
34 AutoDeletor<cairo_t>::~AutoDeletor(void)
35 {
36         if (__pPtr)
37         {
38                 cairo_destroy(__pPtr);
39         }
40 }
41
42 template <>
43 AutoDeletor<cairo_surface_t>::~AutoDeletor(void)
44 {
45         if (__pPtr)
46         {
47                 cairo_surface_destroy(__pPtr);
48         }
49 }
50
51 template <>
52 AutoDeletor<cairo_pattern_t>::~AutoDeletor(void)
53 {
54         if (__pPtr)
55         {
56                 cairo_pattern_destroy(__pPtr);
57         }
58 }
59
60 } // _Util
61
62 namespace _Cairo
63 {
64
65 const double _DOUBLE_PI = 3.141592;
66
67 void
68 SetColor(cairo_t* pCairo, unsigned long composedColor)
69 {
70         double a = ((composedColor >> 24) & 0xFF) * 1.0 / 255.0;
71         double r = ((composedColor >> 16) & 0xFF) * 1.0 / 255.0;
72         double g = ((composedColor >> 8) & 0xFF) * 1.0 / 255.0;
73         double b = ((composedColor >> 0) & 0xFF) * 1.0 / 255.0;
74
75         cairo_set_source_rgba(pCairo, r, g, b, a);
76 }
77
78 template <>
79 void
80 SetClip<int>(cairo_t* pCairo, int x, int y, int width, int height)
81 {
82         cairo_new_path(pCairo);
83         cairo_rectangle(pCairo, x, y, width, height);
84         cairo_clip(pCairo);
85         cairo_new_path(pCairo);
86 }
87
88 template <>
89 void
90 SetClip<float>(cairo_t* pCairo, float x, float y, float width, float height)
91 {
92
93         cairo_new_path(pCairo);
94         cairo_rectangle(pCairo, x, y, width, height);
95         cairo_clip(pCairo);
96         cairo_new_path(pCairo);
97 }
98
99 void
100 ResetClip(cairo_t* pCairo)
101 {
102         cairo_reset_clip(pCairo);
103 }
104
105 void
106 SetDash(cairo_t* pCairo, double* pDashes, int dashCount, double offset)
107 {
108         double sum = 0.0;
109
110         for (int i = 0; i < dashCount; i++)
111         {
112                 sum += pDashes[i];
113         }
114
115         if (sum == 0.0 && dashCount > 0)
116         {
117                 // used the maximum value of integer type instead of double type(1.79769e+308).
118                 const double infiniteValue = double(2147483647);
119                 const double zeroDashes[2] = { 0.0, infiniteValue };
120
121                 cairo_set_dash(pCairo, zeroDashes, 2, offset);
122         }
123         else
124         {
125                 cairo_set_dash(pCairo, pDashes, dashCount, offset);
126         }
127 }
128
129 void
130 ResetDash(cairo_t* pCairo)
131 {
132         cairo_set_dash(pCairo, 0, 0, 0.0);
133 }
134
135 void
136 SetComposite(cairo_t* pCairo, cairo_operator_t op)
137 {
138         cairo_set_operator(pCairo, op);
139 }
140
141 void
142 ResetComposite(cairo_t* pCairo)
143 {
144         cairo_set_operator(pCairo, CAIRO_OPERATOR_OVER);
145 }
146
147 void
148 SetLineCap(cairo_t* pCairo, cairo_line_cap_t cap)
149 {
150         cairo_set_line_cap(pCairo, cap);
151 }
152
153 void
154 ResetLineCap(cairo_t* pCairo)
155 {
156         cairo_set_line_cap(pCairo, CAIRO_LINE_CAP_ROUND);
157 }
158
159 void
160 SetLineJoin(cairo_t* pCairo, cairo_line_join_t join)
161 {
162         cairo_set_line_join(pCairo, join);
163 }
164
165 void
166 ResetLineJoin(cairo_t* pCairo)
167 {
168         cairo_set_line_join(pCairo, CAIRO_LINE_JOIN_ROUND);
169 }
170
171 template <>
172 void
173 DrawRoundRectangle<double>(cairo_t* pCairo, double lineWidth, unsigned long composedColor, const _Util::Rectangle<double>& rect, const _Util::Dimension<double>& arcDim)
174 {
175         double x = rect.x;
176         double y = rect.y;
177         double width = rect.w;
178         double height = rect.h;
179         double radiusHorizontal = arcDim.w;
180         double radiusVertical = arcDim.h;
181         double radius = (radiusHorizontal > radiusVertical) ? radiusHorizontal :  radiusVertical;
182         double scalingFactorHorizental = radius / radiusHorizontal;
183         double scalingFactorVertical = radius / radiusVertical;
184         double degrees = _DOUBLE_PI / 180.0;
185
186         cairo_save(pCairo);
187         cairo_scale(pCairo, radiusHorizontal / radius, radiusVertical / radius);
188         cairo_new_sub_path(pCairo);
189
190         cairo_arc_negative(pCairo, (x + width - radiusHorizontal) * scalingFactorHorizental, (y + radiusVertical) * scalingFactorVertical, radius, 0 * degrees, -90 * degrees);
191         cairo_arc_negative(pCairo, (x + radiusHorizontal) * scalingFactorHorizental, (y + radiusVertical) * scalingFactorVertical, radius, -90 * degrees, -180 * degrees);
192         cairo_arc_negative(pCairo, (x + radiusHorizontal) * scalingFactorHorizental, (y + height - radiusVertical) * scalingFactorVertical, radius, -180 * degrees, -270 * degrees);
193         cairo_arc_negative(pCairo, (x + width - radiusHorizontal) * scalingFactorHorizental, (y + height - radiusVertical) * scalingFactorVertical, radius, -270 * degrees, -360 * degrees);
194
195         cairo_close_path(pCairo);
196         cairo_restore(pCairo);
197
198         SetColor(pCairo, composedColor);
199
200         cairo_set_line_width(pCairo, lineWidth);
201         cairo_stroke(pCairo);
202 }
203
204 template <>
205 void
206 DrawRoundRectangle<int>(cairo_t* pCairo, int lineWidth, unsigned long composedColor, const _Util::Rectangle<double>& rect, const _Util::Dimension<double>& arcDim)
207 {
208         double offset = (lineWidth % 2) ? 0.5 : 0.0;
209
210         _Util::Rectangle<double> revisedRect =
211         {
212                 rect.x + offset,
213                 rect.y + offset,
214                 rect.w,
215                 rect.h
216         };
217
218         DrawRoundRectangle<double>(pCairo, double(lineWidth), composedColor, revisedRect, arcDim);
219 }
220
221 void
222 FillRoundRectangle(cairo_t* pCairo, unsigned long composedColor, const _Util::Rectangle<double>& rect, const _Util::Dimension<double>& arcDim)
223 {
224         double x = rect.x;
225         double y = rect.y;
226         double width = rect.w;
227         double height = rect.h;
228         double radiusHorizontal = arcDim.w;
229         double radiusVertical = arcDim.h;
230         double radius = (radiusHorizontal > radiusVertical) ? radiusHorizontal :  radiusVertical;
231         double degrees = _DOUBLE_PI / 180.0;
232         double scalingFactorHorizental = radius / radiusHorizontal;
233         double scalingFactorVertical = radius / radiusVertical;
234
235         cairo_save(pCairo);
236         cairo_scale(pCairo, radiusHorizontal / radius, radiusVertical / radius);
237         cairo_new_sub_path(pCairo);
238         cairo_arc(pCairo, (x + width - radiusHorizontal) * scalingFactorHorizental, (y + radiusVertical) * scalingFactorVertical, radius, -90 * degrees, 0 * degrees);
239         cairo_arc(pCairo, (x + width - radiusHorizontal) * scalingFactorHorizental, (y + height - radiusVertical) * scalingFactorVertical, radius, 0 * degrees, 90 * degrees);
240         cairo_arc(pCairo, (x + radiusHorizontal) * scalingFactorHorizental, (y + height - radiusVertical) * scalingFactorVertical, radius, 90 * degrees, 180 * degrees);
241         cairo_arc(pCairo, (x + radiusHorizontal) * scalingFactorHorizental, (y + radiusVertical) * scalingFactorVertical, radius, 180 * degrees, 270 * degrees);
242         cairo_close_path(pCairo);
243         cairo_restore(pCairo);
244
245         SetColor(pCairo, composedColor);
246
247         cairo_fill(pCairo);
248 }
249
250 template <>
251 void
252 Drawline<double>(cairo_t* pCairo, double lineWidth, unsigned long composedColor, const _Util::Point<double> point[], int numPoint)
253 {
254         if (numPoint != 2)
255         {
256                 return;
257         }
258
259         {
260                 cairo_new_path(pCairo);
261                 cairo_move_to(pCairo, point[0].x, point[0].y);
262
263                 for (int i = 1; i < numPoint; i++)
264                 {
265                         cairo_line_to(pCairo, point[i].x, point[i].y);
266                 }
267         }
268
269         SetColor(pCairo, composedColor);
270
271         cairo_set_line_width(pCairo, lineWidth);
272
273         cairo_stroke(pCairo);
274 }
275
276 template <>
277 void
278 Drawline<int>(cairo_t* pCairo, int lineWidth, unsigned long composedColor, const _Util::Point<double> point[], int numPoint)
279 {
280         if (numPoint != 2)
281         {
282                 return;
283         }
284
285         double offset = (lineWidth % 2) ? 0.5 : 0.0;
286
287         {
288                 cairo_new_path(pCairo);
289                 cairo_move_to(pCairo, point[0].x + offset, point[0].y + offset);
290
291                 for (int i = 1; i < numPoint; i++)
292                 {
293                         cairo_line_to(pCairo, point[i].x + offset, point[i].y + offset);
294                 }
295         }
296
297         SetColor(pCairo, composedColor);
298
299         cairo_set_line_width(pCairo, lineWidth);
300
301         cairo_stroke(pCairo);
302 }
303
304 void
305 FillRectangle(cairo_t* pCairo, unsigned long composedColor, const _Util::Rectangle<double>& rect)
306 {
307         cairo_rectangle(pCairo, rect.x, rect.y, rect.w, rect.h);
308         SetColor(pCairo, composedColor);
309         cairo_fill(pCairo);
310 }
311
312 template <>
313 void
314 DrawRectangle<double>(cairo_t* pCairo, double lineWidth, unsigned long composedColor, const _Util::Rectangle<double>& rect)
315 {
316         double x1 = rect.x;
317         double y1 = rect.y;
318         double x2 = x1 + rect.w;
319         double y2 = y1 + rect.h;
320
321         {
322                 cairo_new_path(pCairo);
323
324                 cairo_move_to(pCairo, x1, y1);
325                 cairo_line_to(pCairo, x2, y1);
326                 cairo_line_to(pCairo, x2, y2);
327                 cairo_line_to(pCairo, x1, y2);
328
329                 cairo_close_path(pCairo);
330         }
331
332         SetColor(pCairo, composedColor);
333
334         cairo_set_line_width(pCairo, lineWidth);
335
336         cairo_stroke(pCairo);
337 }
338
339 template <>
340 void
341 DrawRectangle<int>(cairo_t* pCairo, int lineWidth, unsigned long composedColor, const _Util::Rectangle<double>& rect)
342 {
343         double offset = (lineWidth % 2) ? 0.5 : 0.0;
344
345         _Util::Rectangle<double> revisedRect = { rect.x + offset, rect.y + offset, rect.w, rect.h };
346
347         DrawRectangle<double>(pCairo, double(lineWidth), composedColor, revisedRect);
348 }
349
350 template <>
351 void
352 DrawPolyline<double>(cairo_t* pCairo, double lineWidth, unsigned long composedColor, const _Util::Point<double> point[], int numPoint)
353 {
354         if (numPoint <= 0)
355         {
356                 return;
357         }
358
359         {
360                 cairo_new_path(pCairo);
361                 cairo_move_to(pCairo, point[0].x, point[0].y );
362
363                 for (int i = 1; i < numPoint; i++)
364                 {
365                         cairo_line_to(pCairo, point[i].x, point[i].y);
366                 }
367         }
368
369         SetColor(pCairo, composedColor);
370
371         cairo_set_line_width(pCairo, lineWidth);
372
373         cairo_stroke(pCairo);
374 }
375
376 template <>
377 void
378 DrawPolyline<int>(cairo_t* pCairo, int lineWidth, unsigned long composedColor, const _Util::Point<double> point[], int numPoint)
379 {
380         if (numPoint <= 0)
381         {
382                 return;
383         }
384
385         {
386                 double offset = (lineWidth % 2) ? 0.5 : 0.0;
387
388                 cairo_new_path(pCairo);
389                 cairo_move_to(pCairo, point[0].x + offset, point[0].y + offset);
390
391                 for (int i = 1; i < numPoint; i++)
392                 {
393                         cairo_line_to(pCairo, point[i].x + offset, point[i].y + offset);
394                 }
395         }
396
397         SetColor(pCairo, composedColor);
398
399         cairo_set_line_width(pCairo, lineWidth);
400
401         cairo_stroke(pCairo);
402 }
403
404 template <>
405 void
406 DrawPolygon<double>(cairo_t* pCairo, double lineWidth, unsigned long composedColor, const _Util::Point<double> point[], int numPoint)
407 {
408         if (numPoint <= 0)
409         {
410                 return;
411         }
412
413         {
414                 cairo_new_path(pCairo);
415                 cairo_move_to(pCairo, point[0].x, point[0].y);
416
417                 for (int i = 1; i < numPoint; i++)
418                 {
419                         cairo_line_to(pCairo, point[i].x, point[i].y);
420                 }
421
422                 cairo_close_path(pCairo);
423         }
424
425         SetColor(pCairo, composedColor);
426
427         cairo_set_line_width(pCairo, lineWidth);
428
429         cairo_stroke(pCairo);
430 }
431
432 template <>
433 void
434 DrawPolygon<int>(cairo_t* pCairo, int lineWidth, unsigned long composedColor, const _Util::Point<double> point[], int numPoint)
435 {
436         if (numPoint <= 0)
437         {
438                 return;
439         }
440
441         {
442                 double offset = (lineWidth % 2) ? 0.5 : 0.0;
443
444                 cairo_new_path(pCairo);
445                 cairo_move_to(pCairo, point[0].x + offset, point[0].y + offset);
446
447                 for (int i = 1; i < numPoint; i++)
448                 {
449                         cairo_line_to(pCairo, point[i].x + offset, point[i].y + offset);
450                 }
451
452                 cairo_close_path(pCairo);
453         }
454
455         SetColor(pCairo, composedColor);
456
457         cairo_set_line_width(pCairo, lineWidth);
458
459         cairo_stroke(pCairo);
460 }
461
462 void
463 FillPolygon(cairo_t* pCairo, unsigned long composedColor, const _Util::Point<double> point[], int numPoint)
464 {
465         if (numPoint <= 0)
466         {
467                 return;
468         }
469
470         {
471                 cairo_new_path(pCairo);
472                 cairo_move_to(pCairo, point[0].x, point[0].y);
473
474                 for (int i = 1; i < numPoint; i++)
475                 {
476                         cairo_line_to(pCairo, point[i].x, point[i].y);
477                 }
478
479                 cairo_close_path(pCairo);
480         }
481
482         SetColor(pCairo, composedColor);
483
484         cairo_set_fill_rule(pCairo, CAIRO_FILL_RULE_EVEN_ODD);
485         cairo_fill(pCairo);
486 }
487
488 template <>
489 void
490 DrawEllipse<double>(cairo_t* pCairo, double lineWidth, unsigned long composedColor, const _Util::Rectangle<double>& bounds)
491 {
492         double x = bounds.x;
493         double y = bounds.y;
494         double widthHalf = bounds.w * 1.0 / 2.0;
495         double heightHalf = bounds.h * 1.0 / 2.0;
496
497         {
498                 double ux = lineWidth;
499                 double uy = lineWidth;
500                 cairo_device_to_user_distance(pCairo, &ux, &uy);
501                 cairo_set_line_width(pCairo, (ux < uy) ? uy : ux);
502         }
503
504         SetColor(pCairo, composedColor);
505
506         cairo_new_path(pCairo);
507
508         cairo_save(pCairo);
509         {
510                 cairo_translate(pCairo, x + widthHalf, y + heightHalf);
511
512                 double radius = (widthHalf > heightHalf) ? widthHalf : heightHalf;
513
514                 cairo_scale(pCairo, widthHalf / radius, heightHalf / radius);
515
516                 cairo_arc_negative(pCairo, 0.0, 0.0, radius, 0.0, -2 * _DOUBLE_PI);
517         }
518         cairo_restore(pCairo);
519
520         cairo_stroke(pCairo);
521 }
522
523 template <>
524 void
525 DrawEllipse<int>(cairo_t* pCairo, int lineWidth, unsigned long composedColor, const _Util::Rectangle<double>& bounds)
526 {
527         double offset = (lineWidth % 2) ? 0.5f : 0.0f;
528
529         _Util::Rectangle<double> revisedBounds =
530         {
531                 bounds.x + offset,
532                 bounds.y + offset,
533                 bounds.w,
534                 bounds.h
535         };
536
537         DrawEllipse<double>(pCairo, double(lineWidth), composedColor, revisedBounds);
538 }
539
540 void
541 FillEllipse(cairo_t* pCairo, unsigned long composedColor, const _Util::Rectangle<double>& bounds)
542 {
543         double x = bounds.x;
544         double y = bounds.y;
545         double width = bounds.w;
546         double height = bounds.h;
547
548         cairo_new_path(pCairo);
549
550         cairo_save(pCairo);
551         {
552                 cairo_translate(pCairo, x + width / 2.0, y + height / 2.0);
553                 cairo_scale(pCairo, width / 2.0, height / 2.0);
554
555                 double a = ((composedColor >> 24) & 0xFF) * 1.0 / 255.0;
556                 double r = ((composedColor >> 16) & 0xFF) * 1.0 / 255.0;
557                 double g = ((composedColor >> 8) & 0xFF) * 1.0 / 255.0;
558                 double b = ((composedColor >> 0) & 0xFF) * 1.0 / 255.0;
559
560                 cairo_set_source_rgba(pCairo, r, g, b, a);
561
562                 cairo_arc(pCairo, 0.0, 0.0, 1.0, 0.0, 2 * _DOUBLE_PI);
563                 cairo_fill(pCairo);
564         }
565         cairo_restore(pCairo);
566 }
567
568 template <>
569 void
570 DrawArc<double>(cairo_t* pCairo, double lineWidth, unsigned long composedColor, const _Util::Rectangle<double>& bounds, double startAngle, double endAngle, DrawArcStyle arcType)
571 {
572         double x = bounds.x;
573         double y = bounds.y;
574         double widthHalf = bounds.w * 1.0 / 2.0;
575         double heightHalf = bounds.h * 1.0 / 2.0;
576         double angle1 = (360 - startAngle) * 1.0 * (_DOUBLE_PI / 180.0);
577         double angle2 = (360 - endAngle) * 1.0 * (_DOUBLE_PI / 180.0);
578
579         {
580                 double ux = lineWidth;
581                 double uy = lineWidth;
582                 cairo_device_to_user_distance(pCairo, &ux, &uy);
583                 cairo_set_line_width(pCairo, (ux < uy) ? uy : ux);
584         }
585
586         SetColor(pCairo, composedColor);
587
588         cairo_new_path(pCairo);
589
590         switch (arcType)
591         {
592         case DRAW_ARC_STYLE_ARC:
593                 cairo_save(pCairo);
594                 {
595                         cairo_translate(pCairo, x + widthHalf, y + heightHalf);
596
597                         double radius = (widthHalf > heightHalf) ? widthHalf : heightHalf;
598
599                         cairo_scale(pCairo, widthHalf / radius, heightHalf / radius);
600
601                         cairo_arc_negative(pCairo, 0.0, 0.0, radius, angle1, angle2);
602                 }
603                 cairo_restore(pCairo);
604                 break;
605         case DRAW_ARC_STYLE_PIE:
606                 cairo_save(pCairo);
607                 {
608                         cairo_translate(pCairo, x + widthHalf, y + heightHalf);
609
610                         double radius = (widthHalf > heightHalf) ? widthHalf : heightHalf;
611
612                         cairo_scale(pCairo, widthHalf / radius, heightHalf / radius);
613
614                         cairo_arc_negative(pCairo, 0.0, 0.0, radius, angle1, angle2);
615                         cairo_line_to(pCairo, 0.5, 0.5);
616                         cairo_close_path(pCairo);
617                 }
618                 cairo_restore(pCairo);
619                 break;
620         case DRAW_ARC_STYLE_CHORD:
621                 cairo_save(pCairo);
622                 {
623                         cairo_translate(pCairo, x + widthHalf, y + heightHalf);
624
625                         double radius = (widthHalf > heightHalf) ? widthHalf : heightHalf;
626
627                         cairo_scale(pCairo, widthHalf / radius, heightHalf / radius);
628
629                         cairo_arc_negative(pCairo, 0.0, 0.0, radius, angle1, angle2);
630                         cairo_close_path(pCairo);
631                 }
632                 cairo_restore(pCairo);
633                 break;
634         default:
635                 return;
636         }
637
638         cairo_stroke(pCairo);
639 }
640
641 template <>
642 void
643 DrawArc<int>(cairo_t* pCairo, int lineWidth, unsigned long composedColor, const _Util::Rectangle<double>& bounds, double startAngle, double endAngle, DrawArcStyle arcType)
644 {
645         float offset = (lineWidth % 2) ? 0.5f : 0.0f;
646
647         _Util::Rectangle<double> revisedBounds =
648         {
649                 bounds.x + offset,
650                 bounds.y + offset,
651                 bounds.w,
652                 bounds.h
653         };
654
655         DrawArc<double>(pCairo, double(lineWidth), composedColor, revisedBounds, startAngle, endAngle, arcType);
656 }
657
658 void
659 FillArc(cairo_t* pCairo, unsigned long composedColor, const _Util::Rectangle<double>& bounds, double startAngle, double endAngle, FillArcStyle arcType)
660 {
661         double x = bounds.x;
662         double y = bounds.y;
663         double widthHalf = bounds.w * 1.0 / 2.0;
664         double heightHalf = bounds.h * 1.0 / 2.0;
665         double angle1 = (360 - startAngle) * 1.0 * (_DOUBLE_PI / 180.0);
666         double angle2 = (360 - endAngle) * 1.0 * (_DOUBLE_PI / 180.0);
667
668         SetColor(pCairo, composedColor);
669
670         cairo_new_path(pCairo);
671
672         switch (arcType)
673         {
674         case FILL_ARC_STYLE_PIE:
675                 cairo_save(pCairo);
676                 {
677                         cairo_translate(pCairo, x + widthHalf, y + heightHalf);
678
679                         double radius = (widthHalf > heightHalf) ? widthHalf : heightHalf;
680
681                         cairo_scale(pCairo, widthHalf / radius, heightHalf / radius);
682
683                         cairo_arc_negative(pCairo, 0.0, 0.0, radius, angle1, angle2);
684                         cairo_line_to(pCairo, 0.5, 0.5);
685                         cairo_close_path(pCairo);
686                 }
687                 cairo_restore(pCairo);
688                 break;
689         case FILL_ARC_STYLE_CHORD:
690                 cairo_save(pCairo);
691                 {
692                         cairo_translate(pCairo, x + widthHalf, y + heightHalf);
693
694                         double radius = (widthHalf > heightHalf) ? widthHalf : heightHalf;
695
696                         cairo_scale(pCairo, widthHalf / radius, heightHalf / radius);
697
698                         cairo_arc_negative(pCairo, 0.0, 0.0, radius, angle1, angle2);
699                         cairo_close_path(pCairo);
700                 }
701                 cairo_restore(pCairo);
702                 break;
703         default:
704                 return;
705         }
706
707         cairo_fill(pCairo);
708 }
709
710 bool
711 ScalePixmap(Tizen::Graphics::_Util::Pixmap& dstImage, const Tizen::Graphics::_Util::Pixmap& srcImage, PatternFilter patternFilter)
712 {
713         if (srcImage.width <= 0 || srcImage.height <= 0 || dstImage.width <= 0 || dstImage.height <= 0)
714         {
715                 return true;
716         }
717
718         if (srcImage.depth != 32 || dstImage.depth != 32)
719         {
720                 return false;
721         }
722
723         _Util::AutoDeletor<cairo_surface_t> srcSurface(cairo_image_surface_create_for_data((unsigned char*)srcImage.pBitmap, CAIRO_FORMAT_ARGB32, srcImage.width, srcImage.height, srcImage.bytesPerLine));
724         _Util::AutoDeletor<cairo_surface_t> dstSurface(cairo_image_surface_create_for_data((unsigned char*)dstImage.pBitmap, CAIRO_FORMAT_ARGB32, dstImage.width, dstImage.height, dstImage.bytesPerLine));
725
726         if (srcSurface.IsValid() && dstSurface.IsValid())
727         {
728                 _Util::AutoDeletor<cairo_pattern_t> srcPattern(cairo_pattern_create_for_surface(srcSurface));
729                 _Util::AutoDeletor<cairo_t> dstCairo(cairo_create(dstSurface));
730
731                 if (srcPattern.IsValid() && dstCairo.IsValid())
732                 {
733                         cairo_matrix_t cairoMatrix;
734                         cairo_matrix_init_scale(&cairoMatrix, double(srcImage.width) / double(dstImage.width), double(srcImage.height) / double(dstImage.height));
735                         cairo_pattern_set_matrix(srcPattern, &cairoMatrix);
736
737                         switch (patternFilter)
738                         {
739                         case PATTERN_FILTER_FAST:
740                                 cairo_pattern_set_filter(srcPattern, CAIRO_FILTER_FAST);
741                                 break;
742                         case PATTERN_FILTER_GOOD:
743                                 cairo_pattern_set_filter(srcPattern, CAIRO_FILTER_GOOD);
744                                 break;
745                         case PATTERN_FILTER_BEST:
746                                 cairo_pattern_set_filter(srcPattern, CAIRO_FILTER_BEST);
747                                 break;
748                         default:
749                                 cairo_pattern_set_filter(srcPattern, CAIRO_FILTER_FAST);
750                                 break;
751                         };
752
753                         cairo_set_source(dstCairo, srcPattern);
754                         cairo_paint(dstCairo);
755
756                         return true;
757                 }
758         }
759
760         return false;
761 }
762
763 } // _Cairo
764
765 }} // Tizen::Graphics