2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
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
9 // http://www.apache.org/licenses/LICENSE-2.0/
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.
19 * @file FGrp_CanvasCairo.cpp
20 * @brief This is the implementation file for the cairo solution.
24 #include "FGrp_CanvasCairo.h"
25 #include "util/FGrp_UtilTemplate.h"
27 namespace Tizen { namespace Graphics
34 AutoDeletor<cairo_t>::~AutoDeletor(void)
38 cairo_destroy(__pPtr);
43 AutoDeletor<cairo_surface_t>::~AutoDeletor(void)
47 cairo_surface_destroy(__pPtr);
52 AutoDeletor<cairo_pattern_t>::~AutoDeletor(void)
56 cairo_pattern_destroy(__pPtr);
65 const double _DOUBLE_PI = 3.141592;
68 SetColor(cairo_t* pCairo, unsigned long composedColor)
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;
75 cairo_set_source_rgba(pCairo, r, g, b, a);
80 SetClip<int>(cairo_t* pCairo, int x, int y, int width, int height)
82 cairo_new_path(pCairo);
83 cairo_rectangle(pCairo, x, y, width, height);
85 cairo_new_path(pCairo);
90 SetClip<float>(cairo_t* pCairo, float x, float y, float width, float height)
93 cairo_new_path(pCairo);
94 cairo_rectangle(pCairo, x, y, width, height);
96 cairo_new_path(pCairo);
100 ResetClip(cairo_t* pCairo)
102 cairo_reset_clip(pCairo);
106 SetDash(cairo_t* pCairo, double* pDashes, int dashCount, double offset)
110 for (int i = 0; i < dashCount; i++)
115 if (sum == 0.0 && dashCount > 0)
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 };
121 cairo_set_dash(pCairo, zeroDashes, 2, offset);
125 cairo_set_dash(pCairo, pDashes, dashCount, offset);
130 ResetDash(cairo_t* pCairo)
132 cairo_set_dash(pCairo, 0, 0, 0.0);
136 SetComposite(cairo_t* pCairo, cairo_operator_t op)
138 cairo_set_operator(pCairo, op);
142 ResetComposite(cairo_t* pCairo)
144 cairo_set_operator(pCairo, CAIRO_OPERATOR_OVER);
148 SetLineCap(cairo_t* pCairo, cairo_line_cap_t cap)
150 cairo_set_line_cap(pCairo, cap);
154 ResetLineCap(cairo_t* pCairo)
156 cairo_set_line_cap(pCairo, CAIRO_LINE_CAP_ROUND);
160 SetLineJoin(cairo_t* pCairo, cairo_line_join_t join)
162 cairo_set_line_join(pCairo, join);
166 ResetLineJoin(cairo_t* pCairo)
168 cairo_set_line_join(pCairo, CAIRO_LINE_JOIN_ROUND);
173 DrawRoundRectangle<double>(cairo_t* pCairo, double lineWidth, unsigned long composedColor, const _Util::Rectangle<double>& rect, const _Util::Dimension<double>& arcDim)
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;
187 cairo_scale(pCairo, radiusHorizontal / radius, radiusVertical / radius);
188 cairo_new_sub_path(pCairo);
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);
195 cairo_close_path(pCairo);
196 cairo_restore(pCairo);
198 SetColor(pCairo, composedColor);
200 cairo_set_line_width(pCairo, lineWidth);
201 cairo_stroke(pCairo);
206 DrawRoundRectangle<int>(cairo_t* pCairo, int lineWidth, unsigned long composedColor, const _Util::Rectangle<double>& rect, const _Util::Dimension<double>& arcDim)
208 double offset = (lineWidth % 2) ? 0.5 : 0.0;
210 _Util::Rectangle<double> revisedRect =
218 DrawRoundRectangle<double>(pCairo, double(lineWidth), composedColor, revisedRect, arcDim);
222 FillRoundRectangle(cairo_t* pCairo, unsigned long composedColor, const _Util::Rectangle<double>& rect, const _Util::Dimension<double>& arcDim)
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;
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);
245 SetColor(pCairo, composedColor);
252 Drawline<double>(cairo_t* pCairo, double lineWidth, unsigned long composedColor, const _Util::Point<double> point[], int numPoint)
260 cairo_new_path(pCairo);
261 cairo_move_to(pCairo, point[0].x, point[0].y);
263 for (int i = 1; i < numPoint; i++)
265 cairo_line_to(pCairo, point[i].x, point[i].y);
269 SetColor(pCairo, composedColor);
271 cairo_set_line_width(pCairo, lineWidth);
273 cairo_stroke(pCairo);
278 Drawline<int>(cairo_t* pCairo, int lineWidth, unsigned long composedColor, const _Util::Point<double> point[], int numPoint)
285 double offset = (lineWidth % 2) ? 0.5 : 0.0;
288 cairo_new_path(pCairo);
289 cairo_move_to(pCairo, point[0].x + offset, point[0].y + offset);
291 for (int i = 1; i < numPoint; i++)
293 cairo_line_to(pCairo, point[i].x + offset, point[i].y + offset);
297 SetColor(pCairo, composedColor);
299 cairo_set_line_width(pCairo, lineWidth);
301 cairo_stroke(pCairo);
305 FillRectangle(cairo_t* pCairo, unsigned long composedColor, const _Util::Rectangle<double>& rect)
307 cairo_rectangle(pCairo, rect.x, rect.y, rect.w, rect.h);
308 SetColor(pCairo, composedColor);
314 DrawRectangle<double>(cairo_t* pCairo, double lineWidth, unsigned long composedColor, const _Util::Rectangle<double>& rect)
318 double x2 = x1 + rect.w;
319 double y2 = y1 + rect.h;
322 cairo_new_path(pCairo);
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);
329 cairo_close_path(pCairo);
332 SetColor(pCairo, composedColor);
334 cairo_set_line_width(pCairo, lineWidth);
336 cairo_stroke(pCairo);
341 DrawRectangle<int>(cairo_t* pCairo, int lineWidth, unsigned long composedColor, const _Util::Rectangle<double>& rect)
343 double offset = (lineWidth % 2) ? 0.5 : 0.0;
345 _Util::Rectangle<double> revisedRect = { rect.x + offset, rect.y + offset, rect.w, rect.h };
347 DrawRectangle<double>(pCairo, double(lineWidth), composedColor, revisedRect);
352 DrawPolyline<double>(cairo_t* pCairo, double lineWidth, unsigned long composedColor, const _Util::Point<double> point[], int numPoint)
360 cairo_new_path(pCairo);
361 cairo_move_to(pCairo, point[0].x, point[0].y );
363 for (int i = 1; i < numPoint; i++)
365 cairo_line_to(pCairo, point[i].x, point[i].y);
369 SetColor(pCairo, composedColor);
371 cairo_set_line_width(pCairo, lineWidth);
373 cairo_stroke(pCairo);
378 DrawPolyline<int>(cairo_t* pCairo, int lineWidth, unsigned long composedColor, const _Util::Point<double> point[], int numPoint)
386 double offset = (lineWidth % 2) ? 0.5 : 0.0;
388 cairo_new_path(pCairo);
389 cairo_move_to(pCairo, point[0].x + offset, point[0].y + offset);
391 for (int i = 1; i < numPoint; i++)
393 cairo_line_to(pCairo, point[i].x + offset, point[i].y + offset);
397 SetColor(pCairo, composedColor);
399 cairo_set_line_width(pCairo, lineWidth);
401 cairo_stroke(pCairo);
406 DrawPolygon<double>(cairo_t* pCairo, double lineWidth, unsigned long composedColor, const _Util::Point<double> point[], int numPoint)
414 cairo_new_path(pCairo);
415 cairo_move_to(pCairo, point[0].x, point[0].y);
417 for (int i = 1; i < numPoint; i++)
419 cairo_line_to(pCairo, point[i].x, point[i].y);
422 cairo_close_path(pCairo);
425 SetColor(pCairo, composedColor);
427 cairo_set_line_width(pCairo, lineWidth);
429 cairo_stroke(pCairo);
434 DrawPolygon<int>(cairo_t* pCairo, int lineWidth, unsigned long composedColor, const _Util::Point<double> point[], int numPoint)
442 double offset = (lineWidth % 2) ? 0.5 : 0.0;
444 cairo_new_path(pCairo);
445 cairo_move_to(pCairo, point[0].x + offset, point[0].y + offset);
447 for (int i = 1; i < numPoint; i++)
449 cairo_line_to(pCairo, point[i].x + offset, point[i].y + offset);
452 cairo_close_path(pCairo);
455 SetColor(pCairo, composedColor);
457 cairo_set_line_width(pCairo, lineWidth);
459 cairo_stroke(pCairo);
463 FillPolygon(cairo_t* pCairo, unsigned long composedColor, const _Util::Point<double> point[], int numPoint)
471 cairo_new_path(pCairo);
472 cairo_move_to(pCairo, point[0].x, point[0].y);
474 for (int i = 1; i < numPoint; i++)
476 cairo_line_to(pCairo, point[i].x, point[i].y);
479 cairo_close_path(pCairo);
482 SetColor(pCairo, composedColor);
484 cairo_set_fill_rule(pCairo, CAIRO_FILL_RULE_EVEN_ODD);
490 DrawEllipse<double>(cairo_t* pCairo, double lineWidth, unsigned long composedColor, const _Util::Rectangle<double>& bounds)
494 double widthHalf = bounds.w * 1.0 / 2.0;
495 double heightHalf = bounds.h * 1.0 / 2.0;
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);
504 SetColor(pCairo, composedColor);
506 cairo_new_path(pCairo);
510 cairo_translate(pCairo, x + widthHalf, y + heightHalf);
512 double radius = (widthHalf > heightHalf) ? widthHalf : heightHalf;
514 cairo_scale(pCairo, widthHalf / radius, heightHalf / radius);
516 cairo_arc_negative(pCairo, 0.0, 0.0, radius, 0.0, -2 * _DOUBLE_PI);
518 cairo_restore(pCairo);
520 cairo_stroke(pCairo);
525 DrawEllipse<int>(cairo_t* pCairo, int lineWidth, unsigned long composedColor, const _Util::Rectangle<double>& bounds)
527 double offset = (lineWidth % 2) ? 0.5f : 0.0f;
529 _Util::Rectangle<double> revisedBounds =
537 DrawEllipse<double>(pCairo, double(lineWidth), composedColor, revisedBounds);
541 FillEllipse(cairo_t* pCairo, unsigned long composedColor, const _Util::Rectangle<double>& bounds)
545 double width = bounds.w;
546 double height = bounds.h;
548 cairo_new_path(pCairo);
552 cairo_translate(pCairo, x + width / 2.0, y + height / 2.0);
553 cairo_scale(pCairo, width / 2.0, height / 2.0);
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;
560 cairo_set_source_rgba(pCairo, r, g, b, a);
562 cairo_arc(pCairo, 0.0, 0.0, 1.0, 0.0, 2 * _DOUBLE_PI);
565 cairo_restore(pCairo);
570 DrawArc<double>(cairo_t* pCairo, double lineWidth, unsigned long composedColor, const _Util::Rectangle<double>& bounds, double startAngle, double endAngle, DrawArcStyle arcType)
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);
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);
586 SetColor(pCairo, composedColor);
588 cairo_new_path(pCairo);
592 case DRAW_ARC_STYLE_ARC:
595 cairo_translate(pCairo, x + widthHalf, y + heightHalf);
597 double radius = (widthHalf > heightHalf) ? widthHalf : heightHalf;
599 cairo_scale(pCairo, widthHalf / radius, heightHalf / radius);
601 cairo_arc_negative(pCairo, 0.0, 0.0, radius, angle1, angle2);
603 cairo_restore(pCairo);
605 case DRAW_ARC_STYLE_PIE:
608 cairo_translate(pCairo, x + widthHalf, y + heightHalf);
610 double radius = (widthHalf > heightHalf) ? widthHalf : heightHalf;
612 cairo_scale(pCairo, widthHalf / radius, heightHalf / radius);
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);
618 cairo_restore(pCairo);
620 case DRAW_ARC_STYLE_CHORD:
623 cairo_translate(pCairo, x + widthHalf, y + heightHalf);
625 double radius = (widthHalf > heightHalf) ? widthHalf : heightHalf;
627 cairo_scale(pCairo, widthHalf / radius, heightHalf / radius);
629 cairo_arc_negative(pCairo, 0.0, 0.0, radius, angle1, angle2);
630 cairo_close_path(pCairo);
632 cairo_restore(pCairo);
638 cairo_stroke(pCairo);
643 DrawArc<int>(cairo_t* pCairo, int lineWidth, unsigned long composedColor, const _Util::Rectangle<double>& bounds, double startAngle, double endAngle, DrawArcStyle arcType)
645 float offset = (lineWidth % 2) ? 0.5f : 0.0f;
647 _Util::Rectangle<double> revisedBounds =
655 DrawArc<double>(pCairo, double(lineWidth), composedColor, revisedBounds, startAngle, endAngle, arcType);
659 FillArc(cairo_t* pCairo, unsigned long composedColor, const _Util::Rectangle<double>& bounds, double startAngle, double endAngle, FillArcStyle arcType)
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);
668 SetColor(pCairo, composedColor);
670 cairo_new_path(pCairo);
674 case FILL_ARC_STYLE_PIE:
677 cairo_translate(pCairo, x + widthHalf, y + heightHalf);
679 double radius = (widthHalf > heightHalf) ? widthHalf : heightHalf;
681 cairo_scale(pCairo, widthHalf / radius, heightHalf / radius);
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);
687 cairo_restore(pCairo);
689 case FILL_ARC_STYLE_CHORD:
692 cairo_translate(pCairo, x + widthHalf, y + heightHalf);
694 double radius = (widthHalf > heightHalf) ? widthHalf : heightHalf;
696 cairo_scale(pCairo, widthHalf / radius, heightHalf / radius);
698 cairo_arc_negative(pCairo, 0.0, 0.0, radius, angle1, angle2);
699 cairo_close_path(pCairo);
701 cairo_restore(pCairo);
711 ScalePixmap(Tizen::Graphics::_Util::Pixmap& dstImage, const Tizen::Graphics::_Util::Pixmap& srcImage, PatternFilter patternFilter)
713 if (srcImage.width <= 0 || srcImage.height <= 0 || dstImage.width <= 0 || dstImage.height <= 0)
718 if (srcImage.depth != 32 || dstImage.depth != 32)
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));
726 if (srcSurface.IsValid() && dstSurface.IsValid())
728 _Util::AutoDeletor<cairo_pattern_t> srcPattern(cairo_pattern_create_for_surface(srcSurface));
729 _Util::AutoDeletor<cairo_t> dstCairo(cairo_create(dstSurface));
731 if (srcPattern.IsValid() && dstCairo.IsValid())
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);
737 switch (patternFilter)
739 case PATTERN_FILTER_FAST:
740 cairo_pattern_set_filter(srcPattern, CAIRO_FILTER_FAST);
742 case PATTERN_FILTER_GOOD:
743 cairo_pattern_set_filter(srcPattern, CAIRO_FILTER_GOOD);
745 case PATTERN_FILTER_BEST:
746 cairo_pattern_set_filter(srcPattern, CAIRO_FILTER_BEST);
749 cairo_pattern_set_filter(srcPattern, CAIRO_FILTER_FAST);
753 cairo_set_source(dstCairo, srcPattern);
754 cairo_paint(dstCairo);
765 }} // Tizen::Graphics