OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 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 "SkBitmap.h" | 9 #include "SkBitmap.h" |
10 #include "SkShader.h" | 10 #include "SkShader.h" |
11 #include "SkXfermode.h" | 11 #include "SkXfermode.h" |
12 | 12 |
13 namespace skiagm { | 13 enum SrcType { |
| 14 //! A WxH image with a rectangle in the lower right. |
| 15 kRectangleImage_SrcType = 0x01, |
| 16 //! kRectangleImage_SrcType with an alpha of 34.5%. |
| 17 kRectangleImageWithAlpha_SrcType = 0x02, |
| 18 //! kRectnagleImageWithAlpha_SrcType scaled down by half. |
| 19 kSmallRectangleImageWithAlpha_SrcType = 0x04, |
| 20 //! kRectangleImage_SrcType drawn directly instead in an image. |
| 21 kRectangle_SrcType = 0x08, |
| 22 //! Two rectangles, first on the right half, second on the bottom half. |
| 23 kQuarterClear_SrcType = 0x10, |
| 24 //! kQuarterClear_SrcType in a layer. |
| 25 kQuarterClearInLayer_SrcType = 0x20, |
| 26 //! A W/2xH/2 transparent image. |
| 27 kSmallTransparentImage_SrcType = 0x40, |
| 28 //! kRectangleImage_SrcType drawn directly with a mask. |
| 29 kRectangleWithMask_SrcType = 0x80, |
| 30 |
| 31 kAll_SrcType = 0xFF, //!< All the source types. |
| 32 kBasic_SrcType = 0x03, //!< Just basic source types. |
| 33 }; |
| 34 |
| 35 const struct { |
| 36 SkXfermode::Mode fMode; |
| 37 const char* fLabel; |
| 38 int fSourceTypeMask; // The source types to use this |
| 39 // mode with. See draw_mode for |
| 40 // an explanation of each type. |
| 41 // PDF has to play some tricks |
| 42 // to support the base modes, |
| 43 // test those more extensively. |
| 44 } gModes[] = { |
| 45 { SkXfermode::kClear_Mode, "Clear", kAll_SrcType }, |
| 46 { SkXfermode::kSrc_Mode, "Src", kAll_SrcType }, |
| 47 { SkXfermode::kDst_Mode, "Dst", kAll_SrcType }, |
| 48 { SkXfermode::kSrcOver_Mode, "SrcOver", kAll_SrcType }, |
| 49 { SkXfermode::kDstOver_Mode, "DstOver", kAll_SrcType }, |
| 50 { SkXfermode::kSrcIn_Mode, "SrcIn", kAll_SrcType }, |
| 51 { SkXfermode::kDstIn_Mode, "DstIn", kAll_SrcType }, |
| 52 { SkXfermode::kSrcOut_Mode, "SrcOut", kAll_SrcType }, |
| 53 { SkXfermode::kDstOut_Mode, "DstOut", kAll_SrcType }, |
| 54 { SkXfermode::kSrcATop_Mode, "SrcATop", kAll_SrcType }, |
| 55 { SkXfermode::kDstATop_Mode, "DstATop", kAll_SrcType }, |
| 56 |
| 57 { SkXfermode::kXor_Mode, "Xor", kBasic_SrcType }, |
| 58 { SkXfermode::kPlus_Mode, "Plus", kBasic_SrcType }, |
| 59 { SkXfermode::kModulate_Mode, "Modulate", kAll_SrcType }, |
| 60 { SkXfermode::kScreen_Mode, "Screen", kBasic_SrcType }, |
| 61 { SkXfermode::kOverlay_Mode, "Overlay", kBasic_SrcType }, |
| 62 { SkXfermode::kDarken_Mode, "Darken", kBasic_SrcType }, |
| 63 { SkXfermode::kLighten_Mode, "Lighten", kBasic_SrcType }, |
| 64 { SkXfermode::kColorDodge_Mode, "ColorDodge", kBasic_SrcType }, |
| 65 { SkXfermode::kColorBurn_Mode, "ColorBurn", kBasic_SrcType }, |
| 66 { SkXfermode::kHardLight_Mode, "HardLight", kBasic_SrcType }, |
| 67 { SkXfermode::kSoftLight_Mode, "SoftLight", kBasic_SrcType }, |
| 68 { SkXfermode::kDifference_Mode, "Difference", kBasic_SrcType }, |
| 69 { SkXfermode::kExclusion_Mode, "Exclusion", kBasic_SrcType }, |
| 70 { SkXfermode::kMultiply_Mode, "Multiply", kAll_SrcType }, |
| 71 { SkXfermode::kHue_Mode, "Hue", kBasic_SrcType }, |
| 72 { SkXfermode::kSaturation_Mode, "Saturation", kBasic_SrcType }, |
| 73 { SkXfermode::kColor_Mode, "Color", kBasic_SrcType }, |
| 74 { SkXfermode::kLuminosity_Mode, "Luminosity", kBasic_SrcType }, |
| 75 }; |
14 | 76 |
15 static void make_bitmaps(int w, int h, SkBitmap* src, SkBitmap* dst, | 77 static void make_bitmaps(int w, int h, SkBitmap* src, SkBitmap* dst, |
16 SkBitmap* transparent) { | 78 SkBitmap* transparent) { |
17 src->allocN32Pixels(w, h); | 79 src->allocN32Pixels(w, h); |
18 src->eraseColor(SK_ColorTRANSPARENT); | 80 src->eraseColor(SK_ColorTRANSPARENT); |
19 | 81 |
20 SkPaint p; | 82 SkPaint p; |
21 p.setAntiAlias(true); | 83 p.setAntiAlias(true); |
22 | 84 |
23 SkRect r; | 85 SkRect r; |
(...skipping 16 matching lines...) Expand all Loading... |
40 r.set(ww/3, hh/3, ww*19/20, hh*19/20); | 102 r.set(ww/3, hh/3, ww*19/20, hh*19/20); |
41 c.drawRect(r, p); | 103 c.drawRect(r, p); |
42 } | 104 } |
43 | 105 |
44 transparent->allocN32Pixels(w, h); | 106 transparent->allocN32Pixels(w, h); |
45 transparent->eraseColor(SK_ColorTRANSPARENT); | 107 transparent->eraseColor(SK_ColorTRANSPARENT); |
46 } | 108 } |
47 | 109 |
48 static uint16_t gData[] = { 0xFFFF, 0xCCCF, 0xCCCF, 0xFFFF }; | 110 static uint16_t gData[] = { 0xFFFF, 0xCCCF, 0xCCCF, 0xFFFF }; |
49 | 111 |
50 class XfermodesGM : public GM { | 112 class XfermodesGM : public skiagm::GM { |
51 enum SrcType { | |
52 //! A WxH image with a rectangle in the lower right. | |
53 kRectangleImage_SrcType = 0x01, | |
54 //! kRectangleImage_SrcType with an alpha of 34.5%. | |
55 kRectangleImageWithAlpha_SrcType = 0x02, | |
56 //! kRectnagleImageWithAlpha_SrcType scaled down by half. | |
57 kSmallRectangleImageWithAlpha_SrcType = 0x04, | |
58 //! kRectangleImage_SrcType drawn directly instead in an image. | |
59 kRectangle_SrcType = 0x08, | |
60 //! Two rectangles, first on the right half, second on the bottom half. | |
61 kQuarterClear_SrcType = 0x10, | |
62 //! kQuarterClear_SrcType in a layer. | |
63 kQuarterClearInLayer_SrcType = 0x20, | |
64 //! A W/2xH/2 transparent image. | |
65 kSmallTransparentImage_SrcType = 0x40, | |
66 //! kRectangleImage_SrcType drawn directly with a mask. | |
67 kRectangleWithMask_SrcType = 0x80, | |
68 | |
69 kAll_SrcType = 0xFF, //!< All the source types. | |
70 kBasic_SrcType = 0x03, //!< Just basic source types. | |
71 }; | |
72 | |
73 SkBitmap fBG; | 113 SkBitmap fBG; |
74 SkBitmap fSrcB, fDstB, fTransparent; | 114 SkBitmap fSrcB, fDstB, fTransparent; |
75 | 115 |
76 /* The srcType argument indicates what to draw for the source part. Skia | 116 /* The srcType argument indicates what to draw for the source part. Skia |
77 * uses the implied shape of the drawing command and these modes | 117 * uses the implied shape of the drawing command and these modes |
78 * demonstrate that. | 118 * demonstrate that. |
79 */ | 119 */ |
80 void draw_mode(SkCanvas* canvas, SkXfermode* mode, SrcType srcType, | 120 void draw_mode(SkCanvas* canvas, SkXfermode* mode, SrcType srcType, |
81 SkScalar x, SkScalar y) { | 121 SkScalar x, SkScalar y) { |
82 SkPaint p; | 122 SkPaint p; |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 return SkString("xfermodes"); | 212 return SkString("xfermodes"); |
173 } | 213 } |
174 | 214 |
175 SkISize onISize() override { | 215 SkISize onISize() override { |
176 return SkISize::Make(1990, 640); | 216 return SkISize::Make(1990, 640); |
177 } | 217 } |
178 | 218 |
179 void onDraw(SkCanvas* canvas) override { | 219 void onDraw(SkCanvas* canvas) override { |
180 canvas->translate(SkIntToScalar(10), SkIntToScalar(20)); | 220 canvas->translate(SkIntToScalar(10), SkIntToScalar(20)); |
181 | 221 |
182 const struct { | |
183 SkXfermode::Mode fMode; | |
184 const char* fLabel; | |
185 int fSourceTypeMask; // The source types to use this | |
186 // mode with. See draw_mode for | |
187 // an explanation of each type. | |
188 // PDF has to play some tricks | |
189 // to support the base modes, | |
190 // test those more extensively. | |
191 } gModes[] = { | |
192 { SkXfermode::kClear_Mode, "Clear", kAll_SrcType }, | |
193 { SkXfermode::kSrc_Mode, "Src", kAll_SrcType }, | |
194 { SkXfermode::kDst_Mode, "Dst", kAll_SrcType }, | |
195 { SkXfermode::kSrcOver_Mode, "SrcOver", kAll_SrcType }, | |
196 { SkXfermode::kDstOver_Mode, "DstOver", kAll_SrcType }, | |
197 { SkXfermode::kSrcIn_Mode, "SrcIn", kAll_SrcType }, | |
198 { SkXfermode::kDstIn_Mode, "DstIn", kAll_SrcType }, | |
199 { SkXfermode::kSrcOut_Mode, "SrcOut", kAll_SrcType }, | |
200 { SkXfermode::kDstOut_Mode, "DstOut", kAll_SrcType }, | |
201 { SkXfermode::kSrcATop_Mode, "SrcATop", kAll_SrcType }, | |
202 { SkXfermode::kDstATop_Mode, "DstATop", kAll_SrcType }, | |
203 | |
204 { SkXfermode::kXor_Mode, "Xor", kBasic_SrcType }, | |
205 { SkXfermode::kPlus_Mode, "Plus", kBasic_SrcType }, | |
206 { SkXfermode::kModulate_Mode, "Modulate", kAll_SrcType }, | |
207 { SkXfermode::kScreen_Mode, "Screen", kBasic_SrcType }, | |
208 { SkXfermode::kOverlay_Mode, "Overlay", kBasic_SrcType }, | |
209 { SkXfermode::kDarken_Mode, "Darken", kBasic_SrcType }, | |
210 { SkXfermode::kLighten_Mode, "Lighten", kBasic_SrcType }, | |
211 { SkXfermode::kColorDodge_Mode, "ColorDodge", kBasic_SrcType }, | |
212 { SkXfermode::kColorBurn_Mode, "ColorBurn", kBasic_SrcType }, | |
213 { SkXfermode::kHardLight_Mode, "HardLight", kBasic_SrcType }, | |
214 { SkXfermode::kSoftLight_Mode, "SoftLight", kBasic_SrcType }, | |
215 { SkXfermode::kDifference_Mode, "Difference", kBasic_SrcType }, | |
216 { SkXfermode::kExclusion_Mode, "Exclusion", kBasic_SrcType }, | |
217 { SkXfermode::kMultiply_Mode, "Multiply", kAll_SrcType }, | |
218 { SkXfermode::kHue_Mode, "Hue", kBasic_SrcType }, | |
219 { SkXfermode::kSaturation_Mode, "Saturation", kBasic_SrcType }, | |
220 { SkXfermode::kColor_Mode, "Color", kBasic_SrcType }, | |
221 { SkXfermode::kLuminosity_Mode, "Luminosity", kBasic_SrcType }, | |
222 }; | |
223 | |
224 const SkScalar w = SkIntToScalar(W); | 222 const SkScalar w = SkIntToScalar(W); |
225 const SkScalar h = SkIntToScalar(H); | 223 const SkScalar h = SkIntToScalar(H); |
226 SkMatrix m; | 224 SkMatrix m; |
227 m.setScale(SkIntToScalar(6), SkIntToScalar(6)); | 225 m.setScale(SkIntToScalar(6), SkIntToScalar(6)); |
228 SkShader* s = SkShader::CreateBitmapShader(fBG, | 226 SkShader* s = SkShader::CreateBitmapShader(fBG, |
229 SkShader::kRepeat_TileMode, | 227 SkShader::kRepeat_TileMode, |
230 SkShader::kRepeat_TileMode, | 228 SkShader::kRepeat_TileMode, |
231 &m); | 229 &m); |
232 | 230 |
233 SkPaint labelP; | 231 SkPaint labelP; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
284 x0 += SkIntToScalar(400); | 282 x0 += SkIntToScalar(400); |
285 y0 = 0; | 283 y0 = 0; |
286 } | 284 } |
287 } | 285 } |
288 s->unref(); | 286 s->unref(); |
289 } | 287 } |
290 | 288 |
291 private: | 289 private: |
292 typedef GM INHERITED; | 290 typedef GM INHERITED; |
293 }; | 291 }; |
| 292 DEF_GM( return new XfermodesGM; ) |
294 | 293 |
295 ////////////////////////////////////////////////////////////////////////////// | 294 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
| 295 #include "SkNx.h" |
296 | 296 |
297 static GM* MyFactory(void*) { return new XfermodesGM; } | 297 static SkPMColor apply_proc(SkPMColor src, SkPMColor dst, SkXfermodeProc4f proc,
float src_alpha) { |
298 static GMRegistry reg(MyFactory); | 298 SkPM4f src4 = SkPM4f::FromPMColor(src); |
| 299 for (int i = 0; i < 4; ++i) { |
| 300 src4.fVec[i] *= src_alpha; |
| 301 } |
| 302 SkPM4f dst4 = SkPM4f::FromPMColor(dst); |
| 303 SkPM4f res4 = proc(src4, dst4); |
| 304 SkPMColor res; |
| 305 SkNx_cast<uint8_t>(Sk4f::Load(res4.fVec) * Sk4f(255) + Sk4f(0.5f)).store(&re
s); |
| 306 return res; |
| 307 } |
299 | 308 |
| 309 static bool apply_mode(const SkPixmap& res, const SkPixmap& src, const SkPixmap&
dst, |
| 310 SkXfermode* xfer, float src_alpha) { |
| 311 SkXfermode::Mode mode; |
| 312 if (!xfer) { |
| 313 mode = SkXfermode::kSrcOver_Mode; |
| 314 } else if (!xfer->asMode(&mode)) { |
| 315 return false; |
| 316 } |
| 317 SkXfermodeProc4f proc = SkXfermode::GetProc4f(mode); |
| 318 if (!proc) { |
| 319 return false; |
| 320 } |
| 321 |
| 322 for (int y = 0; y < res.height(); ++y) { |
| 323 for (int x = 0; x < res.width(); ++x) { |
| 324 *res.writable_addr32(x, y) = apply_proc(*src.addr32(x, y), *dst.addr
32(x, y), |
| 325 proc, src_alpha); |
| 326 } |
| 327 } |
| 328 return true; |
300 } | 329 } |
| 330 |
| 331 void draw_mode(const SkBitmap& srcB, const SkBitmap& dstB, |
| 332 SkCanvas* canvas, SkXfermode* mode, SkScalar x, SkScalar y, float
src_alpha) { |
| 333 SkBitmap resB; |
| 334 resB.allocN32Pixels(64, 64); |
| 335 |
| 336 SkPixmap srcPM, dstPM, resPM; |
| 337 srcB.peekPixels(&srcPM); |
| 338 dstB.peekPixels(&dstPM); |
| 339 resB.peekPixels(&resPM); |
| 340 |
| 341 if (apply_mode(resPM, srcPM, dstPM, mode, src_alpha)) { |
| 342 canvas->drawBitmap(resB, x, y, nullptr); |
| 343 } |
| 344 } |
| 345 |
| 346 DEF_SIMPLE_GM(xfermodes_proc4f, canvas, 1000, 1000) { |
| 347 SkBitmap bg, srcB, dstB, transparent; |
| 348 |
| 349 bg.installPixels(SkImageInfo::Make(2, 2, kARGB_4444_SkColorType, kOpaque_SkA
lphaType), |
| 350 gData, 4); |
| 351 make_bitmaps(64, 64, &dstB, &srcB, &transparent); |
| 352 |
| 353 canvas->translate(10, 20); |
| 354 |
| 355 const SkScalar w = 64; |
| 356 const SkScalar h = 64; |
| 357 SkMatrix m = SkMatrix::MakeScale(6, 6); |
| 358 SkShader* s = SkShader::CreateBitmapShader(bg, |
| 359 SkShader::kRepeat_TileMode, |
| 360 SkShader::kRepeat_TileMode, |
| 361 &m); |
| 362 |
| 363 SkPaint labelP; |
| 364 labelP.setAntiAlias(true); |
| 365 sk_tool_utils::set_portable_typeface(&labelP); |
| 366 labelP.setTextAlign(SkPaint::kCenter_Align); |
| 367 |
| 368 const int W = 5; |
| 369 |
| 370 const float alphas[] = { 1.0f, 0.5f }; |
| 371 |
| 372 for (auto alpha : alphas) { |
| 373 SkScalar x0 = 0; |
| 374 SkScalar y0 = 0; |
| 375 SkScalar x = x0, y = y0; |
| 376 for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); i++) { |
| 377 SkXfermode* mode = SkXfermode::Create(gModes[i].fMode); |
| 378 SkAutoUnref aur(mode); |
| 379 SkRect r; |
| 380 r.set(x, y, x+w, y+h); |
| 381 |
| 382 SkPaint p; |
| 383 p.setStyle(SkPaint::kFill_Style); |
| 384 p.setShader(s); |
| 385 canvas->drawRect(r, p); |
| 386 |
| 387 draw_mode(srcB, dstB, canvas, mode, r.fLeft, r.fTop, alpha); |
| 388 |
| 389 r.inset(-SK_ScalarHalf, -SK_ScalarHalf); |
| 390 p.setStyle(SkPaint::kStroke_Style); |
| 391 p.setShader(nullptr); |
| 392 canvas->drawRect(r, p); |
| 393 |
| 394 #if 1 |
| 395 canvas->drawText(gModes[i].fLabel, strlen(gModes[i].fLabel), |
| 396 x + w/2, y - labelP.getTextSize()/2, labelP); |
| 397 #endif |
| 398 x += w + SkIntToScalar(10); |
| 399 if ((i % W) == W - 1) { |
| 400 x = x0; |
| 401 y += h + SkIntToScalar(30); |
| 402 } |
| 403 } |
| 404 if (y < 320) { |
| 405 if (x > x0) { |
| 406 y += h + SkIntToScalar(30); |
| 407 } |
| 408 y0 = y; |
| 409 } else { |
| 410 x0 += SkIntToScalar(400); |
| 411 y0 = 0; |
| 412 } |
| 413 |
| 414 canvas->translate(400, 0); |
| 415 } |
| 416 s->unref(); |
| 417 } |
OLD | NEW |