diff --git a/include/c/sk_shader.h b/include/c/sk_shader.h index 9f83ff0415..702cda7fd4 100644 --- a/include/c/sk_shader.h +++ b/include/c/sk_shader.h @@ -24,7 +24,25 @@ typedef enum { MIRROR_SK_SHADER_TILEMODE, } sk_shader_tilemode_t; -sk_shader_t* sk_shader_new_linear_gradient(const sk_point_t pts[2], +/** + Returns a shader that generates a linear gradient between the two + specified points. + + @param points The start and end points for the gradient. + @param colors The array[count] of colors, to be distributed between + the two points + @param colorPos May be NULL. array[count] of SkScalars, or NULL, of + the relative position of each corresponding color + in the colors array. If this is NULL, the the + colors are distributed evenly between the start + and end point. If this is not null, the values + must begin with 0, end with 1.0, and intermediate + values must be strictly increasing. + @param colorCount Must be >=2. The number of colors (and pos if not + NULL) entries. + @param mode The tiling mode +*/ +sk_shader_t* sk_shader_new_linear_gradient(const sk_point_t points[2], const sk_color_t colors[], const float colorPos[], int colorCount, @@ -32,6 +50,94 @@ sk_shader_t* sk_shader_new_linear_gradient(const sk_point_t pts[2], const sk_matrix_t* localMatrix); +/** + Returns a shader that generates a radial gradient given the center + and radius. + + @param center The center of the circle for this gradient + @param radius Must be positive. The radius of the circle for this + gradient + @param colors The array[count] of colors, to be distributed + between the center and edge of the circle + @param colorPos May be NULL. The array[count] of the relative + position of each corresponding color in the colors + array. If this is NULL, the the colors are + distributed evenly between the center and edge of + the circle. If this is not null, the values must + begin with 0, end with 1.0, and intermediate + values must be strictly increasing. + @param count Must be >= 2. The number of colors (and pos if not + NULL) entries + @param tileMode The tiling mode + @param localMatrix May be NULL +*/ +sk_shader_t* sk_shader_new_radial_gradient(const sk_point_t* center, + float radius, + const sk_color_t colors[], + const float colorPos[], + int colorCount, + sk_shader_tilemode_t tileMode, + const sk_matrix_t* localMatrix); + +/** + Returns a shader that generates a sweep gradient given a center. + + @param center The coordinates of the center of the sweep + @param colors The array[count] of colors, to be distributed around + the center. + @param colorPos May be NULL. The array[count] of the relative + position of each corresponding color in the colors + array. If this is NULL, the the colors are + distributed evenly between the center and edge of + the circle. If this is not null, the values must + begin with 0, end with 1.0, and intermediate + values must be strictly increasing. + @param colorCount Must be >= 2. The number of colors (and pos if + not NULL) entries + @param localMatrix May be NULL +*/ +sk_shader_t* sk_shader_new_sweep_gradient(const sk_point_t* center, + const sk_color_t colors[], + const float colorPos[], + int colorCount, + const sk_matrix_t* localMatrix); + +/** + Returns a shader that generates a conical gradient given two circles, or + returns NULL if the inputs are invalid. The gradient interprets the + two circles according to the following HTML spec. + http://dev.w3.org/html5/2dcontext/#dom-context-2d-createradialgradient + + Returns a shader that generates a sweep gradient given a center. + + @param start, startRadius Defines the first circle. + @param end, endRadius Defines the first circle. + @param colors The array[count] of colors, to be distributed between + the two circles. + @param colorPos May be NULL. The array[count] of the relative + position of each corresponding color in the colors + array. If this is NULL, the the colors are + distributed evenly between the two circles. If + this is not null, the values must begin with 0, + end with 1.0, and intermediate values must be + strictly increasing. + @param colorCount Must be >= 2. The number of colors (and pos if + not NULL) entries + @param tileMode The tiling mode + @param localMatrix May be NULL + +*/ +sk_shader_t* sk_shader_new_two_point_conical_gradient( + const sk_point_t* start, + float startRadius, + const sk_point_t* end, + float endRadius, + const sk_color_t colors[], + const float colorPos[], + int colorCount, + sk_shader_tilemode_t tileMode, + const sk_matrix_t* localMatrix); + SK_C_PLUS_PLUS_END_GUARD #endif diff --git a/src/c/sk_surface.cpp b/src/c/sk_surface.cpp index 84a9c541c2..ccab9dfa1a 100644 --- a/src/c/sk_surface.cpp +++ b/src/c/sk_surface.cpp @@ -556,6 +556,86 @@ sk_shader_t* sk_shader_new_linear_gradient(const sk_point_t pts[2], return (sk_shader_t*)s; } +static const SkPoint& to_skpoint(const sk_point_t& p) { + return reinterpret_cast(p); +} + +sk_shader_t* sk_shader_new_radial_gradient(const sk_point_t* ccenter, + float radius, + const sk_color_t colors[], + const float colorPos[], + int colorCount, + sk_shader_tilemode_t cmode, + const sk_matrix_t* cmatrix) { + SkShader::TileMode mode; + if (!from_c_tilemode(cmode, &mode)) { + return NULL; + } + SkMatrix matrix; + if (cmatrix) { + from_c_matrix(cmatrix, &matrix); + } else { + matrix.setIdentity(); + } + SkPoint center = to_skpoint(*ccenter); + SkShader* s = SkGradientShader::CreateRadial( + center, (SkScalar)radius, + reinterpret_cast(colors), + reinterpret_cast(colorPos), + colorCount, mode, 0, &matrix); + return (sk_shader_t*)s; +} + +sk_shader_t* sk_shader_new_sweep_gradient(const sk_point_t* ccenter, + const sk_color_t colors[], + const float colorPos[], + int colorCount, + const sk_matrix_t* cmatrix) { + SkMatrix matrix; + if (cmatrix) { + from_c_matrix(cmatrix, &matrix); + } else { + matrix.setIdentity(); + } + SkShader* s = SkGradientShader::CreateSweep( + (SkScalar)(ccenter->x), + (SkScalar)(ccenter->y), + reinterpret_cast(colors), + reinterpret_cast(colorPos), + colorCount, 0, &matrix); + return (sk_shader_t*)s; +} + +sk_shader_t* sk_shader_new_two_point_conical_gradient(const sk_point_t* start, + float startRadius, + const sk_point_t* end, + float endRadius, + const sk_color_t colors[], + const float colorPos[], + int colorCount, + sk_shader_tilemode_t cmode, + const sk_matrix_t* cmatrix) { + SkShader::TileMode mode; + if (!from_c_tilemode(cmode, &mode)) { + return NULL; + } + SkMatrix matrix; + if (cmatrix) { + from_c_matrix(cmatrix, &matrix); + } else { + matrix.setIdentity(); + } + SkPoint skstart = to_skpoint(*start); + SkPoint skend = to_skpoint(*end); + SkShader* s = SkGradientShader::CreateTwoPointConical( + skstart, (SkScalar)startRadius, + skend, (SkScalar)endRadius, + reinterpret_cast(colors), + reinterpret_cast(colorPos), + colorCount, mode, 0, &matrix); + return (sk_shader_t*)s; +} + /////////////////////////////////////////////////////////////////////////////////////////// #include "../../include/effects/SkBlurMaskFilter.h" diff --git a/tests/CTest.cpp b/tests/CTest.cpp index acab4bb11b..4cc8cd6666 100644 --- a/tests/CTest.cpp +++ b/tests/CTest.cpp @@ -8,9 +8,51 @@ #include "sk_canvas.h" #include "sk_paint.h" #include "sk_surface.h" +#include "sk_shader.h" #include "Test.h" + +static void shader_test(skiatest::Reporter* reporter) { + sk_imageinfo_t info = + {64, 64, sk_colortype_get_default_8888(), PREMUL_SK_ALPHATYPE}; + sk_surface_t* surface = sk_surface_new_raster(&info, NULL); + sk_canvas_t* canvas = sk_surface_get_canvas(surface); + sk_paint_t* paint = sk_paint_new(); + + sk_shader_tilemode_t tilemode = CLAMP_SK_SHADER_TILEMODE; + sk_point_t point = {0.0f, 0.0f}; + sk_point_t point2 = {30.0f, 40.0f}; + sk_color_t colors[] = { + (sk_color_t)sk_color_set_argb(0xFF, 0x00, 0x00, 0xFF), + (sk_color_t)sk_color_set_argb(0xFF, 0x00, 0xFF, 0x00) + }; + sk_shader_t* shader; + + shader = sk_shader_new_radial_gradient( + &point, 1.0f, colors, NULL, 2, tilemode, NULL); + REPORTER_ASSERT(reporter, shader != NULL); + sk_paint_set_shader(paint, shader); + sk_shader_unref(shader); + sk_canvas_draw_paint(canvas, paint); + + shader = sk_shader_new_sweep_gradient(&point, colors, NULL, 2, NULL); + REPORTER_ASSERT(reporter, shader != NULL); + sk_paint_set_shader(paint, shader); + sk_shader_unref(shader); + sk_canvas_draw_paint(canvas, paint); + + shader = sk_shader_new_two_point_conical_gradient( + &point, 10.0f, &point2, 50.0f, colors, NULL, 2, tilemode, NULL); + REPORTER_ASSERT(reporter, shader != NULL); + sk_paint_set_shader(paint, shader); + sk_shader_unref(shader); + sk_canvas_draw_paint(canvas, paint); + + sk_paint_delete(paint); + sk_surface_unref(surface); +} + static void test_c(skiatest::Reporter* reporter) { sk_colortype_t ct = sk_colortype_get_default_8888(); @@ -43,4 +85,5 @@ static void test_c(skiatest::Reporter* reporter) { DEF_TEST(C_API, reporter) { test_c(reporter); + shader_test(reporter); }