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 "SkCanvas.h" 9 #include "SkColorShader.h" 10 #include "SkGradientShader.h" 11 #include "SkShader.h" 12 #include "SkTemplates.h" 13 #include "Test.h" 14 15 struct GradRec { 16 int fColorCount; 17 const SkColor* fColors; 18 const SkScalar* fPos; 19 const SkPoint* fPoint; // 2 20 const SkScalar* fRadius; // 2 21 SkShader::TileMode fTileMode; 22 23 void gradCheck(skiatest::Reporter* reporter, SkShader* shader, 24 SkShader::GradientInfo* info, 25 SkShader::GradientType gt) const { 26 SkAutoTMalloc<SkColor> colorStorage(fColorCount); 27 SkAutoTMalloc<SkScalar> posStorage(fColorCount); 28 29 info->fColorCount = fColorCount; 30 info->fColors = colorStorage; 31 info->fColorOffsets = posStorage.get(); 32 REPORTER_ASSERT(reporter, shader->asAGradient(info) == gt); 33 34 REPORTER_ASSERT(reporter, info->fColorCount == fColorCount); 35 REPORTER_ASSERT(reporter, 36 !memcmp(info->fColors, fColors, fColorCount * sizeof(SkColor))); 37 REPORTER_ASSERT(reporter, 38 !memcmp(info->fColorOffsets, fPos, fColorCount * sizeof(SkScalar))); 39 REPORTER_ASSERT(reporter, fTileMode == info->fTileMode); 40 } 41 }; 42 43 44 static void none_gradproc(skiatest::Reporter* reporter, const GradRec&) { 45 SkAutoTUnref<SkShader> s(SkShader::CreateEmptyShader()); 46 REPORTER_ASSERT(reporter, SkShader::kNone_GradientType == s->asAGradient(NULL)); 47 } 48 49 static void color_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { 50 SkAutoTUnref<SkShader> s(new SkColorShader(rec.fColors[0])); 51 REPORTER_ASSERT(reporter, SkShader::kColor_GradientType == s->asAGradient(NULL)); 52 53 SkShader::GradientInfo info; 54 info.fColors = NULL; 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*) { 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.allocN32Pixels(10, 1); 145 SkPaint paint; 146 paint.setShader(s.get()); 147 SkCanvas canvas(outBitmap); 148 canvas.drawPaint(paint); 149 SkAutoLockPixels alp(outBitmap); 150 for (int i = 0; i < 10; i++) { 151 // The following is commented out because it currently fails 152 // Related bug: https://code.google.com/p/skia/issues/detail?id=1098 153 154 // REPORTER_ASSERT(reporter, SK_ColorBLUE == outBitmap.getColor(i, 0)); 155 } 156 } 157 158 typedef void (*GradProc)(skiatest::Reporter* reporter, const GradRec&); 159 160 static void TestGradientShaders(skiatest::Reporter* reporter) { 161 static const SkColor gColors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE }; 162 static const SkScalar gPos[] = { 0, SK_ScalarHalf, SK_Scalar1 }; 163 static const SkPoint gPts[] = { 164 { 0, 0 }, 165 { SkIntToScalar(10), SkIntToScalar(20) } 166 }; 167 static const SkScalar gRad[] = { SkIntToScalar(1), SkIntToScalar(2) }; 168 169 GradRec rec; 170 rec.fColorCount = SK_ARRAY_COUNT(gColors); 171 rec.fColors = gColors; 172 rec.fPos = gPos; 173 rec.fPoint = gPts; 174 rec.fRadius = gRad; 175 rec.fTileMode = SkShader::kClamp_TileMode; 176 177 static const GradProc gProcs[] = { 178 none_gradproc, 179 color_gradproc, 180 linear_gradproc, 181 radial_gradproc, 182 radial2_gradproc, 183 sweep_gradproc, 184 conical_gradproc, 185 }; 186 187 for (size_t i = 0; i < SK_ARRAY_COUNT(gProcs); ++i) { 188 gProcs[i](reporter, rec); 189 } 190 } 191 192 DEF_TEST(Gradient, reporter) { 193 TestGradientShaders(reporter); 194 TestConstantGradient(reporter); 195 } 196