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