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
26const 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
36const 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
45static 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
57static 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
69static 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
81static 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
99static 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
105const 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
113static 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
125static SkData* AsData(const sk_data_t* cdata) {
126    return reinterpret_cast<SkData*>(const_cast<sk_data_t*>(cdata));
127}
128
129static sk_data_t* ToData(SkData* data) {
130    return reinterpret_cast<sk_data_t*>(data);
131}
132
133static sk_rect_t ToRect(const SkRect& rect) {
134    return reinterpret_cast<const sk_rect_t&>(rect);
135}
136
137static const SkRect& AsRect(const sk_rect_t& crect) {
138    return reinterpret_cast<const SkRect&>(crect);
139}
140
141static const SkRect* AsRect(const sk_rect_t* crect) {
142    return reinterpret_cast<const SkRect*>(crect);
143}
144
145static const SkPath& AsPath(const sk_path_t& cpath) {
146    return reinterpret_cast<const SkPath&>(cpath);
147}
148
149static SkPath* as_path(sk_path_t* cpath) {
150    return reinterpret_cast<SkPath*>(cpath);
151}
152
153static const SkImage* AsImage(const sk_image_t* cimage) {
154    return reinterpret_cast<const SkImage*>(cimage);
155}
156
157static sk_image_t* ToImage(SkImage* cimage) {
158    return reinterpret_cast<sk_image_t*>(cimage);
159}
160
161static sk_canvas_t* ToCanvas(SkCanvas* canvas) {
162    return reinterpret_cast<sk_canvas_t*>(canvas);
163}
164
165static SkCanvas* AsCanvas(sk_canvas_t* ccanvas) {
166    return reinterpret_cast<SkCanvas*>(ccanvas);
167}
168
169static SkPictureRecorder* AsPictureRecorder(sk_picture_recorder_t* crec) {
170    return reinterpret_cast<SkPictureRecorder*>(crec);
171}
172
173static sk_picture_recorder_t* ToPictureRecorder(SkPictureRecorder* rec) {
174    return reinterpret_cast<sk_picture_recorder_t*>(rec);
175}
176
177static const SkPicture* AsPicture(const sk_picture_t* cpic) {
178    return reinterpret_cast<const SkPicture*>(cpic);
179}
180
181static SkPicture* AsPicture(sk_picture_t* cpic) {
182    return reinterpret_cast<SkPicture*>(cpic);
183}
184
185static sk_picture_t* ToPicture(SkPicture* pic) {
186    return reinterpret_cast<sk_picture_t*>(pic);
187}
188
189///////////////////////////////////////////////////////////////////////////////////////////
190
191sk_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
201sk_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
210sk_image_t* sk_image_new_from_data(const sk_data_t* cdata) {
211    return ToImage(SkImage::NewFromData(AsData(cdata)));
212}
213
214sk_data_t* sk_image_encode(const sk_image_t* cimage) {
215    return ToData(AsImage(cimage)->encode());
216}
217
218void sk_image_ref(const sk_image_t* cimage) {
219    AsImage(cimage)->ref();
220}
221
222void sk_image_unref(const sk_image_t* cimage) {
223    AsImage(cimage)->unref();
224}
225
226int sk_image_get_width(const sk_image_t* cimage) {
227    return AsImage(cimage)->width();
228}
229
230int sk_image_get_height(const sk_image_t* cimage) {
231    return AsImage(cimage)->height();
232}
233
234uint32_t sk_image_get_unique_id(const sk_image_t* cimage) {
235    return AsImage(cimage)->uniqueID();
236}
237
238///////////////////////////////////////////////////////////////////////////////////////////
239
240sk_path_t* sk_path_new() {
241    return (sk_path_t*)SkNEW(SkPath);
242}
243
244void sk_path_delete(sk_path_t* cpath) {
245    SkDELETE(as_path(cpath));
246}
247
248void sk_path_move_to(sk_path_t* cpath, float x, float y) {
249    as_path(cpath)->moveTo(x, y);
250}
251
252void sk_path_line_to(sk_path_t* cpath, float x, float y) {
253    as_path(cpath)->lineTo(x, y);
254}
255
256void 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
260void 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
264void 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
268void sk_path_close(sk_path_t* cpath) {
269    as_path(cpath)->close();
270}
271
272void 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
280void 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
288bool 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
306void sk_canvas_save(sk_canvas_t* ccanvas) {
307    AsCanvas(ccanvas)->save();
308}
309
310void 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
314void sk_canvas_restore(sk_canvas_t* ccanvas) {
315    AsCanvas(ccanvas)->restore();
316}
317
318void sk_canvas_translate(sk_canvas_t* ccanvas, float dx, float dy) {
319    AsCanvas(ccanvas)->translate(dx, dy);
320}
321
322void sk_canvas_scale(sk_canvas_t* ccanvas, float sx, float sy) {
323    AsCanvas(ccanvas)->scale(sx, sy);
324}
325
326void sk_canvas_rotate_degress(sk_canvas_t* ccanvas, float degrees) {
327    AsCanvas(ccanvas)->rotate(degrees);
328}
329
330void sk_canvas_rotate_radians(sk_canvas_t* ccanvas, float radians) {
331    AsCanvas(ccanvas)->rotate(SkRadiansToDegrees(radians));
332}
333
334void sk_canvas_skew(sk_canvas_t* ccanvas, float sx, float sy) {
335    AsCanvas(ccanvas)->skew(sx, sy);
336}
337
338void 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
345void sk_canvas_clip_rect(sk_canvas_t* ccanvas, const sk_rect_t* crect) {
346    AsCanvas(ccanvas)->clipRect(AsRect(*crect));
347}
348
349void sk_canvas_clip_path(sk_canvas_t* ccanvas, const sk_path_t* cpath) {
350    AsCanvas(ccanvas)->clipPath(AsPath(*cpath));
351}
352
353void sk_canvas_draw_paint(sk_canvas_t* ccanvas, const sk_paint_t* cpaint) {
354    AsCanvas(ccanvas)->drawPaint(AsPaint(*cpaint));
355}
356
357void 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
361void 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
365void 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
369void 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
374void 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
380void 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
393sk_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
401sk_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
410void sk_surface_unref(sk_surface_t* csurf) {
411    SkSafeUnref((SkSurface*)csurf);
412}
413
414sk_canvas_t* sk_surface_get_canvas(sk_surface_t* csurf) {
415    SkSurface* surf = (SkSurface*)csurf;
416    return (sk_canvas_t*)surf->getCanvas();
417}
418
419sk_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
426sk_picture_recorder_t* sk_picture_recorder_new() {
427    return ToPictureRecorder(new SkPictureRecorder);
428}
429
430void sk_picture_recorder_delete(sk_picture_recorder_t* crec) {
431    delete AsPictureRecorder(crec);
432}
433
434sk_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
439sk_picture_t* sk_picture_recorder_end_recording(sk_picture_recorder_t* crec) {
440    return ToPicture(AsPictureRecorder(crec)->endRecording());
441}
442
443void sk_picture_ref(sk_picture_t* cpic) {
444    SkSafeRef(AsPicture(cpic));
445}
446
447void sk_picture_unref(sk_picture_t* cpic) {
448    SkSafeUnref(AsPicture(cpic));
449}
450
451uint32_t sk_picture_get_unique_id(sk_picture_t* cpic) {
452    return AsPicture(cpic)->uniqueID();
453}
454
455sk_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
464const 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
473static 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
485void sk_shader_ref(sk_shader_t* cshader) {
486    SkSafeRef(AsShader(cshader));
487}
488
489void sk_shader_unref(sk_shader_t* cshader) {
490    SkSafeUnref(AsShader(cshader));
491}
492
493sk_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
520const 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
530static 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
542void sk_maskfilter_ref(sk_maskfilter_t* cfilter) {
543    SkSafeRef(AsMaskFilter(cfilter));
544}
545
546void sk_maskfilter_unref(sk_maskfilter_t* cfilter) {
547    SkSafeUnref(AsMaskFilter(cfilter));
548}
549
550sk_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
560sk_data_t* sk_data_new_with_copy(const void* src, size_t length) {
561    return ToData(SkData::NewWithCopy(src, length));
562}
563
564sk_data_t* sk_data_new_from_malloc(const void* memory, size_t length) {
565    return ToData(SkData::NewFromMalloc(memory, length));
566}
567
568sk_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
572void sk_data_ref(const sk_data_t* cdata) {
573    SkSafeRef(AsData(cdata));
574}
575
576void sk_data_unref(const sk_data_t* cdata) {
577    SkSafeUnref(AsData(cdata));
578}
579
580size_t sk_data_get_size(const sk_data_t* cdata) {
581    return AsData(cdata)->size();
582}
583
584const void* sk_data_get_data(const sk_data_t* cdata) {
585    return AsData(cdata)->data();
586}
587
588///////////////////////////////////////////////////////////////////////////////////////////
589///////////////////////////////////////////////////////////////////////////////////////////
590
591void 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