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