183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com/* 283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com * Copyright 2011 Google Inc. 383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com * 483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com * Use of this source code is governed by a BSD-style license that can be 583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com * found in the LICENSE file. 683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com */ 7e4fafb146e85cdfcf9d5418597b6818aa0754adatfarina@chromium.org 88c0c7b0bcdf17ff672a972748f692a41c22aa0a1reed#include "SkCanvas.h" 983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com#include "SkColorShader.h" 1083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com#include "SkGradientShader.h" 111f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com#include "SkShader.h" 121f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com#include "SkTemplates.h" 138f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "Test.h" 1483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 1583226976b532141b26ff3a40f381a5d08ce3259dreed@google.comstruct GradRec { 1683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com int fColorCount; 1783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com const SkColor* fColors; 1883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com const SkScalar* fPos; 1983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com const SkPoint* fPoint; // 2 2083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com const SkScalar* fRadius; // 2 2183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com SkShader::TileMode fTileMode; 2283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 2383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com void gradCheck(skiatest::Reporter* reporter, SkShader* shader, 2483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com SkShader::GradientInfo* info, 2583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com SkShader::GradientType gt) const { 2683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com SkAutoTMalloc<SkColor> colorStorage(fColorCount); 2783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com SkAutoTMalloc<SkScalar> posStorage(fColorCount); 2883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 2983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com info->fColorCount = fColorCount; 3083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com info->fColors = colorStorage; 3183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com info->fColorOffsets = posStorage.get(); 3283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com REPORTER_ASSERT(reporter, shader->asAGradient(info) == gt); 3383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 3483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com REPORTER_ASSERT(reporter, info->fColorCount == fColorCount); 3583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com REPORTER_ASSERT(reporter, 3683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com !memcmp(info->fColors, fColors, fColorCount * sizeof(SkColor))); 3783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com REPORTER_ASSERT(reporter, 3883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com !memcmp(info->fColorOffsets, fPos, fColorCount * sizeof(SkScalar))); 3983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com REPORTER_ASSERT(reporter, fTileMode == info->fTileMode); 4083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com } 4183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com}; 4283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 4383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 44e0e385c1d4171e065348ba17c546b3463a0bd651sugoi@google.comstatic void none_gradproc(skiatest::Reporter* reporter, const GradRec&) { 45e1085e0381a4abfe440e664c1a0669f3676a8092reed SkAutoTUnref<SkShader> s(SkShader::CreateEmptyShader()); 4683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com REPORTER_ASSERT(reporter, SkShader::kNone_GradientType == s->asAGradient(NULL)); 4783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com} 4883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 4983226976b532141b26ff3a40f381a5d08ce3259dreed@google.comstatic void color_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { 5083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com SkAutoTUnref<SkShader> s(new SkColorShader(rec.fColors[0])); 5183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com REPORTER_ASSERT(reporter, SkShader::kColor_GradientType == s->asAGradient(NULL)); 5283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 5383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com SkShader::GradientInfo info; 5437ebe3fbf6c4a5728bc2c322cc0f626444f987bfrobertphillips@google.com info.fColors = NULL; 5583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com info.fColorCount = 0; 5683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com s->asAGradient(&info); 5783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com REPORTER_ASSERT(reporter, 1 == info.fColorCount); 5883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com} 5983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 6083226976b532141b26ff3a40f381a5d08ce3259dreed@google.comstatic void linear_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { 6183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com SkAutoTUnref<SkShader> s(SkGradientShader::CreateLinear(rec.fPoint, 6283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fColors, 6383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fPos, 6483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fColorCount, 6583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fTileMode)); 66d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 6783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com SkShader::GradientInfo info; 6883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.gradCheck(reporter, s, &info, SkShader::kLinear_GradientType); 6983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com REPORTER_ASSERT(reporter, !memcmp(info.fPoint, rec.fPoint, 2 * sizeof(SkPoint))); 7083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com} 7183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 7283226976b532141b26ff3a40f381a5d08ce3259dreed@google.comstatic void radial_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { 7383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com SkAutoTUnref<SkShader> s(SkGradientShader::CreateRadial(rec.fPoint[0], 7483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fRadius[0], 7583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fColors, 7683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fPos, 7783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fColorCount, 7883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fTileMode)); 79d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 8083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com SkShader::GradientInfo info; 8183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.gradCheck(reporter, s, &info, SkShader::kRadial_GradientType); 8283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com REPORTER_ASSERT(reporter, info.fPoint[0] == rec.fPoint[0]); 8383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com REPORTER_ASSERT(reporter, info.fRadius[0] == rec.fRadius[0]); 8483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com} 8583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 8683226976b532141b26ff3a40f381a5d08ce3259dreed@google.comstatic void radial2_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { 8783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com SkAutoTUnref<SkShader> s(SkGradientShader::CreateTwoPointRadial(rec.fPoint[0], 8883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fRadius[0], 8983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fPoint[1], 9083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fRadius[1], 9183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fColors, 9283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fPos, 9383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fColorCount, 9483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fTileMode)); 95d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 9683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com SkShader::GradientInfo info; 9783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.gradCheck(reporter, s, &info, SkShader::kRadial2_GradientType); 9883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com REPORTER_ASSERT(reporter, !memcmp(info.fPoint, rec.fPoint, 2 * sizeof(SkPoint))); 9983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com REPORTER_ASSERT(reporter, !memcmp(info.fRadius, rec.fRadius, 2 * sizeof(SkScalar))); 10083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com} 10183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 10283226976b532141b26ff3a40f381a5d08ce3259dreed@google.comstatic void sweep_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { 10383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com SkAutoTUnref<SkShader> s(SkGradientShader::CreateSweep(rec.fPoint[0].fX, 10483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fPoint[0].fY, 10583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fColors, 10683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fPos, 10783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fColorCount)); 108d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 10983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com SkShader::GradientInfo info; 11083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.gradCheck(reporter, s, &info, SkShader::kSweep_GradientType); 11183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com REPORTER_ASSERT(reporter, info.fPoint[0] == rec.fPoint[0]); 11283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com} 11383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 11483226976b532141b26ff3a40f381a5d08ce3259dreed@google.comstatic void conical_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { 11583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com SkAutoTUnref<SkShader> s(SkGradientShader::CreateTwoPointConical(rec.fPoint[0], 11683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fRadius[0], 11783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fPoint[1], 11883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fRadius[1], 11983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fColors, 12083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fPos, 12183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fColorCount, 12283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fTileMode)); 123d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 12483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com SkShader::GradientInfo info; 12583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.gradCheck(reporter, s, &info, SkShader::kConical_GradientType); 12683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com REPORTER_ASSERT(reporter, !memcmp(info.fPoint, rec.fPoint, 2 * sizeof(SkPoint))); 12783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com REPORTER_ASSERT(reporter, !memcmp(info.fRadius, rec.fRadius, 2 * sizeof(SkScalar))); 12883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com} 12983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 130e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org// Ensure that repeated color gradients behave like drawing a single color 131e0e385c1d4171e065348ba17c546b3463a0bd651sugoi@google.comstatic void TestConstantGradient(skiatest::Reporter*) { 132e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org const SkPoint pts[] = { 133e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org { 0, 0 }, 134e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org { SkIntToScalar(10), 0 } 135e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org }; 136e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org SkColor colors[] = { SK_ColorBLUE, SK_ColorBLUE }; 137e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org const SkScalar pos[] = { 0, SK_Scalar1 }; 138e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org SkAutoTUnref<SkShader> s(SkGradientShader::CreateLinear(pts, 139e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org colors, 140e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org pos, 141e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org 2, 142e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org SkShader::kClamp_TileMode)); 143e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org SkBitmap outBitmap; 144deee496cd30070e52556dcb538c2e5eb39b66b81mike@reedtribe.org outBitmap.allocN32Pixels(10, 1); 145e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org SkPaint paint; 146e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org paint.setShader(s.get()); 147deee496cd30070e52556dcb538c2e5eb39b66b81mike@reedtribe.org SkCanvas canvas(outBitmap); 148e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org canvas.drawPaint(paint); 149e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org SkAutoLockPixels alp(outBitmap); 150e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org for (int i = 0; i < 10; i++) { 151e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org // The following is commented out because it currently fails 152e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org // Related bug: https://code.google.com/p/skia/issues/detail?id=1098 153e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org 154e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org // REPORTER_ASSERT(reporter, SK_ColorBLUE == outBitmap.getColor(i, 0)); 155e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org } 156e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org} 157e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org 15883226976b532141b26ff3a40f381a5d08ce3259dreed@google.comtypedef void (*GradProc)(skiatest::Reporter* reporter, const GradRec&); 15983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 160e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.orgstatic void TestGradientShaders(skiatest::Reporter* reporter) { 16183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com static const SkColor gColors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE }; 16283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com static const SkScalar gPos[] = { 0, SK_ScalarHalf, SK_Scalar1 }; 16383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com static const SkPoint gPts[] = { 16483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com { 0, 0 }, 16583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com { SkIntToScalar(10), SkIntToScalar(20) } 16683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com }; 16783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com static const SkScalar gRad[] = { SkIntToScalar(1), SkIntToScalar(2) }; 16883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 16983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com GradRec rec; 17083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fColorCount = SK_ARRAY_COUNT(gColors); 17183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fColors = gColors; 17283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fPos = gPos; 17383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fPoint = gPts; 17483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fRadius = gRad; 17583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com rec.fTileMode = SkShader::kClamp_TileMode; 17683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 17783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com static const GradProc gProcs[] = { 17883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com none_gradproc, 17983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com color_gradproc, 18083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com linear_gradproc, 18183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com radial_gradproc, 18283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com radial2_gradproc, 18383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com sweep_gradproc, 18483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com conical_gradproc, 18583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com }; 186d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 18783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com for (size_t i = 0; i < SK_ARRAY_COUNT(gProcs); ++i) { 18883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com gProcs[i](reporter, rec); 18983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com } 19083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com} 19183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 192e4fafb146e85cdfcf9d5418597b6818aa0754adatfarina@chromium.orgDEF_TEST(Gradient, reporter) { 193e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org TestGradientShaders(reporter); 194e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org TestConstantGradient(reporter); 195e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org} 196