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