blob: 94e925ada4e558b0b608187daf0bc0a5bbd663fd [file] [log] [blame]
reed8e474782014-10-06 11:00:51 -07001/*
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
reed73c25012014-11-17 06:15:42 -08008#include "sk_canvas.h"
9#include "sk_image.h"
10#include "sk_paint.h"
11#include "sk_path.h"
reed938dfba2014-10-06 06:08:16 -070012#include "sk_surface.h"
13
14#include "SkCanvas.h"
15#include "SkImage.h"
16#include "SkMatrix.h"
17#include "SkPaint.h"
18#include "SkPath.h"
19#include "SkSurface.h"
20
reede3323962014-10-24 11:16:19 -070021const struct {
22 sk_colortype_t fC;
23 SkColorType fSK;
24} gColorTypeMap[] = {
25 { UNKNOWN_SK_COLORTYPE, kUnknown_SkColorType },
26 { RGBA_8888_SK_COLORTYPE, kRGBA_8888_SkColorType },
27 { BGRA_8888_SK_COLORTYPE, kBGRA_8888_SkColorType },
28 { ALPHA_8_SK_COLORTYPE, kAlpha_8_SkColorType },
29};
30
31const struct {
32 sk_alphatype_t fC;
33 SkAlphaType fSK;
34} gAlphaTypeMap[] = {
35 { OPAQUE_SK_ALPHATYPE, kOpaque_SkAlphaType },
36 { PREMUL_SK_ALPHATYPE, kPremul_SkAlphaType },
37 { UNPREMUL_SK_ALPHATYPE, kUnpremul_SkAlphaType },
38};
39
40static bool from_c_colortype(sk_colortype_t cCT, SkColorType* skCT) {
41 for (size_t i = 0; i < SK_ARRAY_COUNT(gColorTypeMap); ++i) {
42 if (gColorTypeMap[i].fC == cCT) {
43 if (skCT) {
44 *skCT = gColorTypeMap[i].fSK;
45 }
46 return true;
47 }
48 }
49 return false;
50}
51
52static bool to_c_colortype(SkColorType skCT, sk_colortype_t* cCT) {
53 for (size_t i = 0; i < SK_ARRAY_COUNT(gColorTypeMap); ++i) {
54 if (gColorTypeMap[i].fSK == skCT) {
55 if (cCT) {
56 *cCT = gColorTypeMap[i].fC;
57 }
58 return true;
59 }
60 }
61 return false;
62}
63
64static bool from_c_alphatype(sk_alphatype_t cAT, SkAlphaType* skAT) {
65 for (size_t i = 0; i < SK_ARRAY_COUNT(gAlphaTypeMap); ++i) {
66 if (gAlphaTypeMap[i].fC == cAT) {
67 if (skAT) {
68 *skAT = gAlphaTypeMap[i].fSK;
69 }
70 return true;
71 }
72 }
73 return false;
74}
75
76static bool from_c_info(const sk_imageinfo_t& cinfo, SkImageInfo* info) {
77 SkColorType ct;
78 SkAlphaType at;
79
80 if (!from_c_colortype(cinfo.colorType, &ct)) {
81 // optionally report error to client?
82 return false;
83 }
84 if (!from_c_alphatype(cinfo.alphaType, &at)) {
85 // optionally report error to client?
86 return false;
87 }
88 if (info) {
89 *info = SkImageInfo::Make(cinfo.width, cinfo.height, ct, at);
90 }
91 return true;
reed938dfba2014-10-06 06:08:16 -070092}
93
abarth9503ac72014-12-02 15:47:33 -080094static void from_c_matrix(const sk_matrix_t* cmatrix, SkMatrix* matrix) {
95 matrix->setAll(cmatrix->mat[0], cmatrix->mat[1], cmatrix->mat[2],
96 cmatrix->mat[3], cmatrix->mat[4], cmatrix->mat[5],
97 cmatrix->mat[6], cmatrix->mat[7], cmatrix->mat[8]);
98}
99
reed73c25012014-11-17 06:15:42 -0800100const struct {
101 sk_path_direction_t fC;
102 SkPath::Direction fSk;
103} gPathDirMap[] = {
104 { CW_SK_PATH_DIRECTION, SkPath::kCW_Direction },
105 { CCW_SK_PATH_DIRECTION, SkPath::kCCW_Direction },
106};
107
108static bool from_c_path_direction(sk_path_direction_t cdir, SkPath::Direction* dir) {
109 for (size_t i = 0; i < SK_ARRAY_COUNT(gPathDirMap); ++i) {
110 if (gPathDirMap[i].fC == cdir) {
111 if (dir) {
112 *dir = gPathDirMap[i].fSk;
113 }
114 return true;
115 }
116 }
117 return false;
118}
119
reed8e474782014-10-06 11:00:51 -0700120static const SkRect& AsRect(const sk_rect_t& crect) {
121 return reinterpret_cast<const SkRect&>(crect);
122}
123
reed73c25012014-11-17 06:15:42 -0800124static SkRect* as_rect(sk_rect_t* crect) {
125 return reinterpret_cast<SkRect*>(crect);
126}
127
reed8e474782014-10-06 11:00:51 -0700128static const SkPath& AsPath(const sk_path_t& cpath) {
129 return reinterpret_cast<const SkPath&>(cpath);
130}
131
robertphillipsa624e872014-10-08 06:04:35 -0700132static SkPath* as_path(sk_path_t* cpath) {
133 return reinterpret_cast<SkPath*>(cpath);
134}
135
reed8e474782014-10-06 11:00:51 -0700136static const SkImage* AsImage(const sk_image_t* cimage) {
137 return reinterpret_cast<const SkImage*>(cimage);
138}
reed938dfba2014-10-06 06:08:16 -0700139
140static const SkPaint& AsPaint(const sk_paint_t& cpaint) {
reed8e474782014-10-06 11:00:51 -0700141 return reinterpret_cast<const SkPaint&>(cpaint);
reed938dfba2014-10-06 06:08:16 -0700142}
143
144static const SkPaint* AsPaint(const sk_paint_t* cpaint) {
reed8e474782014-10-06 11:00:51 -0700145 return reinterpret_cast<const SkPaint*>(cpaint);
reed938dfba2014-10-06 06:08:16 -0700146}
147
reed8e474782014-10-06 11:00:51 -0700148static SkPaint* AsPaint(sk_paint_t* cpaint) {
149 return reinterpret_cast<SkPaint*>(cpaint);
150}
151
152static SkCanvas* AsCanvas(sk_canvas_t* ccanvas) {
153 return reinterpret_cast<SkCanvas*>(ccanvas);
154}
155
reedafa278e2014-11-24 19:11:48 -0800156static SkShader* AsShader(sk_shader_t* cshader) {
157 return reinterpret_cast<SkShader*>(cshader);
158}
159
reed8e474782014-10-06 11:00:51 -0700160///////////////////////////////////////////////////////////////////////////////////////////
161
reede3323962014-10-24 11:16:19 -0700162sk_colortype_t sk_colortype_get_default_8888() {
163 sk_colortype_t ct;
164 if (!to_c_colortype(kN32_SkColorType, &ct)) {
165 ct = UNKNOWN_SK_COLORTYPE;
166 }
167 return ct;
168}
169
170///////////////////////////////////////////////////////////////////////////////////////////
171
reed8e474782014-10-06 11:00:51 -0700172sk_image_t* sk_image_new_raster_copy(const sk_imageinfo_t* cinfo, const void* pixels,
173 size_t rowBytes) {
reede3323962014-10-24 11:16:19 -0700174 SkImageInfo info;
175 if (!from_c_info(*cinfo, &info)) {
176 return NULL;
177 }
178 return (sk_image_t*)SkImage::NewRasterCopy(info, pixels, rowBytes);
reed8e474782014-10-06 11:00:51 -0700179}
180
181void sk_image_ref(const sk_image_t* cimage) {
182 AsImage(cimage)->ref();
183}
184
185void sk_image_unref(const sk_image_t* cimage) {
186 AsImage(cimage)->unref();
187}
188
189int sk_image_get_width(const sk_image_t* cimage) {
190 return AsImage(cimage)->width();
191}
192
193int sk_image_get_height(const sk_image_t* cimage) {
194 return AsImage(cimage)->height();
195}
196
197uint32_t sk_image_get_unique_id(const sk_image_t* cimage) {
198 return AsImage(cimage)->uniqueID();
199}
200
201///////////////////////////////////////////////////////////////////////////////////////////
202
203sk_paint_t* sk_paint_new() {
204 return (sk_paint_t*)SkNEW(SkPaint);
205}
206
207void sk_paint_delete(sk_paint_t* cpaint) {
208 SkDELETE(AsPaint(cpaint));
209}
210
211bool sk_paint_is_antialias(const sk_paint_t* cpaint) {
212 return AsPaint(*cpaint).isAntiAlias();
213}
214
215void sk_paint_set_antialias(sk_paint_t* cpaint, bool aa) {
216 AsPaint(cpaint)->setAntiAlias(aa);
217}
218
219sk_color_t sk_paint_get_color(const sk_paint_t* cpaint) {
220 return AsPaint(*cpaint).getColor();
221}
222
223void sk_paint_set_color(sk_paint_t* cpaint, sk_color_t c) {
224 AsPaint(cpaint)->setColor(c);
225}
reed938dfba2014-10-06 06:08:16 -0700226
reedafa278e2014-11-24 19:11:48 -0800227void sk_paint_set_shader(sk_paint_t* cpaint, sk_shader_t* cshader) {
228 AsPaint(cpaint)->setShader(AsShader(cshader));
229}
230
reed938dfba2014-10-06 06:08:16 -0700231///////////////////////////////////////////////////////////////////////////////////////////
232
robertphillipsa624e872014-10-08 06:04:35 -0700233sk_path_t* sk_path_new() {
234 return (sk_path_t*)SkNEW(SkPath);
235}
236
237void sk_path_delete(sk_path_t* cpath) {
238 SkDELETE(as_path(cpath));
239}
240
241void sk_path_move_to(sk_path_t* cpath, float x, float y) {
242 as_path(cpath)->moveTo(x, y);
243}
244
245void sk_path_line_to(sk_path_t* cpath, float x, float y) {
246 as_path(cpath)->lineTo(x, y);
247}
248
249void sk_path_quad_to(sk_path_t* cpath, float x0, float y0, float x1, float y1) {
250 as_path(cpath)->quadTo(x0, y0, x1, y1);
251}
252
reed73c25012014-11-17 06:15:42 -0800253void sk_path_conic_to(sk_path_t* cpath, float x0, float y0, float x1, float y1, float w) {
254 as_path(cpath)->conicTo(x0, y0, x1, y1, w);
255}
256
257void sk_path_cubic_to(sk_path_t* cpath, float x0, float y0, float x1, float y1, float x2, float y2) {
258 as_path(cpath)->cubicTo(x0, y0, x1, y1, x2, y2);
259}
260
robertphillipsa624e872014-10-08 06:04:35 -0700261void sk_path_close(sk_path_t* cpath) {
262 as_path(cpath)->close();
263}
264
reed73c25012014-11-17 06:15:42 -0800265void sk_path_add_rect(sk_path_t* cpath, const sk_rect_t* crect, sk_path_direction_t cdir) {
266 SkPath::Direction dir;
267 if (!from_c_path_direction(cdir, &dir)) {
268 return;
269 }
270 as_path(cpath)->addRect(AsRect(*crect), dir);
271}
272
273void sk_path_add_oval(sk_path_t* cpath, const sk_rect_t* crect, sk_path_direction_t cdir) {
274 SkPath::Direction dir;
275 if (!from_c_path_direction(cdir, &dir)) {
276 return;
277 }
278 as_path(cpath)->addOval(AsRect(*crect), dir);
279}
280
281bool sk_path_get_bounds(const sk_path_t* cpath, sk_rect_t* crect) {
282 const SkPath& path = AsPath(*cpath);
283 SkRect* rect = as_rect(crect);
284
285 if (path.isEmpty()) {
286 if (rect) {
287 rect->setEmpty();
288 }
289 return false;
290 }
291 *rect = path.getBounds();
292 return true;
293}
294
robertphillipsa624e872014-10-08 06:04:35 -0700295///////////////////////////////////////////////////////////////////////////////////////////
296
reed938dfba2014-10-06 06:08:16 -0700297void sk_canvas_save(sk_canvas_t* ccanvas) {
298 AsCanvas(ccanvas)->save();
299}
300
301void sk_canvas_save_layer(sk_canvas_t* ccanvas, const sk_rect_t* crect, const sk_paint_t* cpaint) {
302 AsCanvas(ccanvas)->drawRect(AsRect(*crect), AsPaint(*cpaint));
303}
304
305void sk_canvas_restore(sk_canvas_t* ccanvas) {
306 AsCanvas(ccanvas)->restore();
307}
308
309void sk_canvas_translate(sk_canvas_t* ccanvas, float dx, float dy) {
310 AsCanvas(ccanvas)->translate(dx, dy);
311}
312
313void sk_canvas_scale(sk_canvas_t* ccanvas, float sx, float sy) {
reed8e474782014-10-06 11:00:51 -0700314 AsCanvas(ccanvas)->scale(sx, sy);
reed938dfba2014-10-06 06:08:16 -0700315}
316
abarth2fc6ea62014-12-01 14:04:03 -0800317void sk_canvas_rotate_degress(sk_canvas_t* ccanvas, float degrees) {
318 AsCanvas(ccanvas)->rotate(degrees);
319}
320
321void sk_canvas_rotate_radians(sk_canvas_t* ccanvas, float radians) {
322 AsCanvas(ccanvas)->rotate(SkRadiansToDegrees(radians));
323}
324
325void sk_canvas_skew(sk_canvas_t* ccanvas, float sx, float sy) {
326 AsCanvas(ccanvas)->skew(sx, sy);
327}
328
abarth9503ac72014-12-02 15:47:33 -0800329void sk_canvas_concat_matrix(sk_canvas_t* ccanvas, const sk_matrix_t* cmatrix) {
330 SkASSERT(cmatrix);
331 SkMatrix matrix;
332 from_c_matrix(cmatrix, &matrix);
333 AsCanvas(ccanvas)->concat(matrix);
334}
335
reed938dfba2014-10-06 06:08:16 -0700336void sk_canvas_draw_paint(sk_canvas_t* ccanvas, const sk_paint_t* cpaint) {
337 AsCanvas(ccanvas)->drawPaint(AsPaint(*cpaint));
338}
339
340void sk_canvas_draw_rect(sk_canvas_t* ccanvas, const sk_rect_t* crect, const sk_paint_t* cpaint) {
341 AsCanvas(ccanvas)->drawRect(AsRect(*crect), AsPaint(*cpaint));
342}
343
344void sk_canvas_draw_oval(sk_canvas_t* ccanvas, const sk_rect_t* crect, const sk_paint_t* cpaint) {
345 AsCanvas(ccanvas)->drawOval(AsRect(*crect), AsPaint(*cpaint));
346}
347
348void sk_canvas_draw_path(sk_canvas_t* ccanvas, const sk_path_t* cpath, const sk_paint_t* cpaint) {
349 AsCanvas(ccanvas)->drawPath(AsPath(*cpath), AsPaint(*cpaint));
350}
351
352void sk_canvas_draw_image(sk_canvas_t* ccanvas, const sk_image_t* cimage, float x, float y,
353 const sk_paint_t* cpaint) {
354 AsCanvas(ccanvas)->drawImage(AsImage(cimage), x, y, AsPaint(cpaint));
355}
356
357///////////////////////////////////////////////////////////////////////////////////////////
358
reed8e474782014-10-06 11:00:51 -0700359sk_surface_t* sk_surface_new_raster(const sk_imageinfo_t* cinfo) {
reede3323962014-10-24 11:16:19 -0700360 SkImageInfo info;
361 if (!from_c_info(*cinfo, &info)) {
362 return NULL;
363 }
364 return (sk_surface_t*)SkSurface::NewRaster(info);
reed938dfba2014-10-06 06:08:16 -0700365}
366
reed8e474782014-10-06 11:00:51 -0700367sk_surface_t* sk_surface_new_raster_direct(const sk_imageinfo_t* cinfo, void* pixels,
reed938dfba2014-10-06 06:08:16 -0700368 size_t rowBytes) {
reede3323962014-10-24 11:16:19 -0700369 SkImageInfo info;
370 if (!from_c_info(*cinfo, &info)) {
371 return NULL;
372 }
373 return (sk_surface_t*)SkSurface::NewRasterDirect(info, pixels, rowBytes);
reed938dfba2014-10-06 06:08:16 -0700374}
375
reedafa278e2014-11-24 19:11:48 -0800376void sk_surface_unref(sk_surface_t* csurf) {
377 SkSafeUnref((SkSurface*)csurf);
reed938dfba2014-10-06 06:08:16 -0700378}
379
380sk_canvas_t* sk_surface_get_canvas(sk_surface_t* csurf) {
381 SkSurface* surf = (SkSurface*)csurf;
reed8e474782014-10-06 11:00:51 -0700382 return (sk_canvas_t*)surf->getCanvas();
reed938dfba2014-10-06 06:08:16 -0700383}
384
385sk_image_t* sk_surface_new_image_snapshot(sk_surface_t* csurf) {
386 SkSurface* surf = (SkSurface*)csurf;
reed8e474782014-10-06 11:00:51 -0700387 return (sk_image_t*)surf->newImageSnapshot();
reed938dfba2014-10-06 06:08:16 -0700388}
389
reedafa278e2014-11-24 19:11:48 -0800390///////////////////////////////////////////////////////////////////////////////////////////
reed938dfba2014-10-06 06:08:16 -0700391
reedafa278e2014-11-24 19:11:48 -0800392#include "../../include/effects/SkGradientShader.h"
393#include "sk_shader.h"
394
395const struct {
396 sk_shader_tilemode_t fC;
397 SkShader::TileMode fSK;
398} gTileModeMap[] = {
399 { CLAMP_SK_SHADER_TILEMODE, SkShader::kClamp_TileMode },
400 { REPEAT_SK_SHADER_TILEMODE, SkShader::kRepeat_TileMode },
401 { MIRROR_SK_SHADER_TILEMODE, SkShader::kMirror_TileMode },
402};
403
404static bool from_c_tilemode(sk_shader_tilemode_t cMode, SkShader::TileMode* skMode) {
405 for (size_t i = 0; i < SK_ARRAY_COUNT(gTileModeMap); ++i) {
406 if (cMode == gTileModeMap[i].fC) {
407 if (skMode) {
408 *skMode = gTileModeMap[i].fSK;
409 }
410 return true;
411 }
412 }
413 return false;
414}
415
416void sk_shader_ref(sk_shader_t* cshader) {
417 SkSafeRef(AsShader(cshader));
418}
419
420void sk_shader_unref(sk_shader_t* cshader) {
421 SkSafeUnref(AsShader(cshader));
422}
423
424sk_shader_t* sk_shader_new_linear_gradient(const sk_point_t pts[2],
425 const sk_color_t colors[],
426 const float colorPos[],
427 int colorCount,
428 sk_shader_tilemode_t cmode,
429 const sk_matrix_t* cmatrix) {
430 SkShader::TileMode mode;
431 if (!from_c_tilemode(cmode, &mode)) {
432 return NULL;
433 }
434 SkMatrix matrix;
435 if (cmatrix) {
abarth9503ac72014-12-02 15:47:33 -0800436 from_c_matrix(cmatrix, &matrix);
reedafa278e2014-11-24 19:11:48 -0800437 } else {
438 matrix.setIdentity();
439 }
440 SkShader* s = SkGradientShader::CreateLinear(reinterpret_cast<const SkPoint*>(pts),
441 reinterpret_cast<const SkColor*>(colors),
442 colorPos, colorCount, mode, 0, &matrix);
443 return (sk_shader_t*)s;
444}
445
446///////////////////////////////////////////////////////////////////////////////////////////
447///////////////////////////////////////////////////////////////////////////////////////////
reed8e474782014-10-06 11:00:51 -0700448
449void sk_test_capi(SkCanvas* canvas) {
450 sk_imageinfo_t cinfo;
451 cinfo.width = 100;
452 cinfo.height = 100;
453 cinfo.colorType = (sk_colortype_t)kN32_SkColorType;
454 cinfo.alphaType = (sk_alphatype_t)kPremul_SkAlphaType;
455
456 sk_surface_t* csurface = sk_surface_new_raster(&cinfo);
457 sk_canvas_t* ccanvas = sk_surface_get_canvas(csurface);
458
459 sk_paint_t* cpaint = sk_paint_new();
460 sk_paint_set_antialias(cpaint, true);
461 sk_paint_set_color(cpaint, 0xFFFF0000);
462
463 sk_rect_t cr = { 5, 5, 95, 95 };
464 sk_canvas_draw_oval(ccanvas, &cr, cpaint);
465
466 cr.left += 25;
467 cr.top += 25;
468 cr.right -= 25;
469 cr.bottom -= 25;
470 sk_paint_set_color(cpaint, 0xFF00FF00);
471 sk_canvas_draw_rect(ccanvas, &cr, cpaint);
472
robertphillipsa624e872014-10-08 06:04:35 -0700473 sk_path_t* cpath = sk_path_new();
474 sk_path_move_to(cpath, 50, 50);
475 sk_path_line_to(cpath, 100, 100);
476 sk_path_line_to(cpath, 50, 100);
477 sk_path_close(cpath);
478
479 sk_canvas_draw_path(ccanvas, cpath, cpaint);
480
reed8e474782014-10-06 11:00:51 -0700481 sk_image_t* cimage = sk_surface_new_image_snapshot(csurface);
482
483 // HERE WE CROSS THE C..C++ boundary
484 canvas->drawImage((const SkImage*)cimage, 20, 20, NULL);
485
robertphillipsa624e872014-10-08 06:04:35 -0700486 sk_path_delete(cpath);
reed8e474782014-10-06 11:00:51 -0700487 sk_paint_delete(cpaint);
488 sk_image_unref(cimage);
reedafa278e2014-11-24 19:11:48 -0800489 sk_surface_unref(csurface);
reed8e474782014-10-06 11:00:51 -0700490}