1 /*
2  * Copyright 2014 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "sk_canvas.h"
9 #include "sk_data.h"
10 #include "sk_image.h"
11 #include "sk_paint.h"
12 #include "sk_path.h"
13 #include "sk_surface.h"
14 #include "sk_types_priv.h"
15 
16 #include "SkCanvas.h"
17 #include "SkData.h"
18 #include "SkImage.h"
19 #include "SkMaskFilter.h"
20 #include "SkMatrix.h"
21 #include "SkPaint.h"
22 #include "SkPath.h"
23 #include "SkPictureRecorder.h"
24 #include "SkSurface.h"
25 
26 const struct {
27     sk_colortype_t  fC;
28     SkColorType     fSK;
29 } gColorTypeMap[] = {
30     { UNKNOWN_SK_COLORTYPE,     kUnknown_SkColorType    },
31     { RGBA_8888_SK_COLORTYPE,   kRGBA_8888_SkColorType  },
32     { BGRA_8888_SK_COLORTYPE,   kBGRA_8888_SkColorType  },
33     { ALPHA_8_SK_COLORTYPE,     kAlpha_8_SkColorType    },
34 };
35 
36 const struct {
37     sk_alphatype_t  fC;
38     SkAlphaType     fSK;
39 } gAlphaTypeMap[] = {
40     { OPAQUE_SK_ALPHATYPE,      kOpaque_SkAlphaType     },
41     { PREMUL_SK_ALPHATYPE,      kPremul_SkAlphaType     },
42     { UNPREMUL_SK_ALPHATYPE,    kUnpremul_SkAlphaType   },
43 };
44 
from_c_colortype(sk_colortype_t cCT,SkColorType * skCT)45 static bool from_c_colortype(sk_colortype_t cCT, SkColorType* skCT) {
46     for (size_t i = 0; i < SK_ARRAY_COUNT(gColorTypeMap); ++i) {
47         if (gColorTypeMap[i].fC == cCT) {
48             if (skCT) {
49                 *skCT = gColorTypeMap[i].fSK;
50             }
51             return true;
52         }
53     }
54     return false;
55 }
56 
to_c_colortype(SkColorType skCT,sk_colortype_t * cCT)57 static bool to_c_colortype(SkColorType skCT, sk_colortype_t* cCT) {
58     for (size_t i = 0; i < SK_ARRAY_COUNT(gColorTypeMap); ++i) {
59         if (gColorTypeMap[i].fSK == skCT) {
60             if (cCT) {
61                 *cCT = gColorTypeMap[i].fC;
62             }
63             return true;
64         }
65     }
66     return false;
67 }
68 
from_c_alphatype(sk_alphatype_t cAT,SkAlphaType * skAT)69 static bool from_c_alphatype(sk_alphatype_t cAT, SkAlphaType* skAT) {
70     for (size_t i = 0; i < SK_ARRAY_COUNT(gAlphaTypeMap); ++i) {
71         if (gAlphaTypeMap[i].fC == cAT) {
72             if (skAT) {
73                 *skAT = gAlphaTypeMap[i].fSK;
74             }
75             return true;
76         }
77     }
78     return false;
79 }
80 
from_c_info(const sk_imageinfo_t & cinfo,SkImageInfo * info)81 static bool from_c_info(const sk_imageinfo_t& cinfo, SkImageInfo* info) {
82     SkColorType ct;
83     SkAlphaType at;
84 
85     if (!from_c_colortype(cinfo.colorType, &ct)) {
86         // optionally report error to client?
87         return false;
88     }
89     if (!from_c_alphatype(cinfo.alphaType, &at)) {
90         // optionally report error to client?
91         return false;
92     }
93     if (info) {
94         *info = SkImageInfo::Make(cinfo.width, cinfo.height, ct, at);
95     }
96     return true;
97 }
98 
from_c_matrix(const sk_matrix_t * cmatrix,SkMatrix * matrix)99 static void from_c_matrix(const sk_matrix_t* cmatrix, SkMatrix* matrix) {
100     matrix->setAll(cmatrix->mat[0], cmatrix->mat[1], cmatrix->mat[2],
101                    cmatrix->mat[3], cmatrix->mat[4], cmatrix->mat[5],
102                    cmatrix->mat[6], cmatrix->mat[7], cmatrix->mat[8]);
103 }
104 
105 const struct {
106     sk_path_direction_t fC;
107     SkPath::Direction   fSk;
108 } gPathDirMap[] = {
109     { CW_SK_PATH_DIRECTION,  SkPath::kCW_Direction },
110     { CCW_SK_PATH_DIRECTION, SkPath::kCCW_Direction },
111 };
112 
from_c_path_direction(sk_path_direction_t cdir,SkPath::Direction * dir)113 static bool from_c_path_direction(sk_path_direction_t cdir, SkPath::Direction* dir) {
114     for (size_t i = 0; i < SK_ARRAY_COUNT(gPathDirMap); ++i) {
115         if (gPathDirMap[i].fC == cdir) {
116             if (dir) {
117                 *dir = gPathDirMap[i].fSk;
118             }
119             return true;
120         }
121     }
122     return false;
123 }
124 
AsData(const sk_data_t * cdata)125 static SkData* AsData(const sk_data_t* cdata) {
126     return reinterpret_cast<SkData*>(const_cast<sk_data_t*>(cdata));
127 }
128 
ToData(SkData * data)129 static sk_data_t* ToData(SkData* data) {
130     return reinterpret_cast<sk_data_t*>(data);
131 }
132 
ToRect(const SkRect & rect)133 static sk_rect_t ToRect(const SkRect& rect) {
134     return reinterpret_cast<const sk_rect_t&>(rect);
135 }
136 
AsRect(const sk_rect_t & crect)137 static const SkRect& AsRect(const sk_rect_t& crect) {
138     return reinterpret_cast<const SkRect&>(crect);
139 }
140 
AsRect(const sk_rect_t * crect)141 static const SkRect* AsRect(const sk_rect_t* crect) {
142     return reinterpret_cast<const SkRect*>(crect);
143 }
144 
AsPath(const sk_path_t & cpath)145 static const SkPath& AsPath(const sk_path_t& cpath) {
146     return reinterpret_cast<const SkPath&>(cpath);
147 }
148 
as_path(sk_path_t * cpath)149 static SkPath* as_path(sk_path_t* cpath) {
150     return reinterpret_cast<SkPath*>(cpath);
151 }
152 
AsImage(const sk_image_t * cimage)153 static const SkImage* AsImage(const sk_image_t* cimage) {
154     return reinterpret_cast<const SkImage*>(cimage);
155 }
156 
ToImage(SkImage * cimage)157 static sk_image_t* ToImage(SkImage* cimage) {
158     return reinterpret_cast<sk_image_t*>(cimage);
159 }
160 
ToCanvas(SkCanvas * canvas)161 static sk_canvas_t* ToCanvas(SkCanvas* canvas) {
162     return reinterpret_cast<sk_canvas_t*>(canvas);
163 }
164 
AsCanvas(sk_canvas_t * ccanvas)165 static SkCanvas* AsCanvas(sk_canvas_t* ccanvas) {
166     return reinterpret_cast<SkCanvas*>(ccanvas);
167 }
168 
AsPictureRecorder(sk_picture_recorder_t * crec)169 static SkPictureRecorder* AsPictureRecorder(sk_picture_recorder_t* crec) {
170     return reinterpret_cast<SkPictureRecorder*>(crec);
171 }
172 
ToPictureRecorder(SkPictureRecorder * rec)173 static sk_picture_recorder_t* ToPictureRecorder(SkPictureRecorder* rec) {
174     return reinterpret_cast<sk_picture_recorder_t*>(rec);
175 }
176 
AsPicture(const sk_picture_t * cpic)177 static const SkPicture* AsPicture(const sk_picture_t* cpic) {
178     return reinterpret_cast<const SkPicture*>(cpic);
179 }
180 
AsPicture(sk_picture_t * cpic)181 static SkPicture* AsPicture(sk_picture_t* cpic) {
182     return reinterpret_cast<SkPicture*>(cpic);
183 }
184 
ToPicture(SkPicture * pic)185 static sk_picture_t* ToPicture(SkPicture* pic) {
186     return reinterpret_cast<sk_picture_t*>(pic);
187 }
188 
189 ///////////////////////////////////////////////////////////////////////////////////////////
190 
sk_colortype_get_default_8888()191 sk_colortype_t sk_colortype_get_default_8888() {
192     sk_colortype_t ct;
193     if (!to_c_colortype(kN32_SkColorType, &ct)) {
194         ct = UNKNOWN_SK_COLORTYPE;
195     }
196     return ct;
197 }
198 
199 ///////////////////////////////////////////////////////////////////////////////////////////
200 
sk_image_new_raster_copy(const sk_imageinfo_t * cinfo,const void * pixels,size_t rowBytes)201 sk_image_t* sk_image_new_raster_copy(const sk_imageinfo_t* cinfo, const void* pixels,
202                                      size_t rowBytes) {
203     SkImageInfo info;
204     if (!from_c_info(*cinfo, &info)) {
205         return NULL;
206     }
207     return (sk_image_t*)SkImage::NewRasterCopy(info, pixels, rowBytes);
208 }
209 
sk_image_new_from_data(const sk_data_t * cdata)210 sk_image_t* sk_image_new_from_data(const sk_data_t* cdata) {
211     return ToImage(SkImage::NewFromData(AsData(cdata)));
212 }
213 
sk_image_encode(const sk_image_t * cimage)214 sk_data_t* sk_image_encode(const sk_image_t* cimage) {
215     return ToData(AsImage(cimage)->encode());
216 }
217 
sk_image_ref(const sk_image_t * cimage)218 void sk_image_ref(const sk_image_t* cimage) {
219     AsImage(cimage)->ref();
220 }
221 
sk_image_unref(const sk_image_t * cimage)222 void sk_image_unref(const sk_image_t* cimage) {
223     AsImage(cimage)->unref();
224 }
225 
sk_image_get_width(const sk_image_t * cimage)226 int sk_image_get_width(const sk_image_t* cimage) {
227     return AsImage(cimage)->width();
228 }
229 
sk_image_get_height(const sk_image_t * cimage)230 int sk_image_get_height(const sk_image_t* cimage) {
231     return AsImage(cimage)->height();
232 }
233 
sk_image_get_unique_id(const sk_image_t * cimage)234 uint32_t sk_image_get_unique_id(const sk_image_t* cimage) {
235     return AsImage(cimage)->uniqueID();
236 }
237 
238 ///////////////////////////////////////////////////////////////////////////////////////////
239 
sk_path_new()240 sk_path_t* sk_path_new() {
241     return (sk_path_t*)SkNEW(SkPath);
242 }
243 
sk_path_delete(sk_path_t * cpath)244 void sk_path_delete(sk_path_t* cpath) {
245     SkDELETE(as_path(cpath));
246 }
247 
sk_path_move_to(sk_path_t * cpath,float x,float y)248 void sk_path_move_to(sk_path_t* cpath, float x, float y) {
249     as_path(cpath)->moveTo(x, y);
250 }
251 
sk_path_line_to(sk_path_t * cpath,float x,float y)252 void sk_path_line_to(sk_path_t* cpath, float x, float y) {
253     as_path(cpath)->lineTo(x, y);
254 }
255 
sk_path_quad_to(sk_path_t * cpath,float x0,float y0,float x1,float y1)256 void sk_path_quad_to(sk_path_t* cpath, float x0, float y0, float x1, float y1) {
257     as_path(cpath)->quadTo(x0, y0, x1, y1);
258 }
259 
sk_path_conic_to(sk_path_t * cpath,float x0,float y0,float x1,float y1,float w)260 void sk_path_conic_to(sk_path_t* cpath, float x0, float y0, float x1, float y1, float w) {
261     as_path(cpath)->conicTo(x0, y0, x1, y1, w);
262 }
263 
sk_path_cubic_to(sk_path_t * cpath,float x0,float y0,float x1,float y1,float x2,float y2)264 void sk_path_cubic_to(sk_path_t* cpath, float x0, float y0, float x1, float y1, float x2, float y2) {
265     as_path(cpath)->cubicTo(x0, y0, x1, y1, x2, y2);
266 }
267 
sk_path_close(sk_path_t * cpath)268 void sk_path_close(sk_path_t* cpath) {
269     as_path(cpath)->close();
270 }
271 
sk_path_add_rect(sk_path_t * cpath,const sk_rect_t * crect,sk_path_direction_t cdir)272 void sk_path_add_rect(sk_path_t* cpath, const sk_rect_t* crect, sk_path_direction_t cdir) {
273     SkPath::Direction dir;
274     if (!from_c_path_direction(cdir, &dir)) {
275         return;
276     }
277     as_path(cpath)->addRect(AsRect(*crect), dir);
278 }
279 
sk_path_add_oval(sk_path_t * cpath,const sk_rect_t * crect,sk_path_direction_t cdir)280 void sk_path_add_oval(sk_path_t* cpath, const sk_rect_t* crect, sk_path_direction_t cdir) {
281     SkPath::Direction dir;
282     if (!from_c_path_direction(cdir, &dir)) {
283         return;
284     }
285     as_path(cpath)->addOval(AsRect(*crect), dir);
286 }
287 
sk_path_get_bounds(const sk_path_t * cpath,sk_rect_t * crect)288 bool sk_path_get_bounds(const sk_path_t* cpath, sk_rect_t* crect) {
289     const SkPath& path = AsPath(*cpath);
290 
291     if (path.isEmpty()) {
292         if (crect) {
293             *crect = ToRect(SkRect::MakeEmpty());
294         }
295         return false;
296     }
297 
298     if (crect) {
299         *crect = ToRect(path.getBounds());
300     }
301     return true;
302 }
303 
304 ///////////////////////////////////////////////////////////////////////////////////////////
305 
sk_canvas_save(sk_canvas_t * ccanvas)306 void sk_canvas_save(sk_canvas_t* ccanvas) {
307     AsCanvas(ccanvas)->save();
308 }
309 
sk_canvas_save_layer(sk_canvas_t * ccanvas,const sk_rect_t * crect,const sk_paint_t * cpaint)310 void sk_canvas_save_layer(sk_canvas_t* ccanvas, const sk_rect_t* crect, const sk_paint_t* cpaint) {
311     AsCanvas(ccanvas)->drawRect(AsRect(*crect), AsPaint(*cpaint));
312 }
313 
sk_canvas_restore(sk_canvas_t * ccanvas)314 void sk_canvas_restore(sk_canvas_t* ccanvas) {
315     AsCanvas(ccanvas)->restore();
316 }
317 
sk_canvas_translate(sk_canvas_t * ccanvas,float dx,float dy)318 void sk_canvas_translate(sk_canvas_t* ccanvas, float dx, float dy) {
319     AsCanvas(ccanvas)->translate(dx, dy);
320 }
321 
sk_canvas_scale(sk_canvas_t * ccanvas,float sx,float sy)322 void sk_canvas_scale(sk_canvas_t* ccanvas, float sx, float sy) {
323     AsCanvas(ccanvas)->scale(sx, sy);
324 }
325 
sk_canvas_rotate_degress(sk_canvas_t * ccanvas,float degrees)326 void sk_canvas_rotate_degress(sk_canvas_t* ccanvas, float degrees) {
327     AsCanvas(ccanvas)->rotate(degrees);
328 }
329 
sk_canvas_rotate_radians(sk_canvas_t * ccanvas,float radians)330 void sk_canvas_rotate_radians(sk_canvas_t* ccanvas, float radians) {
331     AsCanvas(ccanvas)->rotate(SkRadiansToDegrees(radians));
332 }
333 
sk_canvas_skew(sk_canvas_t * ccanvas,float sx,float sy)334 void sk_canvas_skew(sk_canvas_t* ccanvas, float sx, float sy) {
335     AsCanvas(ccanvas)->skew(sx, sy);
336 }
337 
sk_canvas_concat(sk_canvas_t * ccanvas,const sk_matrix_t * cmatrix)338 void sk_canvas_concat(sk_canvas_t* ccanvas, const sk_matrix_t* cmatrix) {
339     SkASSERT(cmatrix);
340     SkMatrix matrix;
341     from_c_matrix(cmatrix, &matrix);
342     AsCanvas(ccanvas)->concat(matrix);
343 }
344 
sk_canvas_clip_rect(sk_canvas_t * ccanvas,const sk_rect_t * crect)345 void sk_canvas_clip_rect(sk_canvas_t* ccanvas, const sk_rect_t* crect) {
346     AsCanvas(ccanvas)->clipRect(AsRect(*crect));
347 }
348 
sk_canvas_clip_path(sk_canvas_t * ccanvas,const sk_path_t * cpath)349 void sk_canvas_clip_path(sk_canvas_t* ccanvas, const sk_path_t* cpath) {
350     AsCanvas(ccanvas)->clipPath(AsPath(*cpath));
351 }
352 
sk_canvas_draw_paint(sk_canvas_t * ccanvas,const sk_paint_t * cpaint)353 void sk_canvas_draw_paint(sk_canvas_t* ccanvas, const sk_paint_t* cpaint) {
354     AsCanvas(ccanvas)->drawPaint(AsPaint(*cpaint));
355 }
356 
sk_canvas_draw_rect(sk_canvas_t * ccanvas,const sk_rect_t * crect,const sk_paint_t * cpaint)357 void sk_canvas_draw_rect(sk_canvas_t* ccanvas, const sk_rect_t* crect, const sk_paint_t* cpaint) {
358     AsCanvas(ccanvas)->drawRect(AsRect(*crect), AsPaint(*cpaint));
359 }
360 
sk_canvas_draw_oval(sk_canvas_t * ccanvas,const sk_rect_t * crect,const sk_paint_t * cpaint)361 void sk_canvas_draw_oval(sk_canvas_t* ccanvas, const sk_rect_t* crect, const sk_paint_t* cpaint) {
362     AsCanvas(ccanvas)->drawOval(AsRect(*crect), AsPaint(*cpaint));
363 }
364 
sk_canvas_draw_path(sk_canvas_t * ccanvas,const sk_path_t * cpath,const sk_paint_t * cpaint)365 void sk_canvas_draw_path(sk_canvas_t* ccanvas, const sk_path_t* cpath, const sk_paint_t* cpaint) {
366     AsCanvas(ccanvas)->drawPath(AsPath(*cpath), AsPaint(*cpaint));
367 }
368 
sk_canvas_draw_image(sk_canvas_t * ccanvas,const sk_image_t * cimage,float x,float y,const sk_paint_t * cpaint)369 void sk_canvas_draw_image(sk_canvas_t* ccanvas, const sk_image_t* cimage, float x, float y,
370                           const sk_paint_t* cpaint) {
371     AsCanvas(ccanvas)->drawImage(AsImage(cimage), x, y, AsPaint(cpaint));
372 }
373 
sk_canvas_draw_image_rect(sk_canvas_t * ccanvas,const sk_image_t * cimage,const sk_rect_t * csrcR,const sk_rect_t * cdstR,const sk_paint_t * cpaint)374 void sk_canvas_draw_image_rect(sk_canvas_t* ccanvas, const sk_image_t* cimage,
375                                const sk_rect_t* csrcR, const sk_rect_t* cdstR,
376                                const sk_paint_t* cpaint) {
377     AsCanvas(ccanvas)->drawImageRect(AsImage(cimage), AsRect(csrcR), AsRect(*cdstR), AsPaint(cpaint));
378 }
379 
sk_canvas_draw_picture(sk_canvas_t * ccanvas,const sk_picture_t * cpicture,const sk_matrix_t * cmatrix,const sk_paint_t * cpaint)380 void sk_canvas_draw_picture(sk_canvas_t* ccanvas, const sk_picture_t* cpicture,
381                             const sk_matrix_t* cmatrix, const sk_paint_t* cpaint) {
382     const SkMatrix* matrixPtr = NULL;
383     SkMatrix matrix;
384     if (cmatrix) {
385         from_c_matrix(cmatrix, &matrix);
386         matrixPtr = &matrix;
387     }
388     AsCanvas(ccanvas)->drawPicture(AsPicture(cpicture), matrixPtr, AsPaint(cpaint));
389 }
390 
391 ///////////////////////////////////////////////////////////////////////////////////////////
392 
sk_surface_new_raster(const sk_imageinfo_t * cinfo)393 sk_surface_t* sk_surface_new_raster(const sk_imageinfo_t* cinfo) {
394     SkImageInfo info;
395     if (!from_c_info(*cinfo, &info)) {
396         return NULL;
397     }
398     return (sk_surface_t*)SkSurface::NewRaster(info);
399 }
400 
sk_surface_new_raster_direct(const sk_imageinfo_t * cinfo,void * pixels,size_t rowBytes)401 sk_surface_t* sk_surface_new_raster_direct(const sk_imageinfo_t* cinfo, void* pixels,
402                                            size_t rowBytes) {
403     SkImageInfo info;
404     if (!from_c_info(*cinfo, &info)) {
405         return NULL;
406     }
407     return (sk_surface_t*)SkSurface::NewRasterDirect(info, pixels, rowBytes);
408 }
409 
sk_surface_unref(sk_surface_t * csurf)410 void sk_surface_unref(sk_surface_t* csurf) {
411     SkSafeUnref((SkSurface*)csurf);
412 }
413 
sk_surface_get_canvas(sk_surface_t * csurf)414 sk_canvas_t* sk_surface_get_canvas(sk_surface_t* csurf) {
415     SkSurface* surf = (SkSurface*)csurf;
416     return (sk_canvas_t*)surf->getCanvas();
417 }
418 
sk_surface_new_image_snapshot(sk_surface_t * csurf)419 sk_image_t* sk_surface_new_image_snapshot(sk_surface_t* csurf) {
420     SkSurface* surf = (SkSurface*)csurf;
421     return (sk_image_t*)surf->newImageSnapshot();
422 }
423 
424 ///////////////////////////////////////////////////////////////////////////////////////////
425 
sk_picture_recorder_new()426 sk_picture_recorder_t* sk_picture_recorder_new() {
427     return ToPictureRecorder(new SkPictureRecorder);
428 }
429 
sk_picture_recorder_delete(sk_picture_recorder_t * crec)430 void sk_picture_recorder_delete(sk_picture_recorder_t* crec) {
431     delete AsPictureRecorder(crec);
432 }
433 
sk_picture_recorder_begin_recording(sk_picture_recorder_t * crec,const sk_rect_t * cbounds)434 sk_canvas_t* sk_picture_recorder_begin_recording(sk_picture_recorder_t* crec,
435                                                  const sk_rect_t* cbounds) {
436     return ToCanvas(AsPictureRecorder(crec)->beginRecording(AsRect(*cbounds)));
437 }
438 
sk_picture_recorder_end_recording(sk_picture_recorder_t * crec)439 sk_picture_t* sk_picture_recorder_end_recording(sk_picture_recorder_t* crec) {
440     return ToPicture(AsPictureRecorder(crec)->endRecording());
441 }
442 
sk_picture_ref(sk_picture_t * cpic)443 void sk_picture_ref(sk_picture_t* cpic) {
444     SkSafeRef(AsPicture(cpic));
445 }
446 
sk_picture_unref(sk_picture_t * cpic)447 void sk_picture_unref(sk_picture_t* cpic) {
448     SkSafeUnref(AsPicture(cpic));
449 }
450 
sk_picture_get_unique_id(sk_picture_t * cpic)451 uint32_t sk_picture_get_unique_id(sk_picture_t* cpic) {
452     return AsPicture(cpic)->uniqueID();
453 }
454 
sk_picture_get_bounds(sk_picture_t * cpic)455 sk_rect_t sk_picture_get_bounds(sk_picture_t* cpic) {
456     return ToRect(AsPicture(cpic)->cullRect());
457 }
458 
459 ///////////////////////////////////////////////////////////////////////////////////////////
460 
461 #include "../../include/effects/SkGradientShader.h"
462 #include "sk_shader.h"
463 
464 const struct {
465     sk_shader_tilemode_t    fC;
466     SkShader::TileMode      fSK;
467 } gTileModeMap[] = {
468     { CLAMP_SK_SHADER_TILEMODE,     SkShader::kClamp_TileMode },
469     { REPEAT_SK_SHADER_TILEMODE,    SkShader::kRepeat_TileMode },
470     { MIRROR_SK_SHADER_TILEMODE,    SkShader::kMirror_TileMode  },
471 };
472 
from_c_tilemode(sk_shader_tilemode_t cMode,SkShader::TileMode * skMode)473 static bool from_c_tilemode(sk_shader_tilemode_t cMode, SkShader::TileMode* skMode) {
474     for (size_t i = 0; i < SK_ARRAY_COUNT(gTileModeMap); ++i) {
475         if (cMode == gTileModeMap[i].fC) {
476             if (skMode) {
477                 *skMode = gTileModeMap[i].fSK;
478             }
479             return true;
480         }
481     }
482     return false;
483 }
484 
sk_shader_ref(sk_shader_t * cshader)485 void sk_shader_ref(sk_shader_t* cshader) {
486     SkSafeRef(AsShader(cshader));
487 }
488 
sk_shader_unref(sk_shader_t * cshader)489 void sk_shader_unref(sk_shader_t* cshader) {
490     SkSafeUnref(AsShader(cshader));
491 }
492 
sk_shader_new_linear_gradient(const sk_point_t pts[2],const sk_color_t colors[],const float colorPos[],int colorCount,sk_shader_tilemode_t cmode,const sk_matrix_t * cmatrix)493 sk_shader_t* sk_shader_new_linear_gradient(const sk_point_t pts[2],
494                                            const sk_color_t colors[],
495                                            const float colorPos[],
496                                            int colorCount,
497                                            sk_shader_tilemode_t cmode,
498                                            const sk_matrix_t* cmatrix) {
499     SkShader::TileMode mode;
500     if (!from_c_tilemode(cmode, &mode)) {
501         return NULL;
502     }
503     SkMatrix matrix;
504     if (cmatrix) {
505         from_c_matrix(cmatrix, &matrix);
506     } else {
507         matrix.setIdentity();
508     }
509     SkShader* s = SkGradientShader::CreateLinear(reinterpret_cast<const SkPoint*>(pts),
510                                                  reinterpret_cast<const SkColor*>(colors),
511                                                  colorPos, colorCount, mode, 0, &matrix);
512     return (sk_shader_t*)s;
513 }
514 
515 ///////////////////////////////////////////////////////////////////////////////////////////
516 
517 #include "../../include/effects/SkBlurMaskFilter.h"
518 #include "sk_maskfilter.h"
519 
520 const struct {
521     sk_blurstyle_t  fC;
522     SkBlurStyle     fSk;
523 } gBlurStylePairs[] = {
524     { NORMAL_SK_BLUR_STYLE, kNormal_SkBlurStyle },
525     { SOLID_SK_BLUR_STYLE,  kSolid_SkBlurStyle },
526     { OUTER_SK_BLUR_STYLE,  kOuter_SkBlurStyle },
527     { INNER_SK_BLUR_STYLE,  kInner_SkBlurStyle },
528 };
529 
find_blurstyle(sk_blurstyle_t csrc,SkBlurStyle * dst)530 static bool find_blurstyle(sk_blurstyle_t csrc, SkBlurStyle* dst) {
531     for (size_t i = 0; i < SK_ARRAY_COUNT(gBlurStylePairs); ++i) {
532         if (gBlurStylePairs[i].fC == csrc) {
533             if (dst) {
534                 *dst = gBlurStylePairs[i].fSk;
535             }
536             return true;
537         }
538     }
539     return false;
540 }
541 
sk_maskfilter_ref(sk_maskfilter_t * cfilter)542 void sk_maskfilter_ref(sk_maskfilter_t* cfilter) {
543     SkSafeRef(AsMaskFilter(cfilter));
544 }
545 
sk_maskfilter_unref(sk_maskfilter_t * cfilter)546 void sk_maskfilter_unref(sk_maskfilter_t* cfilter) {
547     SkSafeUnref(AsMaskFilter(cfilter));
548 }
549 
sk_maskfilter_new_blur(sk_blurstyle_t cstyle,float sigma)550 sk_maskfilter_t* sk_maskfilter_new_blur(sk_blurstyle_t cstyle, float sigma) {
551     SkBlurStyle style;
552     if (!find_blurstyle(cstyle, &style)) {
553         return NULL;
554     }
555     return ToMaskFilter(SkBlurMaskFilter::Create(style, sigma));
556 }
557 
558 ///////////////////////////////////////////////////////////////////////////////////////////
559 
sk_data_new_with_copy(const void * src,size_t length)560 sk_data_t* sk_data_new_with_copy(const void* src, size_t length) {
561     return ToData(SkData::NewWithCopy(src, length));
562 }
563 
sk_data_new_from_malloc(const void * memory,size_t length)564 sk_data_t* sk_data_new_from_malloc(const void* memory, size_t length) {
565     return ToData(SkData::NewFromMalloc(memory, length));
566 }
567 
sk_data_new_subset(const sk_data_t * csrc,size_t offset,size_t length)568 sk_data_t* sk_data_new_subset(const sk_data_t* csrc, size_t offset, size_t length) {
569     return ToData(SkData::NewSubset(AsData(csrc), offset, length));
570 }
571 
sk_data_ref(const sk_data_t * cdata)572 void sk_data_ref(const sk_data_t* cdata) {
573     SkSafeRef(AsData(cdata));
574 }
575 
sk_data_unref(const sk_data_t * cdata)576 void sk_data_unref(const sk_data_t* cdata) {
577     SkSafeUnref(AsData(cdata));
578 }
579 
sk_data_get_size(const sk_data_t * cdata)580 size_t sk_data_get_size(const sk_data_t* cdata) {
581     return AsData(cdata)->size();
582 }
583 
sk_data_get_data(const sk_data_t * cdata)584 const void* sk_data_get_data(const sk_data_t* cdata) {
585     return AsData(cdata)->data();
586 }
587 
588 ///////////////////////////////////////////////////////////////////////////////////////////
589 ///////////////////////////////////////////////////////////////////////////////////////////
590 
sk_test_capi(SkCanvas * canvas)591 void sk_test_capi(SkCanvas* canvas) {
592     sk_imageinfo_t cinfo;
593     cinfo.width = 100;
594     cinfo.height = 100;
595     cinfo.colorType = (sk_colortype_t)kN32_SkColorType;
596     cinfo.alphaType = (sk_alphatype_t)kPremul_SkAlphaType;
597 
598     sk_surface_t* csurface = sk_surface_new_raster(&cinfo);
599     sk_canvas_t* ccanvas = sk_surface_get_canvas(csurface);
600 
601     sk_paint_t* cpaint = sk_paint_new();
602     sk_paint_set_antialias(cpaint, true);
603     sk_paint_set_color(cpaint, 0xFFFF0000);
604 
605     sk_rect_t cr = { 5, 5, 95, 95 };
606     sk_canvas_draw_oval(ccanvas, &cr, cpaint);
607 
608     cr.left += 25;
609     cr.top += 25;
610     cr.right -= 25;
611     cr.bottom -= 25;
612     sk_paint_set_color(cpaint, 0xFF00FF00);
613     sk_canvas_draw_rect(ccanvas, &cr, cpaint);
614 
615     sk_path_t* cpath = sk_path_new();
616     sk_path_move_to(cpath, 50, 50);
617     sk_path_line_to(cpath, 100, 100);
618     sk_path_line_to(cpath, 50, 100);
619     sk_path_close(cpath);
620 
621     sk_canvas_draw_path(ccanvas, cpath, cpaint);
622 
623     sk_image_t* cimage = sk_surface_new_image_snapshot(csurface);
624 
625     // HERE WE CROSS THE C..C++ boundary
626     canvas->drawImage((const SkImage*)cimage, 20, 20, NULL);
627 
628     sk_path_delete(cpath);
629     sk_paint_delete(cpaint);
630     sk_image_unref(cimage);
631     sk_surface_unref(csurface);
632 }
633