1 /* 2 * Copyright 2014 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 "gm.h" 9 #include "SkGradientShader.h" 10 #include "SkImage.h" 11 #include "SkPatchUtils.h" 12 #include "SkPath.h" 13 14 static sk_sp<SkShader> make_shader() { 15 const SkColor colors[] = { 16 SK_ColorRED, SK_ColorCYAN, SK_ColorGREEN, SK_ColorWHITE, SK_ColorMAGENTA, SK_ColorBLUE, 17 SK_ColorYELLOW, 18 }; 19 const SkPoint pts[] = { { 100.f / 4.f, 0.f }, { 3.f * 100.f / 4.f, 100.f } }; 20 21 return SkGradientShader::MakeLinear(pts, colors, nullptr, SK_ARRAY_COUNT(colors), 22 SkShader::kMirror_TileMode); 23 } 24 25 static void draw_control_points(SkCanvas* canvas, const SkPoint cubics[12]) { 26 //draw control points 27 SkPaint paint; 28 SkPoint bottom[SkPatchUtils::kNumPtsCubic]; 29 SkPatchUtils::GetBottomCubic(cubics, bottom); 30 SkPoint top[SkPatchUtils::kNumPtsCubic]; 31 SkPatchUtils::GetTopCubic(cubics, top); 32 SkPoint left[SkPatchUtils::kNumPtsCubic]; 33 SkPatchUtils::GetLeftCubic(cubics, left); 34 SkPoint right[SkPatchUtils::kNumPtsCubic]; 35 SkPatchUtils::GetRightCubic(cubics, right); 36 37 paint.setColor(SK_ColorBLACK); 38 paint.setStrokeWidth(0.5f); 39 SkPoint corners[4] = { bottom[0], bottom[3], top[0], top[3] }; 40 canvas->drawPoints(SkCanvas::kLines_PointMode, 4, bottom, paint); 41 canvas->drawPoints(SkCanvas::kLines_PointMode, 2, bottom + 1, paint); 42 canvas->drawPoints(SkCanvas::kLines_PointMode, 4, top, paint); 43 canvas->drawPoints(SkCanvas::kLines_PointMode, 4, left, paint); 44 canvas->drawPoints(SkCanvas::kLines_PointMode, 4, right, paint); 45 46 canvas->drawPoints(SkCanvas::kLines_PointMode, 2, top + 1, paint); 47 canvas->drawPoints(SkCanvas::kLines_PointMode, 2, left + 1, paint); 48 canvas->drawPoints(SkCanvas::kLines_PointMode, 2, right + 1, paint); 49 50 paint.setStrokeWidth(2); 51 52 paint.setColor(SK_ColorRED); 53 canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, corners, paint); 54 55 paint.setColor(SK_ColorBLUE); 56 canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, bottom + 1, paint); 57 58 paint.setColor(SK_ColorCYAN); 59 canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, top + 1, paint); 60 61 paint.setColor(SK_ColorYELLOW); 62 canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, left + 1, paint); 63 64 paint.setColor(SK_ColorGREEN); 65 canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, right + 1, paint); 66 } 67 68 // The order of the colors and points is clockwise starting at upper-left corner. 69 const SkPoint gCubics[SkPatchUtils::kNumCtrlPts] = { 70 //top points 71 {100,100},{150,50},{250,150}, {300,100}, 72 //right points 73 {250, 150},{350,250}, 74 //bottom points 75 {300,300},{250,250},{150,350},{100,300}, 76 //left points 77 {50,250},{150,150} 78 }; 79 80 const SkPoint gTexCoords[SkPatchUtils::kNumCorners] = { 81 {0.0f, 0.0f}, {100.0f, 0.0f}, {100.0f,100.0f}, {0.0f, 100.0f} 82 }; 83 84 85 static void dopatch(SkCanvas* canvas, const SkColor colors[], sk_sp<SkImage> img = nullptr) { 86 SkPaint paint; 87 88 const SkBlendMode modes[] = { 89 SkBlendMode::kSrc, 90 SkBlendMode::kDst, 91 SkBlendMode::kModulate, 92 }; 93 94 SkPoint texStorage[4]; 95 const SkPoint* tex = gTexCoords; 96 97 sk_sp<SkShader> shader; 98 if (img) { 99 SkScalar w = img->width(); 100 SkScalar h = img->height(); 101 shader = img->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); 102 texStorage[0].set(0, 0); 103 texStorage[1].set(w, 0); 104 texStorage[2].set(w, h); 105 texStorage[3].set(0, h); 106 tex = texStorage; 107 } else { 108 shader = make_shader(); 109 } 110 111 canvas->save(); 112 for (int y = 0; y < 3; y++) { 113 for (int x = 0; x < 4; x++) { 114 canvas->save(); 115 canvas->translate(x * 350.0f, y * 350.0f); 116 switch (x) { 117 case 0: 118 canvas->drawPatch(gCubics, nullptr, nullptr, modes[y], paint); 119 break; 120 case 1: 121 canvas->drawPatch(gCubics, colors, nullptr, modes[y], paint); 122 break; 123 case 2: 124 paint.setShader(shader); 125 canvas->drawPatch(gCubics, nullptr, tex, modes[y], paint); 126 paint.setShader(nullptr); 127 break; 128 case 3: 129 paint.setShader(shader); 130 canvas->drawPatch(gCubics, colors, tex, modes[y], paint); 131 paint.setShader(nullptr); 132 break; 133 default: 134 break; 135 } 136 137 draw_control_points(canvas, gCubics); 138 canvas->restore(); 139 } 140 } 141 canvas->restore(); 142 } 143 144 DEF_SIMPLE_GM(patch_primitive, canvas, 1500, 1100) { 145 const SkColor colors[SkPatchUtils::kNumCorners] = { 146 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorCYAN 147 }; 148 dopatch(canvas, colors); 149 } 150 #include "Resources.h" 151 DEF_SIMPLE_GM(patch_image, canvas, 1500, 1100) { 152 const SkColor colors[SkPatchUtils::kNumCorners] = { 153 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorCYAN 154 }; 155 dopatch(canvas, colors, GetResourceAsImage("images/mandrill_128.png")); 156 } 157 DEF_SIMPLE_GM(patch_alpha, canvas, 1500, 1100) { 158 const SkColor colors[SkPatchUtils::kNumCorners] = { 159 SK_ColorRED, 0x0000FF00, SK_ColorBLUE, 0x00FF00FF, 160 }; 161 dopatch(canvas, colors); 162 } 163 164 // These two should look the same (one patch, one simple path) 165 DEF_SIMPLE_GM(patch_alpha_test, canvas, 550, 250) { 166 canvas->translate(-75, -75); 167 168 const SkColor colors[SkPatchUtils::kNumCorners] = { 169 0x80FF0000, 0x80FF0000, 0x80FF0000, 0x80FF0000, 170 }; 171 SkPaint paint; 172 canvas->drawPatch(gCubics, colors, nullptr, SkBlendMode::kModulate, paint); 173 174 canvas->translate(300, 0); 175 176 SkPath path; 177 path.moveTo(gCubics[0]); 178 path.cubicTo(gCubics[ 1], gCubics[ 2], gCubics[ 3]); 179 path.cubicTo(gCubics[ 4], gCubics[ 5], gCubics[ 6]); 180 path.cubicTo(gCubics[ 7], gCubics[ 8], gCubics[ 9]); 181 path.cubicTo(gCubics[10], gCubics[11], gCubics[ 0]); 182 paint.setColor(colors[0]); 183 canvas->drawPath(path, paint); 184 } 185 186