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