Tizen 2.1 base
[framework/osp/uifw.git] / src / graphics / FGrp_CanvasPixman.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_CanvasPixman.cpp
20  * @brief               This is the implementation file for the pixman solution.
21  *
22  */
23
24 #include <memory>
25
26 #include "FGrp_CanvasPixman.h"
27 #include "util/FGrp_UtilTemplate.h"
28
29
30 namespace Tizen { namespace Graphics
31 {
32
33 namespace _Util
34 {
35
36 template <>
37 AutoDeletor<pixman_image_t>::~AutoDeletor(void)
38 {
39         if (__pPtr)
40         {
41                 pixman_image_unref(__pPtr);
42         }
43 }
44
45 } // _Util
46
47 namespace _Pixman
48 {
49
50 pixman_op_t GetRop(Tizen::Graphics::BlendingMode blendingMode)
51 {
52         switch (blendingMode)
53         {
54         case BLENDING_MODE_CLEAR:
55                 return PIXMAN_OP_CLEAR;
56         case BLENDING_MODE_SRC:
57                 return PIXMAN_OP_SRC;
58         case BLENDING_MODE_DST:
59                 return PIXMAN_OP_DST;
60         case BLENDING_MODE_SRC_OVER:
61                 return PIXMAN_OP_OVER;
62         case BLENDING_MODE_DST_OVER:
63                 return PIXMAN_OP_OVER_REVERSE;
64         case BLENDING_MODE_SRC_IN:
65                 return PIXMAN_OP_IN;
66         case BLENDING_MODE_DST_IN:
67                 return PIXMAN_OP_IN_REVERSE;
68         case BLENDING_MODE_SRC_OUT:
69                 return PIXMAN_OP_OUT;
70         case BLENDING_MODE_DST_OUT:
71                 return PIXMAN_OP_OUT_REVERSE;
72         case BLENDING_MODE_SRC_ATOP:
73                 return PIXMAN_OP_ATOP;
74         case BLENDING_MODE_DST_ATOP:
75                 return PIXMAN_OP_ATOP_REVERSE;
76         case BLENDING_MODE_DST_XOR:
77                 return PIXMAN_OP_XOR;
78         case BLENDING_MODE_ADD:
79                 return PIXMAN_OP_ADD;
80         case BLENDING_MODE_SATURATE:
81                 return PIXMAN_OP_SATURATE;
82         case BLENDING_MODE_MULTIPLY:
83                 return PIXMAN_OP_MULTIPLY;
84         case BLENDING_MODE_SCREEN:
85                 return PIXMAN_OP_SCREEN;
86         case BLENDING_MODE_OVERLAY:
87                 return PIXMAN_OP_OVERLAY;
88         case BLENDING_MODE_DARKEN:
89                 return PIXMAN_OP_DARKEN;
90         case BLENDING_MODE_LIGHTEN:
91                 return PIXMAN_OP_LIGHTEN;
92         case BLENDING_MODE_COLOR_DODGE:
93                 return PIXMAN_OP_COLOR_DODGE;
94         case BLENDING_MODE_COLOR_BURN:
95                 return PIXMAN_OP_COLOR_BURN;
96         case BLENDING_MODE_HARD_LIGHT:
97                 return PIXMAN_OP_HARD_LIGHT;
98         case BLENDING_MODE_SOFT_LIGHT:
99                 return PIXMAN_OP_SOFT_LIGHT;
100         case BLENDING_MODE_DIFFERENCE:
101                 return PIXMAN_OP_DIFFERENCE;
102         case BLENDING_MODE_EXCLUSION:
103                 return PIXMAN_OP_EXCLUSION;
104         default:
105                 return PIXMAN_OP_SRC;
106         }
107 }
108
109 pixman_filter_t GetFilter(BitmapDrawingQuality drawingQuality)
110 {
111         switch (drawingQuality)
112         {
113         case Tizen::Graphics::BITMAP_DRAWING_QUALITY_HIGH:
114                 return PIXMAN_FILTER_BEST;
115         case Tizen::Graphics::BITMAP_DRAWING_QUALITY_MID:
116                 return PIXMAN_FILTER_GOOD;
117         default:
118                 return PIXMAN_FILTER_FAST;
119         }
120 }
121
122 pixman_filter_t GetFilter(BitmapScalingQuality scalingQuality)
123 {
124         switch (scalingQuality)
125         {
126         case Tizen::Graphics::BITMAP_SCALING_QUALITY_HIGH:
127                 return PIXMAN_FILTER_BEST;
128         case Tizen::Graphics::BITMAP_SCALING_QUALITY_MID:
129                 return PIXMAN_FILTER_GOOD;
130         default:
131                 return PIXMAN_FILTER_FAST;
132         }
133 }
134
135 pixman_transform_t GetTransform(int xDest, int yDest, double degree, int xPivot, int yPivot)
136 {
137         pixman_transform_t transform;
138
139         double c = cos(degree * 3.141592 / 180.0);
140         double s = sin(degree * 3.141592 / 180.0);
141
142         pixman_transform_init_identity(&transform);
143
144         pixman_transform_translate(&transform, NULL, pixman_int_to_fixed(-xDest), pixman_int_to_fixed(-yDest));
145         pixman_transform_rotate(&transform, NULL, pixman_double_to_fixed(c), pixman_double_to_fixed(s));
146         pixman_transform_translate(&transform, NULL, pixman_int_to_fixed(xPivot), pixman_int_to_fixed(yPivot));
147
148         return transform;
149 }
150
151 pixman_transform_t GetTransform(int srcWidth, int srcHeight, int dstWidth, int dstHeight)
152 {
153         pixman_transform_t transform;
154
155         pixman_transform_init_scale(&transform, 65536 * srcWidth / dstWidth,  65536 * srcHeight / dstHeight);
156
157         return transform;
158 }
159
160 bool ResizePixmap(Tizen::Graphics::_Util::Pixmap& dstImage, const Tizen::Graphics::_Util::Pixmap& srcImage, pixman_filter_t filter)
161 {
162         Tizen::Graphics::_Util::AutoDeletor<pixman_image_t> pPixmanDst;
163
164         switch (dstImage.depth)
165         {
166         case 16:
167                 pPixmanDst.Bind(pixman_image_create_bits(PIXMAN_r5g6b5, dstImage.width, dstImage.height, (uint32_t*)dstImage.pBitmap, dstImage.bytesPerLine));
168                 break;
169         case 32:
170                 pPixmanDst.Bind(pixman_image_create_bits(PIXMAN_a8r8g8b8, dstImage.width, dstImage.height, (uint32_t*)dstImage.pBitmap, dstImage.bytesPerLine));
171                 break;
172         default:
173                 return false;
174         }
175
176         if (pPixmanDst)
177         {
178                 Tizen::Graphics::_Util::AutoDeletor<pixman_image_t> pPixmanSrc;
179
180                 switch (srcImage.depth)
181                 {
182                 case 16:
183                         // color key is not supporting
184                         pPixmanSrc.Bind(pixman_image_create_bits(PIXMAN_r5g6b5, srcImage.width, srcImage.height, (uint32_t*)srcImage.pBitmap, srcImage.bytesPerLine));
185                         break;
186                 case 32:
187                         pPixmanSrc.Bind(pixman_image_create_bits(PIXMAN_a8r8g8b8, srcImage.width, srcImage.height, (uint32_t*)srcImage.pBitmap, srcImage.bytesPerLine));
188                         break;
189                 default:
190                         return false;
191                 }
192
193                 if (pPixmanSrc)
194                 {
195                         pixman_transform_t transform = Tizen::Graphics::_Pixman::GetTransform(srcImage.width, srcImage.height, dstImage.width, dstImage.height);
196
197                         pixman_image_set_transform(pPixmanSrc, &transform);
198
199                         pixman_image_set_filter(pPixmanSrc, filter, NULL, 0);
200
201                         pixman_image_composite32(PIXMAN_OP_SRC, pPixmanSrc, 0, pPixmanDst, 0, 0, 0, 0, 0, 0, dstImage.width, dstImage.height);
202
203                         return true;
204                 }
205         }
206
207         return false;
208 }
209
210 bool CompositePixmap(Tizen::Graphics::_Util::Pixmap& dstImage, const Tizen::Graphics::_Util::Pixmap& srcImage, pixman_op_t rop, pixman_filter_t filter, pixman_transform_t transform, pixman_repeat_t repeatMethod)
211 {
212         Tizen::Graphics::_Util::AutoDeletor<pixman_image_t> pPixmanDst;
213
214         switch (dstImage.depth)
215         {
216         case 16:
217                 pPixmanDst.Bind(pixman_image_create_bits(PIXMAN_r5g6b5, dstImage.width, dstImage.height, (uint32_t*)dstImage.pBitmap, dstImage.bytesPerLine));
218                 break;
219         case 32:
220                 pPixmanDst.Bind(pixman_image_create_bits(PIXMAN_a8r8g8b8, dstImage.width, dstImage.height, (uint32_t*)dstImage.pBitmap, dstImage.bytesPerLine));
221                 break;
222         default:
223                 return false;
224         }
225
226         if (pPixmanDst)
227         {
228                 std::auto_ptr<Tizen::Graphics::_Util::Pixmap> premultipliedSrcImage;
229
230                 Tizen::Graphics::_Util::AutoDeletor<pixman_image_t> pPixmanMsk;
231                 Tizen::Graphics::_Util::AutoDeletor<pixman_image_t> pPixmanSrc;
232
233                 switch (srcImage.depth)
234                 {
235                 case 16:
236                         // color key is not supporting
237                         pPixmanSrc.Bind(pixman_image_create_bits(PIXMAN_r5g6b5, srcImage.width, srcImage.height, (uint32_t*)srcImage.pBitmap, srcImage.bytesPerLine));
238                         break;
239                 case 32:
240                         if (srcImage.isPremultiplied || rop == PIXMAN_OP_SRC)
241                         {
242                                 pPixmanSrc.Bind(pixman_image_create_bits(PIXMAN_a8r8g8b8, srcImage.width, srcImage.height, (uint32_t*)srcImage.pBitmap, srcImage.bytesPerLine));
243                         }
244                         else
245                         {
246                                 premultipliedSrcImage.reset(srcImage.GetPremultipliedPixmap());
247
248                                 if (premultipliedSrcImage.get())
249                                 {
250                                         pPixmanSrc.Bind(pixman_image_create_bits(PIXMAN_a8r8g8b8, premultipliedSrcImage->width, premultipliedSrcImage->height, (uint32_t*)premultipliedSrcImage->pBitmap, premultipliedSrcImage->bytesPerLine));
251                                 }
252                                 else
253                                 {
254                                         // slow but it does not create additional buffer
255                                         pPixmanSrc.Bind(pixman_image_create_bits(PIXMAN_x8r8g8b8, srcImage.width, srcImage.height, (uint32_t*)srcImage.pBitmap, srcImage.bytesPerLine));
256                                         pPixmanMsk.Bind(pixman_image_create_bits(PIXMAN_a8r8g8b8, srcImage.width, srcImage.height, (uint32_t*)srcImage.pBitmap, srcImage.bytesPerLine));
257
258                                         if (pPixmanMsk == null)
259                                         {
260                                                 return false;
261                                         }
262                                 }
263                         }
264                         break;
265                 default:
266                         return false;
267                 }
268
269                 if (pPixmanSrc)
270                 {
271                         pixman_image_set_transform(pPixmanSrc, &transform);
272
273                         if (pPixmanMsk)
274                         {
275                                 pixman_image_set_transform(pPixmanMsk, &transform);
276                         }
277
278                         pixman_image_set_filter(pPixmanSrc, filter, NULL, 0);
279                         pixman_image_set_repeat(pPixmanSrc, repeatMethod);
280
281                         pixman_image_composite32(rop, pPixmanSrc, pPixmanMsk, pPixmanDst, 0, 0, 0, 0, 0, 0, dstImage.width, dstImage.height);
282
283                         return true;
284                 }
285         }
286
287         return false;
288 }
289
290 bool ResizePixmap(Tizen::Graphics::_Util::Pixmap& dstImage, const Tizen::Graphics::_Util::Pixmap& srcImage, Tizen::Graphics::BitmapScalingQuality scalingQuality)
291 {
292         if (dstImage.width <= 0 || dstImage.height <= 0)
293         {
294                 return true;
295         }
296
297         pixman_filter_t filter = Tizen::Graphics::_Pixman::GetFilter(scalingQuality);
298
299         return ResizePixmap(dstImage, srcImage, filter);
300 }
301
302 bool CopyPixmap(Tizen::Graphics::_Util::Pixmap& dstImage, const Tizen::Graphics::_Util::Pixmap& srcImage, Tizen::Graphics::BitmapDrawingQuality drawingQuality, Tizen::Graphics::BlendingMode blendingMode)
303 {
304         if (dstImage.width <= 0 || dstImage.height <= 0)
305         {
306                 return true;
307         }
308
309         pixman_op_t rop = Tizen::Graphics::_Pixman::GetRop(blendingMode);
310
311         pixman_filter_t filter = Tizen::Graphics::_Pixman::GetFilter(drawingQuality);
312
313         pixman_transform_t transform;
314         pixman_transform_init_identity(&transform);
315
316         return CompositePixmap(dstImage, srcImage, rop, filter, transform, PIXMAN_REPEAT_NONE);
317 }
318
319 bool ScalePixmap(Tizen::Graphics::_Util::Pixmap& dstImage, const Tizen::Graphics::_Util::Pixmap& srcImage, Tizen::Graphics::BitmapDrawingQuality drawingQuality, Tizen::Graphics::BlendingMode blendingMode)
320 {
321         if (dstImage.width <= 0 || dstImage.height <= 0)
322         {
323                 return true;
324         }
325
326         pixman_op_t rop = Tizen::Graphics::_Pixman::GetRop(blendingMode);
327         pixman_filter_t filter = Tizen::Graphics::_Pixman::GetFilter(drawingQuality);
328         pixman_transform_t transform = Tizen::Graphics::_Pixman::GetTransform(srcImage.width, srcImage.height, dstImage.width, dstImage.height);
329
330         return CompositePixmap(dstImage, srcImage, rop, filter, transform, PIXMAN_REPEAT_NORMAL);
331 }
332
333 bool RotatePixmap(Tizen::Graphics::_Util::Pixmap& dstImage, const Tizen::Graphics::_Util::Pixmap& srcImage, Tizen::Graphics::BitmapDrawingQuality drawingQuality, int xDest, int yDest, double degree, int xPivot, int yPivot)
334 {
335         if (dstImage.width <= 0 || dstImage.height <= 0)
336         {
337                 return true;
338         }
339
340         pixman_filter_t filter = Tizen::Graphics::_Pixman::GetFilter(drawingQuality);
341         pixman_transform_t transform = Tizen::Graphics::_Pixman::GetTransform(xDest, yDest, degree, xPivot, yPivot);
342
343         return CompositePixmap(dstImage, srcImage, PIXMAN_OP_OVER, filter, transform, PIXMAN_REPEAT_NONE);
344 }
345
346 } // _Pixman
347
348 }} // Tizen::Graphics