Mercurial > MadButterfly
comparison src/graph_engine_skia.cpp @ 482:d38aca825822 Android_Skia
Import more functions for Skia graphic engine.
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Sun, 15 Nov 2009 16:23:21 +0800 |
parents | 9a867333018b |
children | d984a6672be7 |
comparison
equal
deleted
inserted
replaced
481:273307d061b7 | 482:d38aca825822 |
---|---|
1 /*! \page ge_layer Graphic Engine Layer | |
2 * | |
3 * Graphic Engine Layer is an abstract of graphic engine; likes Cairo | |
4 * and Skia. It provides portability for the rest of MadButterfly. | |
5 * | |
6 * The basic stratage of interface of graphic engine layer is defined | |
7 * according purpose of MadButterfly. For example, MadButterfly wants | |
8 * a function that can clear a canvas, we define a clear function. | |
9 * Never define a indirectly way to finish the function. Never define | |
10 * a way to finish the function for the reason that some engine | |
11 * require you to finish the task in that procedure. It avoids | |
12 * binding graphic engine layer with any behavior of a graphic engine, | |
13 * and provides more compatible with other engines, to define | |
14 * interface of graphic engine layer according purpose of | |
15 * MadButterfly. | |
16 * | |
17 * \section ge_mem Graphic Engine Layer Memory Management | |
18 * | |
19 * MadButterfly is responsible for management of objects and memory | |
20 * blocks returned by graphic engine layer, even for graphic engines | |
21 * that have management model. MadButterfly supposes memory blocks | |
22 * only be released when they are no more used. MadBufferfly is | |
23 * responsible for release them. So, even a graphic engine has | |
24 * reference count with objects, MadButterfly still keep a reference | |
25 * for every object returned by the engine until no one will use it. | |
26 * | |
27 * \section ge_transform Transformation of Coordination System | |
28 * | |
29 * Points of pathes are transformed when it is added to the canvas | |
30 * with the transformation matrix at the time. So, changes of | |
31 * transformation matrix of an canvas will not affect points that had | |
32 * been added. It only affects points been added when the matrix is | |
33 * setted. | |
34 */ | |
1 #include <stdio.h> | 35 #include <stdio.h> |
2 #include <SkCanvas.h> | 36 #include <SkCanvas.h> |
3 #include <SkBitmap.h> | 37 #include <SkBitmap.h> |
4 #include <SkShader.h> | 38 #include <SkShader.h> |
39 #include <SkDevice.h> | |
40 #include <SkGradientShader.h> | |
41 #include <SkXfermode.h> | |
42 #include <SkColorFilter.h> | |
5 | 43 |
6 #define C_START extern "C" { | 44 #define C_START extern "C" { |
7 #define C_END } | 45 #define C_END } |
8 | 46 |
9 C_START | 47 C_START |
10 | 48 |
11 #include "mb_graph_engine_skia.h" | 49 #include "mb_graph_engine_skia.h" |
12 #include "mb_shapes.h" | 50 #include "mb_shapes.h" |
51 #include "mb_img_ldr.h" | |
52 | |
53 /*! \brief Source pattern | |
54 * | |
55 * For Skia, source pattern is SkShader with some decoration. Since | |
56 * SkShade will repeative tiling or extenting edge color, it can not | |
57 * stop tiling and extenting for fixed size bitmap. So, we need to | |
58 * translate mbe_paint() into a drawing of a rectangle. | |
59 */ | |
60 struct _mbe_pattern_t { | |
61 SkShader *shader; | |
62 int w, h; | |
63 int has_size; | |
64 co_aix matrix[6]; | |
65 }; | |
13 | 66 |
14 struct _mbe_scaled_font_t { | 67 struct _mbe_scaled_font_t { |
15 struct _mb_font_face_t *face; | 68 struct _mb_font_face_t *face; |
16 co_aix fnt_mtx[6]; | 69 co_aix fnt_mtx[6]; |
17 co_aix ctm[6]; | 70 co_aix ctm[6]; |
18 }; | 71 }; |
19 struct _mbe_font_face_t {}; | 72 struct _mbe_font_face_t {}; |
73 /*! \brief MadButterfly Graphic Engine Context. | |
74 * | |
75 * A context comprises source pattern, target surface, path, | |
76 * line-width, and transform matrix. | |
77 */ | |
20 struct _mbe_t { | 78 struct _mbe_t { |
21 SkCanvas *canvas; | 79 SkCanvas *canvas; |
22 SkShader *shader; | 80 SkPath *path, *subpath; |
23 int shader_owned; | 81 SkPaint *paint; |
82 SkRegion *saved_region; | |
83 | |
84 struct _mbe_states_t *states; | |
85 }; | |
86 | |
87 struct _mbe_states_t { | |
88 mbe_pattern_t *ptn; | |
89 int ptn_owned; | |
90 co_aix line_width; | |
91 co_aix matrix[6]; | |
92 struct _mbe_states_t *next; | |
24 }; | 93 }; |
25 | 94 |
26 #ifndef ASSERT | 95 #ifndef ASSERT |
27 #define ASSERT(x) | 96 #define ASSERT(x) |
28 #endif | 97 #endif |
29 | 98 |
30 void mbe_pattern_add_color_stop_rgba(mbe_pattern_t *ptn, | 99 #define PI 3.1415926535897931 |
31 co_aix offset, | 100 |
32 co_aix r, co_aix g, co_aix b, | 101 #define CO_AIX_2_SKSCALAR(a) ((a) * 65536) |
33 co_aix a) {} | 102 #define SKSCALAR_2_CO_AIX(a) ((co_aix)(a) / 65536) |
34 mbe_pattern_t *mbe_pattern_create_for_surface(mbe_surface_t *surface) {} | 103 #define MB_MATRIX_2_SKMATRIX(sk, mb) { \ |
35 mbe_pattern_t *mbe_pattern_create_radial(co_aix cx0, co_aix cy0, | 104 (sk).setScaleX(CO_AIX_2_SKSCALAR((mb)[0])); \ |
36 co_aix radius0, | 105 (sk).setSkewX(CO_AIX_2_SKSCALAR((mb)[1])); \ |
37 co_aix cx1, co_aix cy1, | 106 (sk).setTranslateX(CO_AIX_2_SKSCALAR((mb)[2])); \ |
38 co_aix radius1) {} | 107 (sk).setSkewY(CO_AIX_2_SKSCALAR((mb)[3])); \ |
39 mbe_pattern_t *mbe_pattern_create_linear(co_aix x0, co_aix y0, | 108 (sk).setScaleY(CO_AIX_2_SKSCALAR((mb)[4])); \ |
40 co_aix x1, co_aix y1) {} | 109 (sk).setTranslateY(CO_AIX_2_SKSCALAR((mb)[5])); \ |
41 void mbe_pattern_set_matrix(mbe_pattern_t *ptn, | 110 } |
42 const co_aix matrix[6]) {} | 111 #define SKMATRIX_2_MB_MATRIX(mb, sk) { \ |
43 void mbe_pattern_destroy(mbe_pattern_t *canvas) {} | 112 (mb)[0] = SKSCALAR_2_CO_AIX((sk).getScaleX()); \ |
44 | 113 (mb)[1] = SKSCALAR_2_CO_AIX((sk).getSkewX()); \ |
45 int mbe_image_surface_get_stride(mbe_surface_t *surface) {} | 114 (mb)[2] = SKSCALAR_2_CO_AIX((sk).getTranslateX()); \ |
46 int mbe_image_surface_get_height(mbe_surface_t *surface) {} | 115 (mb)[3] = SKSCALAR_2_CO_AIX((sk).getSkewY()); \ |
47 int mbe_image_surface_get_width(mbe_surface_t *surface) {} | 116 (mb)[4] = SKSCALAR_2_CO_AIX((sk).getScaleY()); \ |
48 unsigned char *mbe_image_surface_get_data(mbe_surface_t *surface) {} | 117 (mb)[5] = SKSCALAR_2_CO_AIX((sk).getTranslateY()); \ |
118 } | |
119 #define MBSTOP_2_SKCOLOR(c) \ | |
120 ((((int)((c)->a * 255)) << 24) | \ | |
121 (((int)((c)->r * 255)) << 16) | \ | |
122 (((int)((c)->g * 255)) << 8) | \ | |
123 (((int)((c)->b * 255)))) | |
124 | |
125 static const co_aix id_matrix[6] = { 1, 0, 0, 0, 1, 0 }; | |
126 | |
127 static void | |
128 _prepare_sized_pattern(mbe_t *mbe, mbe_pattern_t *ptn) { | |
129 SkCanvas *canvas = mbe->canvas; | |
130 SkPath path; | |
131 co_aix x, y; | |
132 co_aix reverse[6]; | |
133 | |
134 *mbe->saved_region = canvas->getTotalClip(); | |
135 | |
136 compute_reverse(ptn->matrix, reverse); | |
137 x = 0; y = 0; | |
138 matrix_trans_pos(reverse, &x, &y); | |
139 path.moveTo(CO_AIX_2_SKSCALAR(x), CO_AIX_2_SKSCALAR(y)); | |
140 x = 0; y = ptn->h; | |
141 matrix_trans_pos(reverse, &x, &y); | |
142 path.moveTo(CO_AIX_2_SKSCALAR(x), CO_AIX_2_SKSCALAR(y)); | |
143 x = ptn->w; y = ptn->h; | |
144 matrix_trans_pos(reverse, &x, &y); | |
145 path.moveTo(CO_AIX_2_SKSCALAR(x), CO_AIX_2_SKSCALAR(y)); | |
146 path.close(); | |
147 | |
148 canvas->clipPath(path, SkRegion::kIntersect_Op); | |
149 } | |
150 | |
151 static void | |
152 _finish_sized_pattern(mbe_t *mbe) { | |
153 SkCanvas *canvas = mbe->canvas; | |
154 | |
155 canvas->setClipRegion(*mbe->saved_region); | |
156 } | |
157 | |
158 static void | |
159 _canvas_device_region(SkCanvas *canvas, SkRegion *region) { | |
160 SkDevice *device; | |
161 int w, h; | |
162 | |
163 device = canvas->getDevice(); | |
164 w = device->width(); | |
165 h = device->height(); | |
166 region->setRect(0, 0, w, h); | |
167 } | |
168 | |
169 static void | |
170 _update_path(mbe_t *mbe) { | |
171 SkPath *path = mbe->path; | |
172 SkPath *subpath = mbe->subpath; | |
173 SkMatrix canvas_matrix; | |
174 SkPoint point; | |
175 | |
176 MB_MATRIX_2_SKMATRIX(canvas_matrix, mbe->states->matrix); | |
177 path->addPath(*subpath, canvas_matrix); | |
178 | |
179 subpath->getLastPt(&point); | |
180 subpath->rewind(); | |
181 subpath->moveTo(point); | |
182 } | |
183 | |
184 /* | |
185 * When a function want to use the paint associated with a canvas to | |
186 * draw, it should call _prepare_paint() can make the paint ready. | |
187 * And, call _finish_paint() when the paint is no more used. | |
188 */ | |
189 static void | |
190 _prepare_paint(mbe_t *mbe, SkPaint::Style style) { | |
191 SkPaint *paint = mbe->paint; | |
192 mbe_pattern_t *ptn = mbe->states->ptn; | |
193 SkShader *shader = ptn->shader; | |
194 co_aix matrix[6]; | |
195 SkMatrix skmatrix; | |
196 | |
197 paint->setStyle(style); | |
198 | |
199 /* Local matrix of SkShader is a mapping from source pattern to | |
200 * user space. Unlikely, for Cairo is a mapping from user space | |
201 * to source pattern. | |
202 */ | |
203 matrix_mul(mbe->states->matrix, ptn->matrix, matrix); | |
204 MB_MATRIX_2_SKMATRIX(skmatrix, matrix); | |
205 shader->setLocalMatrix(skmatrix); | |
206 paint->setShader(shader); | |
207 | |
208 if(style == SkPaint::kStroke_Style) | |
209 paint->setStrokeWidth(CO_AIX_2_SKSCALAR(mbe->states->line_width)); | |
210 | |
211 if(ptn->has_size) | |
212 _prepare_sized_pattern(mbe, ptn); | |
213 } | |
214 | |
215 static void | |
216 _finish_paint(mbe_t *mbe) { | |
217 mbe_pattern_t *ptn = mbe->states->ptn; | |
218 | |
219 mbe->paint->reset(); | |
220 if(ptn->has_size) | |
221 _finish_sized_pattern(mbe); | |
222 } | |
223 | |
224 mbe_pattern_t *mbe_pattern_create_for_surface(mbe_surface_t *surface) { | |
225 mbe_pattern_t *ptn; | |
226 SkBitmap *bitmap = (SkBitmap *)surface; | |
227 | |
228 ptn = (mbe_pattern_t *)malloc(sizeof(mbe_pattern_t)); | |
229 ptn->shader = SkShader::CreateBitmapShader(*bitmap, | |
230 SkShader::kClamp_TileMode, | |
231 SkShader::kClamp_TileMode); | |
232 if(ptn->shader == NULL) { | |
233 free(ptn); | |
234 return NULL; | |
235 } | |
236 | |
237 ptn->has_size = 1; | |
238 ptn->w = bitmap->width(); | |
239 ptn->h = bitmap->height(); | |
240 | |
241 memcpy(ptn->matrix, id_matrix, sizeof(co_aix) * 6); | |
242 | |
243 return ptn; | |
244 } | |
245 | |
246 mbe_pattern_t * | |
247 mbe_pattern_create_radial(co_aix cx0, co_aix cy0, co_aix radius0, | |
248 co_aix cx1, co_aix cy1, co_aix radius1, | |
249 grad_stop_t *stops, int stop_cnt) { | |
250 mbe_pattern_t *ptn; | |
251 SkColor *colors; | |
252 SkScalar *poses; | |
253 grad_stop_t *stop; | |
254 SkPoint center; | |
255 int i; | |
256 | |
257 ptn = (mbe_pattern_t *)malloc(sizeof(mbe_pattern_t)); | |
258 colors = new SkColor[stop_cnt]; | |
259 poses = new SkScalar[stop_cnt]; | |
260 if(ptn == NULL || colors == NULL || poses == NULL) | |
261 goto fail; | |
262 | |
263 center.set(CO_AIX_2_SKSCALAR(cx1), CO_AIX_2_SKSCALAR(cy1)); | |
264 | |
265 stop = stops; | |
266 for(i = 0; i < stop_cnt; i++) { | |
267 colors[i] = MBSTOP_2_SKCOLOR(stop); | |
268 poses[i] = CO_AIX_2_SKSCALAR(stop->offset); | |
269 } | |
270 | |
271 /* | |
272 * cx0, cy0 and radius0 is not used. Since Skia is still not | |
273 * support two circles radial. And, SVG 1.2 is also not support | |
274 * two circles. | |
275 */ | |
276 ptn->shader = | |
277 SkGradientShader::CreateRadial(center, CO_AIX_2_SKSCALAR(radius1), | |
278 colors, poses, stop_cnt, | |
279 SkShader::kClamp_TileMode); | |
280 if(ptn->shader == NULL) | |
281 goto fail; | |
282 | |
283 memcpy(ptn->matrix, id_matrix, sizeof(co_aix) * 6); | |
284 | |
285 delete colors; | |
286 delete poses; | |
287 return ptn; | |
288 | |
289 fail: | |
290 if(ptn) free(ptn); | |
291 if(colors) delete colors; | |
292 if(poses) delete poses; | |
293 return NULL; | |
294 } | |
295 | |
296 mbe_pattern_t * | |
297 mbe_pattern_create_linear(co_aix x0, co_aix y0, | |
298 co_aix x1, co_aix y1, | |
299 grad_stop_t *stops, int stop_cnt) { | |
300 mbe_pattern_t *ptn; | |
301 SkColor *colors; | |
302 SkScalar *poses; | |
303 grad_stop_t *stop; | |
304 SkPoint points[2]; | |
305 int i; | |
306 | |
307 ptn = (mbe_pattern_t *)malloc(sizeof(mbe_pattern_t)); | |
308 colors = new SkColor[stop_cnt]; | |
309 poses = new SkScalar[stop_cnt]; | |
310 if(ptn == NULL || colors == NULL || poses == NULL) | |
311 goto fail; | |
312 | |
313 points[0].set(CO_AIX_2_SKSCALAR(x0), CO_AIX_2_SKSCALAR(y0)); | |
314 points[1].set(CO_AIX_2_SKSCALAR(x1), CO_AIX_2_SKSCALAR(y1)); | |
315 | |
316 stop = stops; | |
317 for(i = 0; i < stop_cnt; i++) { | |
318 colors[i] = MBSTOP_2_SKCOLOR(stop); | |
319 poses[i] = CO_AIX_2_SKSCALAR(stop->offset); | |
320 } | |
321 | |
322 /* | |
323 * cx0, cy0 and radius0 is not used. Since Skia is still not | |
324 * support two circles radial. And, SVG 1.2 is also not support | |
325 * two circles. | |
326 */ | |
327 ptn->shader = | |
328 SkGradientShader::CreateLinear(points, colors, poses, stop_cnt, | |
329 SkShader::kClamp_TileMode); | |
330 if(ptn->shader == NULL) | |
331 goto fail; | |
332 | |
333 memcpy(ptn->matrix, id_matrix, sizeof(co_aix) * 6); | |
334 | |
335 delete colors; | |
336 delete poses; | |
337 return ptn; | |
338 | |
339 fail: | |
340 if(ptn) free(ptn); | |
341 if(colors) delete colors; | |
342 if(poses) delete poses; | |
343 return NULL; | |
344 } | |
345 | |
346 void mbe_pattern_set_matrix(mbe_pattern_t *ptn, const co_aix matrix[6]) { | |
347 SkMatrix skmatrix; | |
348 | |
349 MB_MATRIX_2_SKMATRIX(skmatrix, matrix); | |
350 | |
351 ptn->shader->setLocalMatrix(skmatrix); | |
352 } | |
353 | |
354 void mbe_pattern_destroy(mbe_pattern_t *ptn) { | |
355 if(ptn->shader) | |
356 delete ptn->shader; | |
357 free(ptn); | |
358 } | |
359 | |
360 int mbe_image_surface_get_stride(mbe_surface_t *surface) { | |
361 return ((SkBitmap *)surface)->rowBytes(); | |
362 } | |
363 | |
364 int mbe_image_surface_get_height(mbe_surface_t *surface) { | |
365 return ((SkBitmap *)surface)->height(); | |
366 } | |
367 | |
368 int mbe_image_surface_get_width(mbe_surface_t *surface) { | |
369 return ((SkBitmap *)surface)->width(); | |
370 } | |
371 | |
372 unsigned char *mbe_image_surface_get_data(mbe_surface_t *surface) { | |
373 return (unsigned char *)((SkBitmap *)surface)->getPixels(); | |
374 } | |
375 | |
49 mbe_surface_t *mbe_image_surface_create_from_png(const char *filename) {} | 376 mbe_surface_t *mbe_image_surface_create_from_png(const char *filename) {} |
377 | |
50 mbe_surface_t * | 378 mbe_surface_t * |
51 mbe_image_surface_create_for_data(unsigned char *data, | 379 mbe_image_surface_create_for_data(unsigned char *data, |
52 mb_img_fmt_t fmt, | 380 mb_img_fmt_t fmt, |
53 int width, int height, | 381 int width, int height, |
54 int stride) {} | 382 int stride) { |
55 mb_img_fmt_t mbe_image_surface_get_format(mbe_surface_t *surface) {} | 383 SkBitmap *bitmap; |
384 SkBitmap::Config cfg; | |
385 | |
386 switch(fmt) { | |
387 case MB_IFMT_ARGB32: | |
388 cfg = SkBitmap::kARGB_8888_Config; break; | |
389 | |
390 case MB_IFMT_A8: | |
391 cfg = SkBitmap::kA8_Config; break; | |
392 | |
393 case MB_IFMT_A1: | |
394 cfg = SkBitmap::kA1_Config; break; | |
395 | |
396 case MB_IFMT_RGB16_565: | |
397 cfg = SkBitmap::kRGB_565_Config; break; | |
398 | |
399 case MB_IFMT_RGB24: | |
400 default: | |
401 return NULL; | |
402 } | |
403 | |
404 bitmap = new SkBitmap(); | |
405 if(bitmap == NULL) | |
406 return NULL; | |
407 | |
408 bitmap->setConfig(cfg, width, height, stride); | |
409 bitmap->setPixels(data); | |
410 | |
411 return (mbe_surface_t *)bitmap; | |
412 } | |
413 | |
414 mb_img_fmt_t mbe_image_surface_get_format(mbe_surface_t *surface) { | |
415 SkBitmap *bitmap = (SkBitmap *)surface; | |
416 mb_img_fmt_t fmt; | |
417 SkBitmap::Config cfg; | |
418 | |
419 cfg = bitmap->getConfig(); | |
420 switch(cfg) { | |
421 case SkBitmap::kARGB_8888_Config: | |
422 fmt = MB_IFMT_ARGB32; break; | |
423 | |
424 case SkBitmap::kA8_Config: | |
425 fmt = MB_IFMT_A8; break; | |
426 | |
427 case SkBitmap::kA1_Config: | |
428 fmt = MB_IFMT_A1; break; | |
429 | |
430 case SkBitmap::kRGB_565_Config: | |
431 fmt = MB_IFMT_RGB16_565; break; | |
432 | |
433 default: | |
434 fmt = MB_IFMT_DUMMY; | |
435 } | |
436 | |
437 return fmt; | |
438 } | |
439 | |
56 mbe_surface_t * | 440 mbe_surface_t * |
57 mbe_image_surface_create(mb_img_fmt_t fmt, int width, int height) {} | 441 mbe_image_surface_create(mb_img_fmt_t fmt, int width, int height) { |
58 | 442 SkBitmap *bitmap; |
59 mbe_scaled_font_t *mbe_scaled_font_reference(mbe_scaled_font_t *scaled) {} | 443 SkBitmap::Config cfg; |
444 | |
445 switch(fmt) { | |
446 case MB_IFMT_ARGB32: | |
447 cfg = SkBitmap::kARGB_8888_Config; break; | |
448 | |
449 case MB_IFMT_A8: | |
450 cfg = SkBitmap::kA8_Config; break; | |
451 | |
452 case MB_IFMT_A1: | |
453 cfg = SkBitmap::kA1_Config; break; | |
454 | |
455 case MB_IFMT_RGB16_565: | |
456 cfg = SkBitmap::kRGB_565_Config; break; | |
457 | |
458 case MB_IFMT_RGB24: | |
459 default: | |
460 return NULL; | |
461 } | |
462 | |
463 bitmap = new SkBitmap(); | |
464 if(bitmap == NULL) | |
465 return NULL; | |
466 | |
467 bitmap->setConfig(cfg, width, height); | |
468 bitmap->allocPixels(); | |
469 | |
470 return (mbe_surface_t *)bitmap; | |
471 } | |
472 | |
473 mbe_scaled_font_t *mbe_scaled_font_reference(mbe_scaled_font_t *scaled) { | |
474 } | |
475 | |
60 void mbe_scaled_font_destroy(mbe_scaled_font_t *scaled) {} | 476 void mbe_scaled_font_destroy(mbe_scaled_font_t *scaled) {} |
61 mbe_font_face_t *mbe_font_face_reference(mbe_font_face_t *face) {} | 477 mbe_font_face_t *mbe_font_face_reference(mbe_font_face_t *face) {} |
62 mbe_scaled_font_t * | 478 mbe_scaled_font_t * |
63 mbe_scaled_font_create(mbe_font_face_t *face, co_aix fnt_mtx[6], | 479 mbe_scaled_font_create(mbe_font_face_t *face, co_aix fnt_mtx[6], |
64 co_aix ctm[6]) {} | 480 co_aix ctm[6]) {} |
66 void mbe_scaled_font_text_extents(mbe_scaled_font_t *scaled, | 482 void mbe_scaled_font_text_extents(mbe_scaled_font_t *scaled, |
67 const char *txt, | 483 const char *txt, |
68 mbe_text_extents_t *extents) {} | 484 mbe_text_extents_t *extents) {} |
69 | 485 |
70 void mbe_font_face_destroy(mbe_font_face_t *face) {} | 486 void mbe_font_face_destroy(mbe_font_face_t *face) {} |
71 void mbe_paint_with_alpha(mbe_t *canvas, co_aix alpha) {} | 487 |
488 void mbe_paint_with_alpha(mbe_t *canvas, co_aix alpha) { | |
489 SkPaint *paint = canvas->paint; | |
490 SkColorFilter *filter; | |
491 SkColor color; | |
492 | |
493 color = ((uint32_t)(alpha * 255)) << 24; | |
494 filter = | |
495 SkColorFilter::CreatePorterDuffFilter(color, | |
496 SkPorterDuff::kSrcOver_Mode); | |
497 mbe_paint(canvas); | |
498 | |
499 } | |
500 | |
72 void mbe_surface_destroy(mbe_surface_t *surface) {} | 501 void mbe_surface_destroy(mbe_surface_t *surface) {} |
73 void mbe_set_source_rgba(mbe_t *canvas, | 502 void mbe_set_source_rgba(mbe_t *canvas, |
74 co_aix r, co_aix g, co_aix b, co_aix a) {} | 503 co_aix r, co_aix g, co_aix b, co_aix a) {} |
75 void mbe_set_scaled_font(mbe_t *canvas, | 504 void mbe_set_scaled_font(mbe_t *canvas, |
76 const mbe_scaled_font_t *scaled) {} | 505 const mbe_scaled_font_t *scaled) {} |
77 void mbe_set_source_rgb(mbe_t *canvas, co_aix r, co_aix g, co_aix b) {} | 506 void mbe_set_source_rgb(mbe_t *canvas, co_aix r, co_aix g, co_aix b) {} |
78 void mbe_set_line_width(mbe_t *canvas, co_aix width) {} | 507 |
508 void mbe_set_line_width(mbe_t *canvas, co_aix width) { | |
509 canvas->states->line_width = width; | |
510 } | |
511 | |
79 mbe_font_face_t *mbe_get_font_face(mbe_t *canvas) {} | 512 mbe_font_face_t *mbe_get_font_face(mbe_t *canvas) {} |
80 void mbe_fill_preserve(mbe_t *canvas) {} | 513 |
81 void mbe_set_source(mbe_t *canvas, mbe_pattern_t *source) {} | 514 void mbe_fill_preserve(mbe_t *canvas) { |
82 void mbe_reset_clip(mbe_t *canvas) {} | 515 mbe_pattern_t *ptn = canvas->states->ptn; |
83 mbe_surface_t *mbe_get_target(mbe_t *canvas) {} | 516 SkPaint *paint = canvas->paint; |
84 void mbe_close_path(mbe_t *canvas) {} | 517 SkPath *path = canvas->path; |
518 SkRegion *saved_clip = NULL; | |
519 co_aix x, y; | |
520 | |
521 ASSERT(paint); | |
522 ASSERT(ptn); | |
523 ASSERT(path); | |
524 | |
525 if(!canvas->subpath->isEmpty()) | |
526 _update_path(canvas); | |
527 | |
528 _prepare_paint(canvas, SkPaint::kFill_Style); | |
529 | |
530 canvas->canvas->drawPath(*path, *paint); | |
531 | |
532 _finish_paint(canvas); | |
533 } | |
534 | |
535 void mbe_set_source(mbe_t *canvas, mbe_pattern_t *source) { | |
536 canvas->states->ptn = source; | |
537 } | |
538 | |
539 void mbe_reset_clip(mbe_t *canvas) { | |
540 SkRegion clip; | |
541 | |
542 _canvas_device_region(canvas->canvas, &clip); | |
543 canvas->canvas->setClipRegion(clip); | |
544 } | |
545 | |
546 mbe_surface_t *mbe_get_target(mbe_t *canvas) { | |
547 return (mbe_surface_t *)&canvas->canvas->getDevice()->accessBitmap(false); | |
548 } | |
549 | |
550 void mbe_close_path(mbe_t *canvas) { | |
551 canvas->subpath->close(); | |
552 } | |
553 | |
85 void mbe_text_path(mbe_t *canvas, const char *txt) {} | 554 void mbe_text_path(mbe_t *canvas, const char *txt) {} |
555 | |
86 void mbe_rectangle(mbe_t *canvas, co_aix x, co_aix y, | 556 void mbe_rectangle(mbe_t *canvas, co_aix x, co_aix y, |
87 co_aix width, co_aix height) {} | 557 co_aix width, co_aix height) { |
88 int mbe_in_stroke(mbe_t *canvas, co_aix x, co_aix y) {} | 558 SkPath *subpath = canvas->subpath; |
89 void mbe_new_path(mbe_t *canvas) {} | 559 |
560 subpath->addRect(CO_AIX_2_SKSCALAR(x), CO_AIX_2_SKSCALAR(y), | |
561 CO_AIX_2_SKSCALAR(x + width), | |
562 CO_AIX_2_SKSCALAR(y + height)); | |
563 } | |
564 | |
565 int mbe_in_stroke(mbe_t *canvas, co_aix x, co_aix y) { | |
566 return 0; | |
567 } | |
568 | |
569 void mbe_new_path(mbe_t *canvas) { | |
570 canvas->subpath->reset(); | |
571 } | |
572 | |
90 void mbe_curve_to(mbe_t *canvas, co_aix x1, co_aix y1, | 573 void mbe_curve_to(mbe_t *canvas, co_aix x1, co_aix y1, |
91 co_aix x2, co_aix y2, | 574 co_aix x2, co_aix y2, |
92 co_aix x3, co_aix y3) {} | 575 co_aix x3, co_aix y3) { |
93 void mbe_restore(mbe_t *canvas) {} | 576 SkPath *subpath = canvas->subpath; |
94 void mbe_move_to(mbe_t *canvas, co_aix x, co_aix y) {} | 577 |
95 void mbe_line_to(mbe_t *canvas, co_aix x, co_aix y) {} | 578 subpath->cubicTo(CO_AIX_2_SKSCALAR(x1), CO_AIX_2_SKSCALAR(y1), |
96 int mbe_in_fill(mbe_t *canvas, co_aix x, co_aix y) {} | 579 CO_AIX_2_SKSCALAR(x2), CO_AIX_2_SKSCALAR(y2), |
97 void mbe_stroke(mbe_t *canvas) {} | 580 CO_AIX_2_SKSCALAR(x3), CO_AIX_2_SKSCALAR(y3)); |
581 } | |
582 | |
583 void mbe_restore(mbe_t *canvas) { | |
584 struct _mbe_states_t *states; | |
585 | |
586 _update_path(canvas); | |
587 | |
588 states = canvas->states; | |
589 ASSERT(states->next); | |
590 canvas->states = states->next; | |
591 free(states); | |
592 } | |
593 | |
594 void mbe_move_to(mbe_t *canvas, co_aix x, co_aix y) { | |
595 canvas->subpath->moveTo(CO_AIX_2_SKSCALAR(x), | |
596 CO_AIX_2_SKSCALAR(y)); | |
597 } | |
598 | |
599 void mbe_line_to(mbe_t *canvas, co_aix x, co_aix y) { | |
600 canvas->subpath->lineTo(CO_AIX_2_SKSCALAR(x), | |
601 CO_AIX_2_SKSCALAR(y)); | |
602 } | |
603 | |
604 int mbe_in_fill(mbe_t *canvas, co_aix x, co_aix y) { | |
605 SkRegion region, dev_region; | |
606 bool in_fill; | |
607 | |
608 if(!canvas->subpath->isEmpty()) | |
609 _update_path(canvas); | |
610 | |
611 _canvas_device_region(canvas->canvas, &dev_region); | |
612 region.setPath(*canvas->path, dev_region); | |
613 | |
614 in_fill = region.contains(x, y); | |
615 | |
616 return in_fill; | |
617 } | |
618 | |
619 void mbe_stroke(mbe_t *canvas) { | |
620 SkPath *path = canvas->path; | |
621 SkPaint *paint = canvas->paint; | |
622 | |
623 ASSERT(ptn); | |
624 ASSERT(path); | |
625 ASSERT(paint); | |
626 | |
627 if(!canvas->subpath->isEmpty()) | |
628 _update_path(canvas); | |
629 | |
630 _prepare_paint(canvas, SkPaint::kStroke_Style); | |
631 | |
632 canvas->canvas->drawPath(*path, *paint); | |
633 | |
634 _finish_paint(canvas); | |
635 | |
636 path->reset(); | |
637 } | |
98 | 638 |
99 mbe_t *mbe_create(mbe_surface_t *target) { | 639 mbe_t *mbe_create(mbe_surface_t *target) { |
100 mbe_t *mbe; | 640 mbe_t *mbe; |
641 struct _mbe_states_t *states; | |
101 SkBitmap *bitmap = (SkBitmap *)target; | 642 SkBitmap *bitmap = (SkBitmap *)target; |
102 | 643 |
103 mbe = (mbe_t *)malloc(sizeof(mbe_t)); | 644 mbe = (mbe_t *)malloc(sizeof(mbe_t)); |
104 if(mbe == NULL) | 645 if(mbe == NULL) |
105 return NULL; | 646 return NULL; |
106 | 647 |
107 mbe->canvas = new SkCanvas(*bitmap); | 648 mbe->states = (struct _mbe_states_t *) |
108 if(mbe->canvas == NULL) { | 649 malloc(sizeof(struct _mbe_states_t)); |
650 states = mbe->states; | |
651 if(states == NULL) { | |
109 free(mbe); | 652 free(mbe); |
110 return NULL; | 653 return NULL; |
111 } | 654 } |
112 | 655 |
113 mbe->shader = NULL; | 656 mbe->canvas = new SkCanvas(*bitmap); |
114 mbe->shader_owned = 0; | 657 mbe->path = new SkPath(); |
115 | 658 mbe->subpath = new SkPath(); |
659 mbe->saved_region = new SkRegion(); | |
660 mbe->paint = new SkPaint(); | |
661 states->ptn = NULL; | |
662 states->ptn_owned = 0; | |
663 states->line_width = 0; | |
664 states->next = NULL; | |
665 | |
666 if(mbe->canvas == NULL || mbe->path == NULL || | |
667 mbe->subpath == NULL || mbe->paint == NULL || | |
668 mbe->saved_region == NULL) | |
669 goto fail; | |
670 | |
671 memcpy(states->matrix, id_matrix, sizeof(co_aix) * 6); | |
672 | |
116 return mbe; | 673 return mbe; |
674 | |
675 fail: | |
676 if(mbe->canvas) delete mbe->canvas; | |
677 if(mbe->path) delete mbe->path; | |
678 if(mbe->subpath) delete mbe->subpath; | |
679 if(mbe->paint) delete mbe->paint; | |
680 if(mbe->saved_region) delete mbe->saved_region; | |
681 free(states); | |
682 free(mbe); | |
683 | |
684 return NULL; | |
117 } | 685 } |
118 | 686 |
119 void mbe_destroy(mbe_t *canvas) { | 687 void mbe_destroy(mbe_t *canvas) { |
688 struct _mbe_states_t *states; | |
689 | |
120 delete canvas->canvas; | 690 delete canvas->canvas; |
121 if(canvas->shader && canvas->shader_owned) | 691 delete canvas->path; |
122 delete canvas->shader; | 692 delete canvas->subpath; |
693 delete canvas->paint; | |
694 delete canvas->saved_region; | |
695 while(canvas->states) { | |
696 states = canvas->states; | |
697 canvas->states = states->next; | |
698 | |
699 if(states->ptn && states->ptn_owned) | |
700 mbe_pattern_destroy(states->ptn); | |
701 free(states); | |
702 } | |
123 free(canvas); | 703 free(canvas); |
124 } | 704 } |
125 | 705 |
126 void mbe_paint(mbe_t *canvas) {} | 706 void mbe_paint(mbe_t *canvas) { |
127 void mbe_save(mbe_t *canvas) {} | 707 SkPaint *paint = canvas->paint; |
128 void mbe_fill(mbe_t *canvas) {} | 708 |
129 void mbe_clip(mbe_t *canvas) {} | 709 ASSERT(paint); |
710 | |
711 _prepare_paint(canvas, SkPaint::kFill_Style); | |
712 | |
713 canvas->canvas->drawPaint(*paint); | |
714 | |
715 _finish_paint(canvas); | |
716 } | |
717 | |
718 void mbe_save(mbe_t *canvas) { | |
719 struct _mbe_states_t *states; | |
720 | |
721 states = (struct _mbe_states_t *)malloc(sizeof(struct _mbe_states_t)); | |
722 ASSERT(states); | |
723 | |
724 memcpy(states, canvas->states, sizeof(struct _mbe_states_t)); | |
725 states->next = canvas->states; | |
726 canvas->states = states; | |
727 } | |
728 | |
729 void mbe_fill(mbe_t *canvas) { | |
730 mbe_fill_preserve(canvas); | |
731 canvas->path->reset(); | |
732 } | |
733 | |
734 void mbe_clip(mbe_t *canvas) { | |
735 if(!canvas->subpath->isEmpty()) | |
736 _update_path(canvas); | |
737 | |
738 canvas->canvas->clipPath(*canvas->path, SkRegion::kIntersect_Op); | |
739 canvas->path->reset(); | |
740 } | |
130 | 741 |
131 mbe_font_face_t * mbe_query_font_face(const char *family, | 742 mbe_font_face_t * mbe_query_font_face(const char *family, |
132 int slant, int weight) {} | 743 int slant, int weight) {} |
133 void mbe_free_font_face(mbe_font_face_t *face) {} | 744 void mbe_free_font_face(mbe_font_face_t *face) {} |
134 | 745 |
135 void mbe_clear(mbe_t *canvas) {} | 746 void mbe_clear(mbe_t *canvas) { |
136 void mbe_copy_source(mbe_t *canvas) {} | 747 SkColor color = 0; |
137 void mbe_transform(mbe_t *mbe, co_aix matrix[6]) {} | 748 |
749 canvas->canvas->drawColor(color, SkPorterDuff::kClear_Mode); | |
750 } | |
751 | |
752 void mbe_copy_source(mbe_t *canvas) { | |
753 SkPaint *paint = canvas->paint; | |
754 SkXfermode *mode; | |
755 | |
756 _prepare_paint(canvas, SkPaint::kFill_Style); | |
757 mode = SkPorterDuff::CreateXfermode(SkPorterDuff::kSrc_Mode); | |
758 paint->setXfermode(mode); | |
759 mode->unref(); | |
760 | |
761 canvas->canvas->drawPaint(*paint); | |
762 | |
763 _finish_paint(canvas); | |
764 } | |
765 | |
766 void mbe_transform(mbe_t *mbe, co_aix matrix[6]) { | |
767 _update_path(mbe); | |
768 | |
769 matrix_mul(matrix, mbe->states->matrix, mbe->states->matrix); | |
770 } | |
771 | |
138 void mbe_arc(mbe_t *mbe, co_aix x, co_aix y, co_aix radius, | 772 void mbe_arc(mbe_t *mbe, co_aix x, co_aix y, co_aix radius, |
139 co_aix angle_start, co_aix angle_stop) {} | 773 co_aix angle_start, co_aix angle_stop) { |
774 SkPoint point; | |
775 SkPath *subpath = mbe->subpath; | |
776 SkRect rect; | |
777 SkScalar x0, y0; | |
778 SkScalar ang_start, ang_stop; | |
779 SkScalar sweep; | |
780 SkScalar r; /* radius */ | |
781 | |
782 subpath->getLastPt(&point); | |
783 x0 = point.fX; | |
784 y0 = point.fX; | |
785 r = CO_AIX_2_SKSCALAR(radius); | |
786 ang_start = CO_AIX_2_SKSCALAR(angle_start * 180 / PI); | |
787 ang_stop = CO_AIX_2_SKSCALAR(angle_stop * 180 / PI); | |
788 | |
789 /* Skia can only draw an arc in clockwise directly. We negative | |
790 * start and stop point to draw the arc in the mirror along x-axis | |
791 * in a sub-path. Then, the sub-path are reflected along x-axis, | |
792 * again. We get a right path, and add it to the path of mbe_t. | |
793 */ | |
794 if(ang_start > ang_stop) { | |
795 SkPath tmppath; | |
796 SkMatrix matrix; | |
797 co_aix reflect[6] = { 1, 0, 0, | |
798 0, -1, 0}; | |
799 | |
800 rect.set(-r, -r, r, r); | |
801 sweep = ang_start - ang_stop; | |
802 tmppath.arcTo(rect, -ang_start, sweep, false); | |
803 | |
804 reflect[2] = x; | |
805 reflect[5] = y; | |
806 MB_MATRIX_2_SKMATRIX(matrix, reflect); | |
807 subpath->addPath(tmppath, matrix); | |
808 } else { | |
809 rect.set(x0 - r, y0 - r, x0 + r, y0 + r); | |
810 sweep = ang_stop - ang_start; | |
811 subpath->arcTo(rect, ang_start, sweep, false); | |
812 } | |
813 } | |
140 | 814 |
141 | 815 |
142 C_END | 816 C_END |