1/* 2 * Copyright 2011 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 "Test.h" 9#include "TestClassDef.h" 10#include "SkBitmapDevice.h" 11#include "SkColorShader.h" 12#include "SkEmptyShader.h" 13#include "SkGradientShader.h" 14#include "SkShader.h" 15#include "SkTemplates.h" 16 17struct GradRec { 18 int fColorCount; 19 const SkColor* fColors; 20 const SkScalar* fPos; 21 const SkPoint* fPoint; // 2 22 const SkScalar* fRadius; // 2 23 SkShader::TileMode fTileMode; 24 25 void gradCheck(skiatest::Reporter* reporter, SkShader* shader, 26 SkShader::GradientInfo* info, 27 SkShader::GradientType gt) const { 28 SkAutoTMalloc<SkColor> colorStorage(fColorCount); 29 SkAutoTMalloc<SkScalar> posStorage(fColorCount); 30 31 info->fColorCount = fColorCount; 32 info->fColors = colorStorage; 33 info->fColorOffsets = posStorage.get(); 34 REPORTER_ASSERT(reporter, shader->asAGradient(info) == gt); 35 36 REPORTER_ASSERT(reporter, info->fColorCount == fColorCount); 37 REPORTER_ASSERT(reporter, 38 !memcmp(info->fColors, fColors, fColorCount * sizeof(SkColor))); 39 REPORTER_ASSERT(reporter, 40 !memcmp(info->fColorOffsets, fPos, fColorCount * sizeof(SkScalar))); 41 REPORTER_ASSERT(reporter, fTileMode == info->fTileMode); 42 } 43}; 44 45 46static void none_gradproc(skiatest::Reporter* reporter, const GradRec&) { 47 SkAutoTUnref<SkShader> s(new SkEmptyShader); 48 REPORTER_ASSERT(reporter, SkShader::kNone_GradientType == s->asAGradient(NULL)); 49} 50 51static void color_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { 52 SkAutoTUnref<SkShader> s(new SkColorShader(rec.fColors[0])); 53 REPORTER_ASSERT(reporter, SkShader::kColor_GradientType == s->asAGradient(NULL)); 54 55 SkShader::GradientInfo info; 56 info.fColors = NULL; 57 info.fColorCount = 0; 58 s->asAGradient(&info); 59 REPORTER_ASSERT(reporter, 1 == info.fColorCount); 60} 61 62static void linear_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { 63 SkAutoTUnref<SkShader> s(SkGradientShader::CreateLinear(rec.fPoint, 64 rec.fColors, 65 rec.fPos, 66 rec.fColorCount, 67 rec.fTileMode)); 68 69 SkShader::GradientInfo info; 70 rec.gradCheck(reporter, s, &info, SkShader::kLinear_GradientType); 71 REPORTER_ASSERT(reporter, !memcmp(info.fPoint, rec.fPoint, 2 * sizeof(SkPoint))); 72} 73 74static void radial_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { 75 SkAutoTUnref<SkShader> s(SkGradientShader::CreateRadial(rec.fPoint[0], 76 rec.fRadius[0], 77 rec.fColors, 78 rec.fPos, 79 rec.fColorCount, 80 rec.fTileMode)); 81 82 SkShader::GradientInfo info; 83 rec.gradCheck(reporter, s, &info, SkShader::kRadial_GradientType); 84 REPORTER_ASSERT(reporter, info.fPoint[0] == rec.fPoint[0]); 85 REPORTER_ASSERT(reporter, info.fRadius[0] == rec.fRadius[0]); 86} 87 88static void radial2_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { 89 SkAutoTUnref<SkShader> s(SkGradientShader::CreateTwoPointRadial(rec.fPoint[0], 90 rec.fRadius[0], 91 rec.fPoint[1], 92 rec.fRadius[1], 93 rec.fColors, 94 rec.fPos, 95 rec.fColorCount, 96 rec.fTileMode)); 97 98 SkShader::GradientInfo info; 99 rec.gradCheck(reporter, s, &info, SkShader::kRadial2_GradientType); 100 REPORTER_ASSERT(reporter, !memcmp(info.fPoint, rec.fPoint, 2 * sizeof(SkPoint))); 101 REPORTER_ASSERT(reporter, !memcmp(info.fRadius, rec.fRadius, 2 * sizeof(SkScalar))); 102} 103 104static void sweep_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { 105 SkAutoTUnref<SkShader> s(SkGradientShader::CreateSweep(rec.fPoint[0].fX, 106 rec.fPoint[0].fY, 107 rec.fColors, 108 rec.fPos, 109 rec.fColorCount)); 110 111 SkShader::GradientInfo info; 112 rec.gradCheck(reporter, s, &info, SkShader::kSweep_GradientType); 113 REPORTER_ASSERT(reporter, info.fPoint[0] == rec.fPoint[0]); 114} 115 116static void conical_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { 117 SkAutoTUnref<SkShader> s(SkGradientShader::CreateTwoPointConical(rec.fPoint[0], 118 rec.fRadius[0], 119 rec.fPoint[1], 120 rec.fRadius[1], 121 rec.fColors, 122 rec.fPos, 123 rec.fColorCount, 124 rec.fTileMode)); 125 126 SkShader::GradientInfo info; 127 rec.gradCheck(reporter, s, &info, SkShader::kConical_GradientType); 128 REPORTER_ASSERT(reporter, !memcmp(info.fPoint, rec.fPoint, 2 * sizeof(SkPoint))); 129 REPORTER_ASSERT(reporter, !memcmp(info.fRadius, rec.fRadius, 2 * sizeof(SkScalar))); 130} 131 132// Ensure that repeated color gradients behave like drawing a single color 133static void TestConstantGradient(skiatest::Reporter*) { 134 const SkPoint pts[] = { 135 { 0, 0 }, 136 { SkIntToScalar(10), 0 } 137 }; 138 SkColor colors[] = { SK_ColorBLUE, SK_ColorBLUE }; 139 const SkScalar pos[] = { 0, SK_Scalar1 }; 140 SkAutoTUnref<SkShader> s(SkGradientShader::CreateLinear(pts, 141 colors, 142 pos, 143 2, 144 SkShader::kClamp_TileMode)); 145 SkBitmap outBitmap; 146 outBitmap.setConfig(SkBitmap::kARGB_8888_Config, 10, 1); 147 outBitmap.allocPixels(); 148 SkPaint paint; 149 paint.setShader(s.get()); 150 SkBitmapDevice device(outBitmap); 151 SkCanvas canvas(&device); 152 canvas.drawPaint(paint); 153 SkAutoLockPixels alp(outBitmap); 154 for (int i = 0; i < 10; i++) { 155 // The following is commented out because it currently fails 156 // Related bug: https://code.google.com/p/skia/issues/detail?id=1098 157 158 // REPORTER_ASSERT(reporter, SK_ColorBLUE == outBitmap.getColor(i, 0)); 159 } 160} 161 162typedef void (*GradProc)(skiatest::Reporter* reporter, const GradRec&); 163 164static void TestGradientShaders(skiatest::Reporter* reporter) { 165 static const SkColor gColors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE }; 166 static const SkScalar gPos[] = { 0, SK_ScalarHalf, SK_Scalar1 }; 167 static const SkPoint gPts[] = { 168 { 0, 0 }, 169 { SkIntToScalar(10), SkIntToScalar(20) } 170 }; 171 static const SkScalar gRad[] = { SkIntToScalar(1), SkIntToScalar(2) }; 172 173 GradRec rec; 174 rec.fColorCount = SK_ARRAY_COUNT(gColors); 175 rec.fColors = gColors; 176 rec.fPos = gPos; 177 rec.fPoint = gPts; 178 rec.fRadius = gRad; 179 rec.fTileMode = SkShader::kClamp_TileMode; 180 181 static const GradProc gProcs[] = { 182 none_gradproc, 183 color_gradproc, 184 linear_gradproc, 185 radial_gradproc, 186 radial2_gradproc, 187 sweep_gradproc, 188 conical_gradproc, 189 }; 190 191 for (size_t i = 0; i < SK_ARRAY_COUNT(gProcs); ++i) { 192 gProcs[i](reporter, rec); 193 } 194} 195 196DEF_TEST(Gradient, reporter) { 197 TestGradientShaders(reporter); 198 TestConstantGradient(reporter); 199} 200