blob: c75ab23d55728f67ee0b348ba70bac82a3d24c65 [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
reed73c25012014-11-17 06:15:42 -080094const struct {
95 sk_path_direction_t fC;
96 SkPath::Direction fSk;
97} gPathDirMap[] = {
98 { CW_SK_PATH_DIRECTION, SkPath::kCW_Direction },
99 { CCW_SK_PATH_DIRECTION, SkPath::kCCW_Direction },
100};
101
102static bool from_c_path_direction(sk_path_direction_t cdir, SkPath::Direction* dir) {
103 for (size_t i = 0; i < SK_ARRAY_COUNT(gPathDirMap); ++i) {
104 if (gPathDirMap[i].fC == cdir) {
105 if (dir) {
106 *dir = gPathDirMap[i].fSk;
107 }
108 return true;
109 }
110 }
111 return false;
112}
113
reed8e474782014-10-06 11:00:51 -0700114static const SkRect& AsRect(const sk_rect_t& crect) {
115 return reinterpret_cast<const SkRect&>(crect);
116}
117
reed73c25012014-11-17 06:15:42 -0800118static SkRect* as_rect(sk_rect_t* crect) {
119 return reinterpret_cast<SkRect*>(crect);
120}
121
reed8e474782014-10-06 11:00:51 -0700122static const SkPath& AsPath(const sk_path_t& cpath) {
123 return reinterpret_cast<const SkPath&>(cpath);
124}
125
robertphillipsa624e872014-10-08 06:04:35 -0700126static SkPath* as_path(sk_path_t* cpath) {
127 return reinterpret_cast<SkPath*>(cpath);
128}
129
reed8e474782014-10-06 11:00:51 -0700130static const SkImage* AsImage(const sk_image_t* cimage) {
131 return reinterpret_cast<const SkImage*>(cimage);
132}
reed938dfba2014-10-06 06:08:16 -0700133
134static const SkPaint& AsPaint(const sk_paint_t& cpaint) {
reed8e474782014-10-06 11:00:51 -0700135 return reinterpret_cast<const SkPaint&>(cpaint);
reed938dfba2014-10-06 06:08:16 -0700136}
137
138static const SkPaint* AsPaint(const sk_paint_t* cpaint) {
reed8e474782014-10-06 11:00:51 -0700139 return reinterpret_cast<const SkPaint*>(cpaint);
reed938dfba2014-10-06 06:08:16 -0700140}
141
reed8e474782014-10-06 11:00:51 -0700142static SkPaint* AsPaint(sk_paint_t* cpaint) {
143 return reinterpret_cast<SkPaint*>(cpaint);
144}
145
146static SkCanvas* AsCanvas(sk_canvas_t* ccanvas) {
147 return reinterpret_cast<SkCanvas*>(ccanvas);
148}
149
reedafa278e2014-11-24 19:11:48 -0800150static SkShader* AsShader(sk_shader_t* cshader) {
151 return reinterpret_cast<SkShader*>(cshader);
152}
153
reed8e474782014-10-06 11:00:51 -0700154///////////////////////////////////////////////////////////////////////////////////////////
155
reede3323962014-10-24 11:16:19 -0700156sk_colortype_t sk_colortype_get_default_8888() {
157 sk_colortype_t ct;
158 if (!to_c_colortype(kN32_SkColorType, &ct)) {
159 ct = UNKNOWN_SK_COLORTYPE;
160 }
161 return ct;
162}
163
164///////////////////////////////////////////////////////////////////////////////////////////
165
reed8e474782014-10-06 11:00:51 -0700166sk_image_t* sk_image_new_raster_copy(const sk_imageinfo_t* cinfo, const void* pixels,
167 size_t rowBytes) {
reede3323962014-10-24 11:16:19 -0700168 SkImageInfo info;
169 if (!from_c_info(*cinfo, &info)) {
170 return NULL;
171 }
172 return (sk_image_t*)SkImage::NewRasterCopy(info, pixels, rowBytes);
reed8e474782014-10-06 11:00:51 -0700173}
174
175void sk_image_ref(const sk_image_t* cimage) {
176 AsImage(cimage)->ref();
177}
178
179void sk_image_unref(const sk_image_t* cimage) {
180 AsImage(cimage)->unref();
181}
182
183int sk_image_get_width(const sk_image_t* cimage) {
184 return AsImage(cimage)->width();
185}
186
187int sk_image_get_height(const sk_image_t* cimage) {
188 return AsImage(cimage)->height();
189}
190
191uint32_t sk_image_get_unique_id(const sk_image_t* cimage) {
192 return AsImage(cimage)->uniqueID();
193}
194
195///////////////////////////////////////////////////////////////////////////////////////////
196
197sk_paint_t* sk_paint_new() {
198 return (sk_paint_t*)SkNEW(SkPaint);
199}
200
201void sk_paint_delete(sk_paint_t* cpaint) {
202 SkDELETE(AsPaint(cpaint));
203}
204
205bool sk_paint_is_antialias(const sk_paint_t* cpaint) {
206 return AsPaint(*cpaint).isAntiAlias();
207}
208
209void sk_paint_set_antialias(sk_paint_t* cpaint, bool aa) {
210 AsPaint(cpaint)->setAntiAlias(aa);
211}
212
213sk_color_t sk_paint_get_color(const sk_paint_t* cpaint) {
214 return AsPaint(*cpaint).getColor();
215}
216
217void sk_paint_set_color(sk_paint_t* cpaint, sk_color_t c) {
218 AsPaint(cpaint)->setColor(c);
219}
reed938dfba2014-10-06 06:08:16 -0700220
reedafa278e2014-11-24 19:11:48 -0800221void sk_paint_set_shader(sk_paint_t* cpaint, sk_shader_t* cshader) {
222 AsPaint(cpaint)->setShader(AsShader(cshader));
223}
224
reed938dfba2014-10-06 06:08:16 -0700225///////////////////////////////////////////////////////////////////////////////////////////
226
robertphillipsa624e872014-10-08 06:04:35 -0700227sk_path_t* sk_path_new() {
228 return (sk_path_t*)SkNEW(SkPath);
229}
230
231void sk_path_delete(sk_path_t* cpath) {
232 SkDELETE(as_path(cpath));
233}
234
235void sk_path_move_to(sk_path_t* cpath, float x, float y) {
236 as_path(cpath)->moveTo(x, y);
237}
238
239void sk_path_line_to(sk_path_t* cpath, float x, float y) {
240 as_path(cpath)->lineTo(x, y);
241}
242
243void sk_path_quad_to(sk_path_t* cpath, float x0, float y0, float x1, float y1) {
244 as_path(cpath)->quadTo(x0, y0, x1, y1);
245}
246
reed73c25012014-11-17 06:15:42 -0800247void sk_path_conic_to(sk_path_t* cpath, float x0, float y0, float x1, float y1, float w) {
248 as_path(cpath)->conicTo(x0, y0, x1, y1, w);
249}
250
251void sk_path_cubic_to(sk_path_t* cpath, float x0, float y0, float x1, float y1, float x2, float y2) {
252 as_path(cpath)->cubicTo(x0, y0, x1, y1, x2, y2);
253}
254
robertphillipsa624e872014-10-08 06:04:35 -0700255void sk_path_close(sk_path_t* cpath) {
256 as_path(cpath)->close();
257}
258
reed73c25012014-11-17 06:15:42 -0800259void sk_path_add_rect(sk_path_t* cpath, const sk_rect_t* crect, sk_path_direction_t cdir) {
260 SkPath::Direction dir;
261 if (!from_c_path_direction(cdir, &dir)) {
262 return;
263 }
264 as_path(cpath)->addRect(AsRect(*crect), dir);
265}
266
267void sk_path_add_oval(sk_path_t* cpath, const sk_rect_t* crect, sk_path_direction_t cdir) {
268 SkPath::Direction dir;
269 if (!from_c_path_direction(cdir, &dir)) {
270 return;
271 }
272 as_path(cpath)->addOval(AsRect(*crect), dir);
273}
274
275bool sk_path_get_bounds(const sk_path_t* cpath, sk_rect_t* crect) {
276 const SkPath& path = AsPath(*cpath);
277 SkRect* rect = as_rect(crect);
278
279 if (path.isEmpty()) {
280 if (rect) {
281 rect->setEmpty();
282 }
283 return false;
284 }
285 *rect = path.getBounds();
286 return true;
287}
288
robertphillipsa624e872014-10-08 06:04:35 -0700289///////////////////////////////////////////////////////////////////////////////////////////
290
reed938dfba2014-10-06 06:08:16 -0700291void sk_canvas_save(sk_canvas_t* ccanvas) {
292 AsCanvas(ccanvas)->save();
293}
294
295void sk_canvas_save_layer(sk_canvas_t* ccanvas, const sk_rect_t* crect, const sk_paint_t* cpaint) {
296 AsCanvas(ccanvas)->drawRect(AsRect(*crect), AsPaint(*cpaint));
297}
298
299void sk_canvas_restore(sk_canvas_t* ccanvas) {
300 AsCanvas(ccanvas)->restore();
301}
302
303void sk_canvas_translate(sk_canvas_t* ccanvas, float dx, float dy) {
304 AsCanvas(ccanvas)->translate(dx, dy);
305}
306
307void sk_canvas_scale(sk_canvas_t* ccanvas, float sx, float sy) {
reed8e474782014-10-06 11:00:51 -0700308 AsCanvas(ccanvas)->scale(sx, sy);
reed938dfba2014-10-06 06:08:16 -0700309}
310
abarth2fc6ea62014-12-01 14:04:03 -0800311void sk_canvas_rotate_degress(sk_canvas_t* ccanvas, float degrees) {
312 AsCanvas(ccanvas)->rotate(degrees);
313}
314
315void sk_canvas_rotate_radians(sk_canvas_t* ccanvas, float radians) {
316 AsCanvas(ccanvas)->rotate(SkRadiansToDegrees(radians));
317}
318
319void sk_canvas_skew(sk_canvas_t* ccanvas, float sx, float sy) {
320 AsCanvas(ccanvas)->skew(sx, sy);
321}
322
reed938dfba2014-10-06 06:08:16 -0700323void sk_canvas_draw_paint(sk_canvas_t* ccanvas, const sk_paint_t* cpaint) {
324 AsCanvas(ccanvas)->drawPaint(AsPaint(*cpaint));
325}
326
327void sk_canvas_draw_rect(sk_canvas_t* ccanvas, const sk_rect_t* crect, const sk_paint_t* cpaint) {
328 AsCanvas(ccanvas)->drawRect(AsRect(*crect), AsPaint(*cpaint));
329}
330
331void sk_canvas_draw_oval(sk_canvas_t* ccanvas, const sk_rect_t* crect, const sk_paint_t* cpaint) {
332 AsCanvas(ccanvas)->drawOval(AsRect(*crect), AsPaint(*cpaint));
333}
334
335void sk_canvas_draw_path(sk_canvas_t* ccanvas, const sk_path_t* cpath, const sk_paint_t* cpaint) {
336 AsCanvas(ccanvas)->drawPath(AsPath(*cpath), AsPaint(*cpaint));
337}
338
339void sk_canvas_draw_image(sk_canvas_t* ccanvas, const sk_image_t* cimage, float x, float y,
340 const sk_paint_t* cpaint) {
341 AsCanvas(ccanvas)->drawImage(AsImage(cimage), x, y, AsPaint(cpaint));
342}
343
344///////////////////////////////////////////////////////////////////////////////////////////
345
reed8e474782014-10-06 11:00:51 -0700346sk_surface_t* sk_surface_new_raster(const sk_imageinfo_t* cinfo) {
reede3323962014-10-24 11:16:19 -0700347 SkImageInfo info;
348 if (!from_c_info(*cinfo, &info)) {
349 return NULL;
350 }
351 return (sk_surface_t*)SkSurface::NewRaster(info);
reed938dfba2014-10-06 06:08:16 -0700352}
353
reed8e474782014-10-06 11:00:51 -0700354sk_surface_t* sk_surface_new_raster_direct(const sk_imageinfo_t* cinfo, void* pixels,
reed938dfba2014-10-06 06:08:16 -0700355 size_t rowBytes) {
reede3323962014-10-24 11:16:19 -0700356 SkImageInfo info;
357 if (!from_c_info(*cinfo, &info)) {
358 return NULL;
359 }
360 return (sk_surface_t*)SkSurface::NewRasterDirect(info, pixels, rowBytes);
reed938dfba2014-10-06 06:08:16 -0700361}
362
reedafa278e2014-11-24 19:11:48 -0800363void sk_surface_unref(sk_surface_t* csurf) {
364 SkSafeUnref((SkSurface*)csurf);
reed938dfba2014-10-06 06:08:16 -0700365}
366
367sk_canvas_t* sk_surface_get_canvas(sk_surface_t* csurf) {
368 SkSurface* surf = (SkSurface*)csurf;
reed8e474782014-10-06 11:00:51 -0700369 return (sk_canvas_t*)surf->getCanvas();
reed938dfba2014-10-06 06:08:16 -0700370}
371
372sk_image_t* sk_surface_new_image_snapshot(sk_surface_t* csurf) {
373 SkSurface* surf = (SkSurface*)csurf;
reed8e474782014-10-06 11:00:51 -0700374 return (sk_image_t*)surf->newImageSnapshot();
reed938dfba2014-10-06 06:08:16 -0700375}
376
reedafa278e2014-11-24 19:11:48 -0800377///////////////////////////////////////////////////////////////////////////////////////////
reed938dfba2014-10-06 06:08:16 -0700378
reedafa278e2014-11-24 19:11:48 -0800379#include "../../include/effects/SkGradientShader.h"
380#include "sk_shader.h"
381
382const struct {
383 sk_shader_tilemode_t fC;
384 SkShader::TileMode fSK;
385} gTileModeMap[] = {
386 { CLAMP_SK_SHADER_TILEMODE, SkShader::kClamp_TileMode },
387 { REPEAT_SK_SHADER_TILEMODE, SkShader::kRepeat_TileMode },
388 { MIRROR_SK_SHADER_TILEMODE, SkShader::kMirror_TileMode },
389};
390
391static bool from_c_tilemode(sk_shader_tilemode_t cMode, SkShader::TileMode* skMode) {
392 for (size_t i = 0; i < SK_ARRAY_COUNT(gTileModeMap); ++i) {
393 if (cMode == gTileModeMap[i].fC) {
394 if (skMode) {
395 *skMode = gTileModeMap[i].fSK;
396 }
397 return true;
398 }
399 }
400 return false;
401}
402
403void sk_shader_ref(sk_shader_t* cshader) {
404 SkSafeRef(AsShader(cshader));
405}
406
407void sk_shader_unref(sk_shader_t* cshader) {
408 SkSafeUnref(AsShader(cshader));
409}
410
411sk_shader_t* sk_shader_new_linear_gradient(const sk_point_t pts[2],
412 const sk_color_t colors[],
413 const float colorPos[],
414 int colorCount,
415 sk_shader_tilemode_t cmode,
416 const sk_matrix_t* cmatrix) {
417 SkShader::TileMode mode;
418 if (!from_c_tilemode(cmode, &mode)) {
419 return NULL;
420 }
421 SkMatrix matrix;
422 if (cmatrix) {
423 matrix.setAll(cmatrix->mat[0], cmatrix->mat[1], cmatrix->mat[2],
424 cmatrix->mat[3], cmatrix->mat[4], cmatrix->mat[5],
425 cmatrix->mat[6], cmatrix->mat[7], cmatrix->mat[8]);
426 } else {
427 matrix.setIdentity();
428 }
429 SkShader* s = SkGradientShader::CreateLinear(reinterpret_cast<const SkPoint*>(pts),
430 reinterpret_cast<const SkColor*>(colors),
431 colorPos, colorCount, mode, 0, &matrix);
432 return (sk_shader_t*)s;
433}
434
435///////////////////////////////////////////////////////////////////////////////////////////
436///////////////////////////////////////////////////////////////////////////////////////////
reed8e474782014-10-06 11:00:51 -0700437
438void sk_test_capi(SkCanvas* canvas) {
439 sk_imageinfo_t cinfo;
440 cinfo.width = 100;
441 cinfo.height = 100;
442 cinfo.colorType = (sk_colortype_t)kN32_SkColorType;
443 cinfo.alphaType = (sk_alphatype_t)kPremul_SkAlphaType;
444
445 sk_surface_t* csurface = sk_surface_new_raster(&cinfo);
446 sk_canvas_t* ccanvas = sk_surface_get_canvas(csurface);
447
448 sk_paint_t* cpaint = sk_paint_new();
449 sk_paint_set_antialias(cpaint, true);
450 sk_paint_set_color(cpaint, 0xFFFF0000);
451
452 sk_rect_t cr = { 5, 5, 95, 95 };
453 sk_canvas_draw_oval(ccanvas, &cr, cpaint);
454
455 cr.left += 25;
456 cr.top += 25;
457 cr.right -= 25;
458 cr.bottom -= 25;
459 sk_paint_set_color(cpaint, 0xFF00FF00);
460 sk_canvas_draw_rect(ccanvas, &cr, cpaint);
461
robertphillipsa624e872014-10-08 06:04:35 -0700462 sk_path_t* cpath = sk_path_new();
463 sk_path_move_to(cpath, 50, 50);
464 sk_path_line_to(cpath, 100, 100);
465 sk_path_line_to(cpath, 50, 100);
466 sk_path_close(cpath);
467
468 sk_canvas_draw_path(ccanvas, cpath, cpaint);
469
reed8e474782014-10-06 11:00:51 -0700470 sk_image_t* cimage = sk_surface_new_image_snapshot(csurface);
471
472 // HERE WE CROSS THE C..C++ boundary
473 canvas->drawImage((const SkImage*)cimage, 20, 20, NULL);
474
robertphillipsa624e872014-10-08 06:04:35 -0700475 sk_path_delete(cpath);
reed8e474782014-10-06 11:00:51 -0700476 sk_paint_delete(cpaint);
477 sk_image_unref(cimage);
reedafa278e2014-11-24 19:11:48 -0800478 sk_surface_unref(csurface);
reed8e474782014-10-06 11:00:51 -0700479}