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