diff --git a/gyp/core.gyp b/gyp/core.gyp index afbc78a4ce..91545ee0c3 100644 --- a/gyp/core.gyp +++ b/gyp/core.gyp @@ -13,6 +13,7 @@ ], 'include_dirs': [ + '../include/c', '../include/config', '../include/core', '../include/pathops', @@ -99,6 +100,7 @@ ], 'direct_dependent_settings': { 'include_dirs': [ + '../include/c', '../include/config', '../include/core', '../include/pathops', diff --git a/gyp/core.gypi b/gyp/core.gypi index 553e36d7ba..9170fabde5 100644 --- a/gyp/core.gypi +++ b/gyp/core.gypi @@ -7,6 +7,9 @@ # { 'sources': [ + '<(skia_src_path)/c/sk_surface.cpp', + '<(skia_include_path)/c/sk_surface.h', + '<(skia_src_path)/core/SkAAClip.cpp', '<(skia_src_path)/core/SkAnnotation.cpp', '<(skia_src_path)/core/SkAdvancedTypefaceMetrics.cpp', diff --git a/gyp/experimental.gyp b/gyp/experimental.gyp index ca21b3b824..c3789fad57 100644 --- a/gyp/experimental.gyp +++ b/gyp/experimental.gyp @@ -12,8 +12,6 @@ '../experimental/SkSetPoly3To3.cpp', '../experimental/SkSetPoly3To3_A.cpp', '../experimental/SkSetPoly3To3_D.cpp', - '../experimental/sk_surface.h', - '../experimental/sk_surface.cpp', ], 'direct_dependent_settings': { 'include_dirs': [ diff --git a/gyp/tests.gypi b/gyp/tests.gypi index b6e060646e..59604db6c5 100644 --- a/gyp/tests.gypi +++ b/gyp/tests.gypi @@ -58,6 +58,7 @@ '../tests/BlendTest.cpp', '../tests/BlitRowTest.cpp', '../tests/BlurTest.cpp', + '../tests/CTest.cpp', '../tests/CachedDataTest.cpp', '../tests/CachedDecodingPixelRefTest.cpp', '../tests/CanvasStateHelpers.cpp', diff --git a/experimental/sk_surface.h b/include/c/sk_surface.h similarity index 86% rename from experimental/sk_surface.h rename to include/c/sk_surface.h index e170049a4b..960c331d2d 100644 --- a/experimental/sk_surface.h +++ b/include/c/sk_surface.h @@ -5,6 +5,9 @@ * found in the LICENSE file. */ +// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL +// DO NOT USE -- FOR INTERNAL TESTING ONLY + #ifndef sk_types_DEFINED #define sk_types_DEFINED @@ -31,10 +34,13 @@ typedef enum { } sk_colortype_t; typedef enum { + OPAQUE_SK_ALPHATYPE, PREMUL_SK_ALPHATYPE, UNPREMUL_SK_ALPHATYPE, } sk_alphatype_t; +sk_colortype_t sk_colortype_get_default_8888(); + typedef struct { int32_t width; int32_t height; @@ -83,6 +89,10 @@ void sk_canvas_draw_oval(sk_canvas_t*, const sk_rect_t*, const sk_paint_t*); void sk_canvas_draw_path(sk_canvas_t*, const sk_path_t*, const sk_paint_t*); void sk_canvas_draw_image(sk_canvas_t*, const sk_image_t*, float x, float y, const sk_paint_t*); +/** + * Return a new image that has made a copy of the provided pixels, or NULL on failure. + * Balance with a call to sk_image_unref(). + */ sk_image_t* sk_image_new_raster_copy(const sk_imageinfo_t*, const void* pixels, size_t rowBytes); void sk_image_ref(const sk_image_t*); void sk_image_unref(const sk_image_t*); @@ -95,6 +105,11 @@ typedef struct sk_surface_t sk_surface_t; sk_surface_t* sk_surface_new_raster(const sk_imageinfo_t*); sk_surface_t* sk_surface_new_raster_direct(const sk_imageinfo_t*, void* pixels, size_t rowBytes); void sk_surface_delete(sk_surface_t*); + +/** + * Return the canvas associated with this surface. Note: the canvas is owned by the surface, + * so the returned object is only valid while the owning surface is valid. + */ sk_canvas_t* sk_surface_get_canvas(sk_surface_t*); sk_image_t* sk_surface_new_image_snapshot(sk_surface_t*); diff --git a/experimental/sk_surface.cpp b/src/c/sk_surface.cpp similarity index 70% rename from experimental/sk_surface.cpp rename to src/c/sk_surface.cpp index ae37c464b2..ec16fc27fb 100644 --- a/experimental/sk_surface.cpp +++ b/src/c/sk_surface.cpp @@ -14,9 +14,77 @@ #include "SkPath.h" #include "SkSurface.h" -static SkImageInfo make(const sk_imageinfo_t& cinfo) { - return SkImageInfo::Make(cinfo.width, cinfo.height, - (SkColorType)cinfo.colorType, (SkAlphaType)cinfo.alphaType); +const struct { + sk_colortype_t fC; + SkColorType fSK; +} gColorTypeMap[] = { + { UNKNOWN_SK_COLORTYPE, kUnknown_SkColorType }, + { RGBA_8888_SK_COLORTYPE, kRGBA_8888_SkColorType }, + { BGRA_8888_SK_COLORTYPE, kBGRA_8888_SkColorType }, + { ALPHA_8_SK_COLORTYPE, kAlpha_8_SkColorType }, +}; + +const struct { + sk_alphatype_t fC; + SkAlphaType fSK; +} gAlphaTypeMap[] = { + { OPAQUE_SK_ALPHATYPE, kOpaque_SkAlphaType }, + { PREMUL_SK_ALPHATYPE, kPremul_SkAlphaType }, + { UNPREMUL_SK_ALPHATYPE, kUnpremul_SkAlphaType }, +}; + +static bool from_c_colortype(sk_colortype_t cCT, SkColorType* skCT) { + for (size_t i = 0; i < SK_ARRAY_COUNT(gColorTypeMap); ++i) { + if (gColorTypeMap[i].fC == cCT) { + if (skCT) { + *skCT = gColorTypeMap[i].fSK; + } + return true; + } + } + return false; +} + +static bool to_c_colortype(SkColorType skCT, sk_colortype_t* cCT) { + for (size_t i = 0; i < SK_ARRAY_COUNT(gColorTypeMap); ++i) { + if (gColorTypeMap[i].fSK == skCT) { + if (cCT) { + *cCT = gColorTypeMap[i].fC; + } + return true; + } + } + return false; +} + +static bool from_c_alphatype(sk_alphatype_t cAT, SkAlphaType* skAT) { + for (size_t i = 0; i < SK_ARRAY_COUNT(gAlphaTypeMap); ++i) { + if (gAlphaTypeMap[i].fC == cAT) { + if (skAT) { + *skAT = gAlphaTypeMap[i].fSK; + } + return true; + } + } + return false; +} + +static bool from_c_info(const sk_imageinfo_t& cinfo, SkImageInfo* info) { + SkColorType ct; + SkAlphaType at; + + if (!from_c_colortype(cinfo.colorType, &ct)) { + // optionally report error to client? + return false; + } + if (!from_c_alphatype(cinfo.alphaType, &at)) { + // optionally report error to client? + return false; + } + if (info) { + *info = SkImageInfo::Make(cinfo.width, cinfo.height, ct, at); + } + return true; } static const SkRect& AsRect(const sk_rect_t& crect) { @@ -53,9 +121,23 @@ static SkCanvas* AsCanvas(sk_canvas_t* ccanvas) { /////////////////////////////////////////////////////////////////////////////////////////// +sk_colortype_t sk_colortype_get_default_8888() { + sk_colortype_t ct; + if (!to_c_colortype(kN32_SkColorType, &ct)) { + ct = UNKNOWN_SK_COLORTYPE; + } + return ct; +} + +/////////////////////////////////////////////////////////////////////////////////////////// + sk_image_t* sk_image_new_raster_copy(const sk_imageinfo_t* cinfo, const void* pixels, size_t rowBytes) { - return (sk_image_t*)SkImage::NewRasterCopy(make(*cinfo), pixels, rowBytes); + SkImageInfo info; + if (!from_c_info(*cinfo, &info)) { + return NULL; + } + return (sk_image_t*)SkImage::NewRasterCopy(info, pixels, rowBytes); } void sk_image_ref(const sk_image_t* cimage) { @@ -176,12 +258,20 @@ void sk_canvas_draw_image(sk_canvas_t* ccanvas, const sk_image_t* cimage, float /////////////////////////////////////////////////////////////////////////////////////////// sk_surface_t* sk_surface_new_raster(const sk_imageinfo_t* cinfo) { - return (sk_surface_t*)SkSurface::NewRaster(make(*cinfo)); + SkImageInfo info; + if (!from_c_info(*cinfo, &info)) { + return NULL; + } + return (sk_surface_t*)SkSurface::NewRaster(info); } sk_surface_t* sk_surface_new_raster_direct(const sk_imageinfo_t* cinfo, void* pixels, size_t rowBytes) { - return (sk_surface_t*)SkSurface::NewRasterDirect(make(*cinfo), pixels, rowBytes); + SkImageInfo info; + if (!from_c_info(*cinfo, &info)) { + return NULL; + } + return (sk_surface_t*)SkSurface::NewRasterDirect(info, pixels, rowBytes); } void sk_surface_delete(sk_surface_t* csurf) { diff --git a/tests/CTest.cpp b/tests/CTest.cpp new file mode 100644 index 0000000000..f663dcf949 --- /dev/null +++ b/tests/CTest.cpp @@ -0,0 +1,36 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "sk_surface.h" +#include "Test.h" + +static void test_c(skiatest::Reporter* reporter) { + sk_colortype_t ct = sk_colortype_get_default_8888(); + + sk_imageinfo_t info = { + 1, 1, ct, PREMUL_SK_ALPHATYPE + }; + uint32_t pixel[1] = { 0 }; + + sk_surface_t* surface = sk_surface_new_raster_direct(&info, pixel, sizeof(uint32_t)); + sk_paint_t* paint = sk_paint_new(); + + sk_canvas_t* canvas = sk_surface_get_canvas(surface); + sk_canvas_draw_paint(canvas, paint); + REPORTER_ASSERT(reporter, 0xFF000000 == pixel[0]); + + sk_paint_set_color(paint, sk_color_set_argb(0xFF, 0xFF, 0xFF, 0xFF)); + sk_canvas_draw_paint(canvas, paint); + REPORTER_ASSERT(reporter, 0xFFFFFFFF == pixel[0]); + + sk_paint_delete(paint); + sk_surface_delete(surface); +} + +DEF_TEST(C_API, reporter) { + test_c(reporter); +}