| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2015 Google Inc. | 3 * Copyright 2015 Google Inc. |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 #include "gm.h" | 8 #include "gm.h" |
| 9 #include "SkArithmeticMode.h" | 9 #include "SkArithmeticMode.h" |
| 10 #include "SkPath.h" | 10 #include "SkPath.h" |
| 11 #include "SkShader.h" | 11 #include "SkShader.h" |
| 12 #include "SkXfermode.h" | 12 #include "SkXfermode.h" |
| 13 | 13 |
| 14 enum { | 14 enum { |
| 15 kXfermodeCount = SkXfermode::kLastMode + 2, // All xfermodes plus arithmetic
mode. | 15 kXfermodeCount = SkXfermode::kLastMode + 2, // All xfermodes plus arithmetic
mode. |
| 16 kShapeSize = 22, | 16 kShapeSize = 22, |
| 17 kShapeSpacing = 36, | 17 kShapeSpacing = 36, |
| 18 kShapeTypeSpacing = 4 * kShapeSpacing / 3, | 18 kShapeTypeSpacing = 4 * kShapeSpacing / 3, |
| 19 kPaintSpacing = 3 * kShapeTypeSpacing, | 19 kPaintSpacing = 4 * kShapeTypeSpacing, |
| 20 kLabelSpacing = 3 * kShapeSize, | 20 kLabelSpacing = 3 * kShapeSize, |
| 21 kMargin = kShapeSpacing / 2, | 21 kMargin = kShapeSpacing / 2, |
| 22 kXfermodeTypeSpacing = kLabelSpacing + 2 * kPaintSpacing + kShapeTypeSpacing
, | 22 kXfermodeTypeSpacing = kLabelSpacing + 2 * kPaintSpacing + kShapeTypeSpacing
, |
| 23 kTitleSpacing = 3 * kShapeSpacing / 4, | 23 kTitleSpacing = 3 * kShapeSpacing / 4, |
| 24 kSubtitleSpacing = 5 * kShapeSpacing / 8 | 24 kSubtitleSpacing = 5 * kShapeSpacing / 8 |
| 25 }; | 25 }; |
| 26 | 26 |
| 27 static const SkColor kBGColor = SkColorSetARGB(200, 210, 184, 135); | 27 static const SkColor kBGColor = SkColorSetARGB(200, 210, 184, 135); |
| 28 | 28 |
| 29 static const SkColor kShapeColors[2] = { | 29 static const SkColor kShapeColors[2] = { |
| 30 SkColorSetARGB(130, 255, 0, 128), // input color unknown | 30 SkColorSetARGB(130, 255, 0, 128), // input color unknown |
| 31 SkColorSetARGB(255, 0, 255, 255) // input color opaque | 31 SkColorSetARGB(255, 0, 255, 255) // input color opaque |
| 32 }; | 32 }; |
| 33 | 33 |
| 34 enum Shape { | 34 enum Shape { |
| 35 kSquare_Shape, | 35 kSquare_Shape, |
| 36 kDiamond_Shape, | 36 kDiamond_Shape, |
| 37 kOval_Shape, | 37 kOval_Shape, |
| 38 kConcave_Shape, |
| 38 | 39 |
| 39 kLast_Shape = kOval_Shape | 40 kLast_Shape = kConcave_Shape |
| 40 }; | 41 }; |
| 41 | 42 |
| 42 namespace skiagm { | 43 namespace skiagm { |
| 43 | 44 |
| 44 /** | 45 /** |
| 45 * Verifies AA works properly on all Xfermodes, including arithmetic, with both
opaque and unknown | 46 * Verifies AA works properly on all Xfermodes, including arithmetic, with both
opaque and unknown |
| 46 * src colors. | 47 * src colors. |
| 47 */ | 48 */ |
| 48 class AAXfermodesGM : public GM { | 49 class AAXfermodesGM : public GM { |
| 49 public: | 50 public: |
| (...skipping 23 matching lines...) Expand all Loading... |
| 73 fLabelPaint.setTextSize(5 * kShapeSize/8); | 74 fLabelPaint.setTextSize(5 * kShapeSize/8); |
| 74 fLabelPaint.setSubpixelText(true); | 75 fLabelPaint.setSubpixelText(true); |
| 75 | 76 |
| 76 static const SkScalar radius = -1.4f * kShapeSize/2; | 77 static const SkScalar radius = -1.4f * kShapeSize/2; |
| 77 SkPoint pts[4] = { | 78 SkPoint pts[4] = { |
| 78 {-radius, 0}, | 79 {-radius, 0}, |
| 79 {0, -1.33f * radius}, | 80 {0, -1.33f * radius}, |
| 80 {radius, 0}, | 81 {radius, 0}, |
| 81 {0, 1.33f * radius} | 82 {0, 1.33f * radius} |
| 82 }; | 83 }; |
| 83 fPath.moveTo(pts[0]); | 84 fOval.moveTo(pts[0]); |
| 84 fPath.quadTo(pts[1], pts[2]); | 85 fOval.quadTo(pts[1], pts[2]); |
| 85 fPath.quadTo(pts[3], pts[0]); | 86 fOval.quadTo(pts[3], pts[0]); |
| 87 |
| 88 fConcave.moveTo(-radius, 0); |
| 89 fConcave.quadTo(0, 0, 0, -radius); |
| 90 fConcave.quadTo(0, 0, radius, 0); |
| 91 fConcave.quadTo(0, 0, 0, radius); |
| 92 fConcave.quadTo(0, 0, -radius, 0); |
| 93 fConcave.close(); |
| 86 } | 94 } |
| 87 | 95 |
| 88 void draw_pass(SkCanvas* canvas, DrawingPass drawingPass) { | 96 void draw_pass(SkCanvas* canvas, DrawingPass drawingPass) { |
| 89 SkRect clipRect = | 97 SkRect clipRect = |
| 90 { -kShapeSize*11/16, -kShapeSize*11/16, kShapeSize*11/16, kShape
Size*11/16 }; | 98 { -kShapeSize*11/16, -kShapeSize*11/16, kShapeSize*11/16, kShape
Size*11/16 }; |
| 91 | 99 |
| 92 canvas->save(); | 100 canvas->save(); |
| 93 if (kCheckerboard_Pass == drawingPass) { | 101 if (kCheckerboard_Pass == drawingPass) { |
| 94 canvas->translate(kMargin, kMargin); | 102 canvas->translate(kMargin, kMargin); |
| 95 } | 103 } |
| 96 canvas->translate(0, kTitleSpacing); | 104 canvas->translate(0, kTitleSpacing); |
| 97 | 105 |
| 98 for (size_t xfermodeSet = 0; xfermodeSet < 2; xfermodeSet++) { | 106 for (size_t xfermodeSet = 0; xfermodeSet < 2; xfermodeSet++) { |
| 99 size_t firstMode = (SkXfermode::kLastCoeffMode + 1) * xfermodeSet; | 107 size_t firstMode = (SkXfermode::kLastCoeffMode + 1) * xfermodeSet; |
| 100 canvas->save(); | 108 canvas->save(); |
| 101 | 109 |
| 102 if (kShape_Pass == drawingPass) { | 110 if (kShape_Pass == drawingPass) { |
| 103 fLabelPaint.setTextAlign(SkPaint::kCenter_Align); | 111 fLabelPaint.setTextAlign(SkPaint::kCenter_Align); |
| 104 canvas->drawText("Src Unknown", sizeof("Src Unknown") - 1, | 112 canvas->drawText("Src Unknown", sizeof("Src Unknown") - 1, |
| 105 kLabelSpacing + kShapeSpacing / 2 + kShapeTypeSpacing, | 113 kLabelSpacing + kShapeTypeSpacing * 1.5f + kShapeSpacing
/ 2, |
| 106 kSubtitleSpacing / 2 + fLabelPaint.getTextSize() / 3, fL
abelPaint); | 114 kSubtitleSpacing / 2 + fLabelPaint.getTextSize() / 3, fL
abelPaint); |
| 107 canvas->drawText("Src Opaque", sizeof("Src Opaque") - 1, | 115 canvas->drawText("Src Opaque", sizeof("Src Opaque") - 1, |
| 108 kLabelSpacing + kShapeSpacing / 2 + kShapeTypeSpacing +
kPaintSpacing, | 116 kLabelSpacing + kShapeTypeSpacing * 1.5f + kShapeSpacing
/ 2 + |
| 109 kSubtitleSpacing / 2 + fLabelPaint.getTextSize() / 3, fL
abelPaint); | 117 kPaintSpacing, kSubtitleSpacing / 2 + fLabelPaint.getTex
tSize() / 3, |
| 118 fLabelPaint); |
| 110 } | 119 } |
| 111 | 120 |
| 112 canvas->translate(0, kSubtitleSpacing + kShapeSpacing/2); | 121 canvas->translate(0, kSubtitleSpacing + kShapeSpacing/2); |
| 113 | 122 |
| 114 for (size_t m = 0; m <= SkXfermode::kLastCoeffMode; m++) { | 123 for (size_t m = 0; m <= SkXfermode::kLastCoeffMode; m++) { |
| 115 SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(firstMode
+ m); | 124 SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(firstMode
+ m); |
| 116 canvas->save(); | 125 canvas->save(); |
| 117 | 126 |
| 118 if (kShape_Pass == drawingPass) { | 127 if (kShape_Pass == drawingPass) { |
| 119 this->drawModeName(canvas, mode); | 128 this->drawModeName(canvas, mode); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 canvas->saveLayer(nullptr, nullptr); | 173 canvas->saveLayer(nullptr, nullptr); |
| 165 | 174 |
| 166 canvas->translate(kMargin, kMargin); | 175 canvas->translate(kMargin, kMargin); |
| 167 draw_pass(canvas, kBackground_Pass); | 176 draw_pass(canvas, kBackground_Pass); |
| 168 | 177 |
| 169 SkPaint titlePaint(fLabelPaint); | 178 SkPaint titlePaint(fLabelPaint); |
| 170 titlePaint.setTextSize(9 * titlePaint.getTextSize() / 8); | 179 titlePaint.setTextSize(9 * titlePaint.getTextSize() / 8); |
| 171 titlePaint.setFakeBoldText(true); | 180 titlePaint.setFakeBoldText(true); |
| 172 titlePaint.setTextAlign(SkPaint::kCenter_Align); | 181 titlePaint.setTextAlign(SkPaint::kCenter_Align); |
| 173 canvas->drawText("Porter Duff", sizeof("Porter Duff") - 1, | 182 canvas->drawText("Porter Duff", sizeof("Porter Duff") - 1, |
| 174 kLabelSpacing + 3 * kShapeTypeSpacing, | 183 kLabelSpacing + 4 * kShapeTypeSpacing, |
| 175 kTitleSpacing / 2 + titlePaint.getTextSize() / 3, title
Paint); | 184 kTitleSpacing / 2 + titlePaint.getTextSize() / 3, title
Paint); |
| 176 canvas->drawText("Advanced", sizeof("Advanced") - 1, | 185 canvas->drawText("Advanced", sizeof("Advanced") - 1, |
| 177 kXfermodeTypeSpacing + kLabelSpacing + 3 * kShapeTypeSp
acing, | 186 kXfermodeTypeSpacing + kLabelSpacing + 4 * kShapeTypeSp
acing, |
| 178 kTitleSpacing / 2 + titlePaint.getTextSize() / 3, title
Paint); | 187 kTitleSpacing / 2 + titlePaint.getTextSize() / 3, title
Paint); |
| 179 | 188 |
| 180 draw_pass(canvas, kShape_Pass); | 189 draw_pass(canvas, kShape_Pass); |
| 181 canvas->restore(); | 190 canvas->restore(); |
| 182 } | 191 } |
| 183 | 192 |
| 184 void drawModeName(SkCanvas* canvas, SkXfermode::Mode mode) { | 193 void drawModeName(SkCanvas* canvas, SkXfermode::Mode mode) { |
| 185 const char* modeName = mode <= SkXfermode::kLastMode ? SkXfermode::ModeN
ame(mode) | 194 const char* modeName = mode <= SkXfermode::kLastMode ? SkXfermode::ModeN
ame(mode) |
| 186 : "Arithmetic"; | 195 : "Arithmetic"; |
| 187 fLabelPaint.setTextAlign(SkPaint::kRight_Align); | 196 fLabelPaint.setTextAlign(SkPaint::kRight_Align); |
| 188 canvas->drawText(modeName, strlen(modeName), kLabelSpacing - kShapeSize
/ 4, | 197 canvas->drawText(modeName, strlen(modeName), kLabelSpacing - kShapeSize
/ 4, |
| 189 fLabelPaint.getTextSize() / 3, fLabelPaint); | 198 fLabelPaint.getTextSize() / 4, fLabelPaint); |
| 190 } | 199 } |
| 191 | 200 |
| 192 void setupShapePaint(SkCanvas* canvas, GrColor color, SkXfermode::Mode mode,
SkPaint* paint) { | 201 void setupShapePaint(SkCanvas* canvas, GrColor color, SkXfermode::Mode mode,
SkPaint* paint) { |
| 193 paint->setColor(color); | 202 paint->setColor(color); |
| 194 | 203 |
| 195 if (mode == SkXfermode::kPlus_Mode) { | 204 if (mode == SkXfermode::kPlus_Mode) { |
| 196 // Check for overflow, otherwise we might get confusing AA artifacts
. | 205 // Check for overflow, otherwise we might get confusing AA artifacts
. |
| 197 int maxSum = SkTMax(SkTMax(SkColorGetA(kBGColor) + SkColorGetA(color
), | 206 int maxSum = SkTMax(SkTMax(SkColorGetA(kBGColor) + SkColorGetA(color
), |
| 198 SkColorGetR(kBGColor) + SkColorGetR(color
)), | 207 SkColorGetR(kBGColor) + SkColorGetR(color
)), |
| 199 SkTMax(SkColorGetG(kBGColor) + SkColorGetG(color
), | 208 SkTMax(SkColorGetG(kBGColor) + SkColorGetG(color
), |
| 200 SkColorGetB(kBGColor) + SkColorGetB(color
))); | 209 SkColorGetB(kBGColor) + SkColorGetB(color
))); |
| 201 | 210 |
| 202 if (maxSum > 255) { | 211 if (maxSum > 255) { |
| 203 SkPaint dimPaint; | 212 SkPaint dimPaint; |
| 204 dimPaint.setAntiAlias(false); | 213 dimPaint.setAntiAlias(false); |
| 205 dimPaint.setXfermode(SkXfermode::Create(SkXfermode::kDstIn_Mode)
); | 214 dimPaint.setXfermode(SkXfermode::Create(SkXfermode::kDstIn_Mode)
); |
| 206 if (255 != paint->getAlpha()) { | 215 if (255 != paint->getAlpha()) { |
| 207 // Dim the src and dst colors. | 216 // Dim the src and dst colors. |
| 208 dimPaint.setARGB(255 * 255 / maxSum, 0, 0, 0); | 217 dimPaint.setARGB(255 * 255 / maxSum, 0, 0, 0); |
| 209 paint->setAlpha(255 * paint->getAlpha() / maxSum); | 218 paint->setAlpha(255 * paint->getAlpha() / maxSum); |
| 210 } else { | 219 } else { |
| 211 // Just clear the dst, we need to preserve the paint's opaci
ty. | 220 // Just clear the dst, we need to preserve the paint's opaci
ty. |
| 212 dimPaint.setARGB(0, 0, 0, 0); | 221 dimPaint.setARGB(0, 0, 0, 0); |
| 213 } | 222 } |
| 214 canvas->drawRectCoords(-kShapeSpacing/2, -kShapeSpacing/2, | 223 canvas->drawRectCoords(-kShapeSpacing/2, -kShapeSpacing/2, |
| 215 kShapeSpacing/2 + 2 * kShapeTypeSpacing, | 224 kShapeSpacing/2 + 3 * kShapeTypeSpacing, |
| 216 kShapeSpacing/2, dimPaint); | 225 kShapeSpacing/2, dimPaint); |
| 217 } | 226 } |
| 218 } | 227 } |
| 219 } | 228 } |
| 220 | 229 |
| 221 void drawShape(SkCanvas* canvas, Shape shape, const SkPaint& paint, SkXfermo
de::Mode mode) { | 230 void drawShape(SkCanvas* canvas, Shape shape, const SkPaint& paint, SkXfermo
de::Mode mode) { |
| 222 SkPaint shapePaint(paint); | 231 SkPaint shapePaint(paint); |
| 223 shapePaint.setAntiAlias(kSquare_Shape != shape); | 232 shapePaint.setAntiAlias(kSquare_Shape != shape); |
| 224 | 233 |
| 225 SkAutoTUnref<SkXfermode> xfermode; | 234 SkAutoTUnref<SkXfermode> xfermode; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 240 canvas->save(); | 249 canvas->save(); |
| 241 canvas->rotate(45); | 250 canvas->rotate(45); |
| 242 canvas->drawRectCoords(-kShapeSize/2, -kShapeSize/2, kShapeSize/
2, kShapeSize/2, | 251 canvas->drawRectCoords(-kShapeSize/2, -kShapeSize/2, kShapeSize/
2, kShapeSize/2, |
| 243 shapePaint); | 252 shapePaint); |
| 244 canvas->restore(); | 253 canvas->restore(); |
| 245 break; | 254 break; |
| 246 | 255 |
| 247 case kOval_Shape: | 256 case kOval_Shape: |
| 248 canvas->save(); | 257 canvas->save(); |
| 249 canvas->rotate(static_cast<SkScalar>((511 * mode + 257) % 360)); | 258 canvas->rotate(static_cast<SkScalar>((511 * mode + 257) % 360)); |
| 250 canvas->drawPath(fPath, shapePaint); | 259 canvas->drawPath(fOval, shapePaint); |
| 251 canvas->restore(); | 260 canvas->restore(); |
| 252 break; | 261 break; |
| 253 | 262 |
| 263 case kConcave_Shape: |
| 264 canvas->drawPath(fConcave, shapePaint); |
| 265 break; |
| 266 |
| 254 default: | 267 default: |
| 255 SkFAIL("Invalid shape."); | 268 SkFAIL("Invalid shape."); |
| 256 } | 269 } |
| 257 } | 270 } |
| 258 | 271 |
| 259 private: | 272 private: |
| 260 SkPaint fLabelPaint; | 273 SkPaint fLabelPaint; |
| 261 SkPath fPath; | 274 SkPath fOval; |
| 275 SkPath fConcave; |
| 262 | 276 |
| 263 typedef GM INHERITED; | 277 typedef GM INHERITED; |
| 264 }; | 278 }; |
| 265 | 279 |
| 266 ////////////////////////////////////////////////////////////////////////////// | 280 ////////////////////////////////////////////////////////////////////////////// |
| 267 | 281 |
| 268 static GM* MyFactory(void*) { return new AAXfermodesGM; } | 282 static GM* MyFactory(void*) { return new AAXfermodesGM; } |
| 269 static GMRegistry reg(MyFactory); | 283 static GMRegistry reg(MyFactory); |
| 270 | 284 |
| 271 } | 285 } |
| OLD | NEW |