blob: 3e4aa4c168e0162d3b3e2bf24c59a88600a43fbe [file] [log] [blame]
Cary Clark224c7002018-06-27 11:00:21 -04001#Topic Blend_Mode
2#Alias BlendMode_Reference ##
3
4#Subtopic Overview
5#Populate
6##
7
8#Subtopic Member_Function
9#Populate
10##
11
12#Subtopic Constant
13#Populate
14##
15
16Describes how destination pixel is replaced with a combination of itself and
17source pixel. Blend_Mode may use source, destination, or both. Blend_Mode may
18operate on each Color component independently, or may allow all source pixel
19components to contribute to one destination pixel component.
20
21Blend_Mode does not use adjacent pixels to determine the outcome.
22
23Blend_Mode uses source and read destination Alpha to determine written
24destination Alpha; both source and destination Alpha may also affect written
25destination Color components.
26
27Regardless of how Alpha is encoded in source and destination pixel, nearly all
28Color_Types treat it as ranging from zero to one. And, nearly all Blend_Mode
29algorithms limit the output so that all results are also zero to one.
30
31Two exceptions are SkBlendMode::kPlus and kRGBA_F16_SkColorType.
32
33SkBlendMode::kPlus permits computing Alpha and Color component values larger
34than one. For Color_Types other than kRGBA_F16_SkColorType, resulting Alpha
35and component values are clamped to one.
36
37kRGBA_F16_SkColorType permits values outside the zero to one range. It is up
38to the client to ensure that the result is within the range of zero to one,
39and therefore well-defined.
40
41#Subtopic Porter_Duff
42
43#A Compositing Digital Images # https://graphics.pixar.com/library/Compositing/paper.pdf ##
44describes Porter_Duff modes SkBlendMode::kClear through SkBlendMode::kXor.
45
46Drawing a bitmap with transparency using Porter_Duff compositing is free to clear
47the destination.
48
49#Illustration 1
50
51Draw geometry with transparency using Porter_Duff compositing does not combine
52transparent source pixels, leaving the destination outside the geometry untouched.
53
54#Illustration 2
55
56##
57
58#Subtopic Lighten_Darken
59
60Modes SkBlendMode::kPlus and SkBlendMode::kScreen use
61simple arithmetic to lighten or darken the destination. Modes
62SkBlendMode::kOverlay through SkBlendMode::kMultiply use more complicated
63algorithms to lighten or darken; sometimes one mode does both, as described by
64#A Blend Modes # https://en.wikipedia.org/wiki/Blend_modes ##
65.
66
67#Illustration
68
69##
70
71#Subtopic Modulate_Blend
72SkBlendMode::kModulate is a mashup of SkBlendMode::kSrcATop and SkBlendMode::kMultiply.
73It multiplies all components, including Alpha; unlike SkBlendMode::kMultiply, if either
74source or destination is transparent, result is transparent. SkBlendMode::kModulate
75uses Premultiplied values to compute the product; SkBlendMode::kMultiply uses Unpremultiplied
76values to compute the product.
77
78#Illustration
79
80##
81
82#Subtopic Color_Blends
83
84Modes SkBlendMode::kHue, SkBlendMode::kSaturation, SkBlendMode::kColor, and
85SkBlendMode::kLuminosity convert source and destination pixels using all
86components color information, using
87###$
88$A non-separable blend modes $ https://www.w3.org/TR/compositing-1/#blendingnonseparable $$
89$$$#
90.
91
92#Illustration
93
94##
95
96# ------------------------------------------------------------------------------
97
98#PhraseDef list_of_blend_modes
99SkBlendMode::kClear, SkBlendMode::kSrc, SkBlendMode::kDst, SkBlendMode::kSrcOver,
100SkBlendMode::kDstOver, SkBlendMode::kSrcIn, SkBlendMode::kDstIn,
101SkBlendMode::kSrcOut, SkBlendMode::kDstOut, SkBlendMode::kSrcATop,
102SkBlendMode::kDstATop, SkBlendMode::kXor, SkBlendMode::kPlus,
103SkBlendMode::kModulate, SkBlendMode::kScreen, SkBlendMode::kOverlay,
104SkBlendMode::kDarken, SkBlendMode::kLighten, SkBlendMode::kColorDodge,
105SkBlendMode::kColorBurn, SkBlendMode::kHardLight, SkBlendMode::kSoftLight,
106SkBlendMode::kDifference, SkBlendMode::kExclusion, SkBlendMode::kMultiply,
107SkBlendMode::kHue, SkBlendMode::kSaturation, SkBlendMode::kColor,
108SkBlendMode::kLuminosity
109##
110
111#EnumClass SkBlendMode
112#Line # algorithm combining source and destination pixels ##
113
114#Code
115 enum class SkBlendMode {
116 kClear,
117 kSrc,
118 kDst,
119 kSrcOver,
120 kDstOver,
121 kSrcIn,
122 kDstIn,
123 kSrcOut,
124 kDstOut,
125 kSrcATop,
126 kDstATop,
127 kXor,
128 kPlus,
129 kModulate,
130 kScreen,
131 kLastCoeffMode = kScreen,
132 kOverlay,
133 kDarken,
134 kLighten,
135 kColorDodge,
136 kColorBurn,
137 kHardLight,
138 kSoftLight,
139 kDifference,
140 kExclusion,
141 kMultiply,
142 kLastSeparableMode = kMultiply,
143 kHue,
144 kSaturation,
145 kColor,
146 kLuminosity,
147 kLastMode = kLuminosity,
148 };
149##
150
151#Const kClear 0
152#Line # replaces destination with zero: fully transparent ##
153#Details Clear
154Replaces destination with Alpha and Color components set to zero;
155a fully transparent pixel.
156##
157
158#Const kSrc 1
159#Line # replaces destination ##
160#Details Src
161Replaces destination with source. Destination alpha and color component values
162are ignored.
163##
164
165#Const kDst 2
166#Line # preserves destination ##
167#Details Dst
168Preserves destination, ignoring source. Drawing with Paint set to kDst has
169no effect.
170##
171
172#Const kSrcOver 3
173#Line # source over destination ##
174#Details Src_Over
175Replaces destination with source blended with destination. If source is opaque,
176replaces destination with source. Used as the default Blend_Mode for SkPaint.
177##
178
179#Const kDstOver 4
180#Line # destination over source ##
181#Details Dst_Over
182Replaces destination with destination blended with source. If destination is opaque,
183has no effect.
184##
185
186#Const kSrcIn 5
187#Line # source trimmed inside destination ##
188#Details Src_In
189Replaces destination with source using destination opacity.
190##
191
192#Const kDstIn 6
193#Line # destination trimmed by source ##
194#Details Dst_In
195Scales destination opacity by source opacity.
196##
197
198#Const kSrcOut 7
199#Line # source trimmed outside destination ##
200#Details Src_Out
201Replaces destination with source using the inverse of destination opacity,
202drawing source fully where destination opacity is zero.
203##
204
205#Const kDstOut 8
206#Line # destination trimmed outside source ##
207#Details Dst_Out
208Replaces destination opacity with inverse of source opacity. If source is
209transparent, has no effect.
210##
211
212#Const kSrcATop 9
213#Line # source inside destination blended with destination ##
214#Details Src_Atop
215Blends destination with source using read destination opacity.
216##
217
218#Const kDstATop 10
219#Line # destination inside source blended with source ##
220#Details Dst_Atop
221Blends destination with source using source opacity.
222##
223
224#Const kXor 11
225#Line # each of source and destination trimmed outside the other ##
226#Details Xor
227Blends destination by exchanging transparency of the source and destination.
228##
229
230#Const kPlus 12
231#Line # sum of colors ##
232#Details Plus
233Replaces destination with source and destination added together.
234##
235
236#Const kModulate 13
237#Line # product of Premultiplied colors; darkens destination ##
238#Details Modulate
239Replaces destination with source and destination multiplied together.
240##
241
242#Const kScreen 14
243#Line # multiply inverse of pixels, inverting result; brightens destination ##
244#Details Screen
245Replaces destination with inverted source and destination multiplied together.
246##
247
248#Const kLastCoeffMode 14
249#Line # last Porter_Duff blend mode ##
250##
251
252#Const kOverlay 15
253#Line # multiply or screen, depending on destination ##
254#Details Overlay
255Replaces destination with multiply or screen, depending on destination.
256##
257
258#Const kDarken 16
259#Line # darker of source and destination ##
260#Details Darken
261Replaces destination with darker of source and destination.
262##
263
264#Const kLighten 17
265#Line # lighter of source and destination ##
266#Details Lighten
267Replaces destination with lighter of source and destination.
268##
269
270#Const kColorDodge 18
271#Line # brighten destination to reflect source ##
272#Details Color_Dodge
273Makes destination brighter to reflect source.
274##
275
276#Const kColorBurn 19
277#Line # darken destination to reflect source ##
278#Details Color_Burn
279Makes destination darker to reflect source.
280##
281
282#Const kHardLight 20
283#Line # multiply or screen, depending on source ##
284#Details Hard_Light
285Makes destination lighter or darker, depending on source.
286##
287
288#Const kSoftLight 21
289#Line # lighten or darken, depending on source ##
290#Details Soft_Light
291Makes destination lighter or darker, depending on source.
292##
293
294#Const kDifference 22
295#Line # subtract darker from lighter with higher contrast ##
296#Details Difference
297Subtracts darker from lighter with higher contrast.
298##
299
300#Const kExclusion 23
301#Line # subtract darker from lighter with lower contrast ##
302#Details Exclusion
303Subtracts darker from lighter with lower contrast.
304##
305
306#Const kMultiply 24
307#Line # multiply source with destination, darkening image ##
308#Details Multiply
309Multiplies source with destination, darkening image.
310##
311
312#Const kLastSeparableMode 24
313#Line # last blend mode operating separately on components ##
314Last blend mode operating separately on components.
315##
316
317#Const kHue 25
318#Line # hue of source with saturation and luminosity of destination ##
319#Details Hue
320Replaces hue of destination with hue of source, leaving saturation and luminosity
321unchanged.
322##
323
324#Const kSaturation 26
325#Line # saturation of source with hue and luminosity of destination ##
326#Details Saturation
327Replaces saturation of destination saturation hue of source, leaving hue and
328luminosity unchanged.
329##
330
331#Const kColor 27
332#Line # hue and saturation of source with luminosity of destination ##
333#Details Color
334Replaces hue and saturation of destination with hue and saturation of source,
335leaving luminosity unchanged.
336##
337
338#Const kLuminosity 28
339#Line # luminosity of source with hue and saturation of destination ##
340#Details Luminosity
341Replaces luminosity of destination with luminosity of source, leaving hue and
342saturation unchanged.
343##
344
345#Const kLastMode 28
346#Line # last valid value ##
347Used by tests to iterate through all valid values.
348##
349
350#NoExample
351##
352
353#SeeAlso SkCanvas::drawColor SkCanvas::drawVertices SkPaint SkShader::MakeCompose SkXfermodeImageFilter
354
355#EnumClass SkBlendMode ##
356
357#Subtopic Clear
358#Line # makes destination pixels transparent ##
359SkBlendMode::kClear sets destination to:
360#Formula
361[0, 0]
362##
363. Use SkBlendMode::kClear to initialize a buffer to fully transparent pixels when
364creating a mask with irregular edges.
365
366#Example
367#Description
368SK_ColorYELLOW is ignored because SkBlendMode::kClear ignores the source pixel
369value and the destination pixel value, always setting the destination to zero.
370##
371 canvas->saveLayer(nullptr, nullptr);
372 canvas->drawColor(SK_ColorYELLOW, SkBlendMode::kClear);
373 SkPaint paint;
374 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
375 SkColor colors[] = { color, SkColorSetA(color, 0) };
376 paint.setShader(SkGradientShader::MakeRadial({ 64, 64}, 100,
377 colors, nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode));
378 canvas->drawCircle(64, 64, 100, paint);
379 canvas->translate(64, 64);
380 }
381 canvas->restore();
382##
383#SeeAlso SkCanvas::clear
384##
385
386#Subtopic Src
387#Line # replaces destination, ignoring Alpha ##
388Given:
389#Formula
390Sa as source Alpha, Sc as source Color component
391##
392; SkBlendMode::kSrc sets destination to:
393#Formula
394[Sa, Sc]
395##
396. Use SkBlendMode::kSrc to copy one buffer to another. All pixels are copied,
397regardless of source and destination Alpha values. As a parameter to
398SkCanvas::drawAtlas, selects sprites and ignores colors.
399#Example
400#Image 3
401#Description
402SkBlendMode::kSrc does not blend transparent pixels with existing background;
403it punches a transparent hole in the existing image.
404##
405 canvas->drawImage(image, 0, 0);
406 canvas->clipRect({50, 50, 200, 200});
407 SkPaint srcBlend;
408 srcBlend.setBlendMode(SkBlendMode::kSrc);
409 canvas->saveLayer(nullptr, &srcBlend);
410 canvas->drawColor(0);
411 SkPaint transRed;
412 transRed.setColor(SkColorSetA(SK_ColorRED, 127));
413 canvas->drawCircle(125, 125, 75, transRed);
414 canvas->restore();
415##
416#SeeAlso SkSurface::draw SkSurface::readPixels
417##
418
419#Subtopic Dst
420#Line # preserves destination, ignoring source ##
421Given:
422#Formula
423Da as destination Alpha, Dc as destination Color component
424##
425; SkBlendMode::kDst preserves destination set to:
426#Formula
427[Da, Dc]
428##
429. Setting Paint Blend_Mode to SkBlendMode::kDst causes drawing with
430Paint to have no effect. As a parameter to SkCanvas::drawAtlas,
431selects colors and ignores sprites.
432#Example
433#Image 3
434 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 125, 128 } };
435 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
436 SkColor colors[] = { 0x7f55aa00, 0x7f3333bf };
437 canvas->drawAtlas(image.get(), xforms, tex, colors, 2, SkBlendMode::kSrc, nullptr, nullptr);
438 canvas->translate(128, 0);
439 canvas->drawAtlas(image.get(), xforms, tex, colors, 2, SkBlendMode::kDst, nullptr, nullptr);
440##
441##
442
443#Subtopic Src_Over
444#Line # blends source with destination ##
445Given:
446#Formula
447Sa as source Alpha, Sc as source Color component,
448Da as destination Alpha, Dc as destination Color component
449##
450; SkBlendMode::kSrcOver replaces destination with:
451#Formula
452[Sa + Da * (1 - Sa), Sc + Dc * (1 - Sa)]
453##
454, drawing source over destination. SkBlendMode::kSrcOver is the default for Paint.
455
456SkBlendMode::kSrcOver cannot make destination more transparent; the result will
457be at least as opaque as the less transparent of source and original destination.
458#Example
459 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE };
460 SkPoint horz[] = { { 0, 0 }, { 256, 0 } };
461 SkPaint paint;
462 paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors),
463 SkShader::kClamp_TileMode));
464 canvas->drawPaint(paint);
465 paint.setBlendMode(SkBlendMode::kDstIn);
466 SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT };
467 SkPoint vert[] = { { 0, 0 }, { 0, 256 } };
468 paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas),
469 SkShader::kClamp_TileMode));
470 canvas->drawPaint(paint);
471 canvas->clipRect( { 30, 30, 226, 226 } );
472 canvas->drawColor(SkColorSetA(SK_ColorGREEN, 128), SkBlendMode::kSrcOver);
473##
474##
475
476#Subtopic Dst_Over
477#Line # blends destination with source ##
478Given:
479#Formula
480Sa as source Alpha, Sc as source Color component,
481Da as destination Alpha, Dc as destination Color component
482##
483; SkBlendMode::kDstOver replaces destination with:
484#Formula
485[Da + Sa * (1 - Da), Dc + Sc * (1 - Da)]
486##
487, drawing destination over source. Has no effect destination if is opaque.
488#Example
489 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE };
490 SkPoint horz[] = { { 0, 0 }, { 256, 0 } };
491 SkPaint paint;
492 paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors),
493 SkShader::kClamp_TileMode));
494 canvas->drawPaint(paint);
495 paint.setBlendMode(SkBlendMode::kDstIn);
496 SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT };
497 SkPoint vert[] = { { 0, 0 }, { 0, 256 } };
498 paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas),
499 SkShader::kClamp_TileMode));
500 canvas->drawPaint(paint);
501 canvas->clipRect( { 30, 30, 226, 226 } );
502 canvas->drawColor(SkColorSetA(SK_ColorGREEN, 128), SkBlendMode::kDstOver);
503##
504##
505
506#Subtopic Src_In
507#Line # source trimmed inside destination ##
508Given:
509#Formula
510Sa as source Alpha, Sc as source Color component, Da as destination Alpha
511##
512; SkBlendMode::kSrcIn replaces destination with:
513#Formula
514[Sa * Da, Sc * Da]
515##
516, drawing source with destination opacity.
517#Example
518 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE };
519 SkPoint horz[] = { { 0, 0 }, { 256, 0 } };
520 SkPaint paint;
521 paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors),
522 SkShader::kClamp_TileMode));
523 canvas->drawPaint(paint);
524 paint.setBlendMode(SkBlendMode::kDstIn);
525 SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT };
526 SkPoint vert[] = { { 0, 0 }, { 0, 256 } };
527 paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas),
528 SkShader::kClamp_TileMode));
529 canvas->drawPaint(paint);
530 canvas->clipRect( { 30, 30, 226, 226 } );
531 canvas->drawColor(SkColorSetA(SK_ColorGREEN, 128), SkBlendMode::kSrcIn);
532##
533##
534
535#Subtopic Dst_In
536#Line # destination trimmed by source ##
537Given:
538#Formula
539Sa as source Alpha, Da as destination Alpha, Dc as destination Color component
540##
541; SkBlendMode::kDstIn replaces destination with:
542#Formula
543[Da * Sa, Dc * Sa]
544##
545, scaling destination Alpha by source Alpha. Resulting
546destination is visible where source is visible.
547#Example
548 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE };
549 SkPoint horz[] = { { 0, 0 }, { 256, 0 } };
550 SkPaint paint;
551 paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors),
552 SkShader::kClamp_TileMode));
553 canvas->drawPaint(paint);
554 paint.setBlendMode(SkBlendMode::kDstIn);
555 SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT };
556 SkPoint vert[] = { { 0, 0 }, { 0, 256 } };
557 paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas),
558 SkShader::kClamp_TileMode));
559 canvas->drawPaint(paint);
560 canvas->clipRect( { 30, 30, 226, 226 } );
561 canvas->drawColor(SkColorSetA(SK_ColorGREEN, 128), SkBlendMode::kDstIn);
562##
563##
564
565#Subtopic Src_Out
566#Line # source trimmed outside destination ##
567Given:
568#Formula
569Sa as source Alpha, Sc as source Color component, Da as destination Alpha
570##
571; SkBlendMode::kSrcOut replaces destination with:
572#Formula
573[Sa * (1 - Da), Sc * (1 - Da)]
574##
575, drawing source fully where destination Alpha is zero. Is destination
576is opaque, has no effect.
577#Example
578 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE };
579 SkPoint horz[] = { { 0, 0 }, { 256, 0 } };
580 SkPaint paint;
581 paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors),
582 SkShader::kClamp_TileMode));
583 canvas->drawPaint(paint);
584 paint.setBlendMode(SkBlendMode::kDstIn);
585 SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT };
586 SkPoint vert[] = { { 0, 0 }, { 0, 256 } };
587 paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas),
588 SkShader::kClamp_TileMode));
589 canvas->drawPaint(paint);
590 canvas->clipRect( { 30, 30, 226, 226 } );
591 canvas->drawColor(SkColorSetA(SK_ColorGREEN, 128), SkBlendMode::kSrcOut);
592##
593##
594
595#Subtopic Dst_Out
596#Line # destination trimmed outside source ##
597Given:
598#Formula
599Sa as source Alpha, Da as destination Alpha, Dc as destination Color component
600##
601; SkBlendMode::kDstOut replaces destination with:
602#Formula
603[Da * (1 - Sa), Dc * (1 - Sa)]
604##
605, scaling destination Alpha by source transparency. Resulting
606destination is visible where source is transparent. If source is transparent,
607has no effect.
608#Example
609 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE };
610 SkPoint horz[] = { { 0, 0 }, { 256, 0 } };
611 SkPaint paint;
612 paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors),
613 SkShader::kClamp_TileMode));
614 canvas->drawPaint(paint);
615 paint.setBlendMode(SkBlendMode::kDstIn);
616 SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT };
617 SkPoint vert[] = { { 0, 0 }, { 0, 256 } };
618 paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas),
619 SkShader::kClamp_TileMode));
620 canvas->drawPaint(paint);
621 canvas->clipRect( { 30, 30, 226, 226 } );
622 canvas->drawColor(SkColorSetA(SK_ColorGREEN, 128), SkBlendMode::kDstOut);
623##
624##
625
626#Subtopic Src_Atop
627#Line # source inside destination over destination ##
628Given:
629#Formula
630Sa as source Alpha, Sc as source Color component,
631Da as destination Alpha, Dc as destination Color component
632##
633; SkBlendMode::kSrcATop replaces destination with:
634#Formula
635[Da, Sc * Da + Dc * (1 - Sa)]
636##
637, replacing opaque destination with opaque source. If source or destination
638is transparent, has no effect.
639#Example
640 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE };
641 SkPoint horz[] = { { 0, 0 }, { 256, 0 } };
642 SkPaint paint;
643 paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors),
644 SkShader::kClamp_TileMode));
645 canvas->drawPaint(paint);
646 paint.setBlendMode(SkBlendMode::kDstIn);
647 SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT };
648 SkPoint vert[] = { { 0, 0 }, { 0, 256 } };
649 paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas),
650 SkShader::kClamp_TileMode));
651 canvas->drawPaint(paint);
652 canvas->clipRect( { 30, 30, 226, 226 } );
653 canvas->drawColor(SkColorSetA(SK_ColorGREEN, 128), SkBlendMode::kSrcATop);
654##
655##
656
657#Subtopic Dst_Atop
658#Line # destination inside source over source ##
659Given:
660#Formula
661Sa as source Alpha, Sc as source Color component,
662Da as destination Alpha, Dc as destination Color component
663##
664; SkBlendMode::kDstATop replaces destination with:
665#Formula
666[Sa, Dc * Sa + Sc * (1 - Da)]
667##
668, making destination transparent where source is transparent.
669#Example
670 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE };
671 SkPoint horz[] = { { 0, 0 }, { 256, 0 } };
672 SkPaint paint;
673 paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors),
674 SkShader::kClamp_TileMode));
675 canvas->drawPaint(paint);
676 paint.setBlendMode(SkBlendMode::kDstATop);
677 SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT };
678 SkPoint vert[] = { { 0, 0 }, { 0, 256 } };
679 paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas),
680 SkShader::kClamp_TileMode));
681 canvas->drawPaint(paint);
682 canvas->clipRect( { 30, 30, 226, 226 } );
683 canvas->drawColor(SkColorSetA(SK_ColorGREEN, 128), SkBlendMode::kSrcATop);
684##
685##
686
687#Subtopic Xor
688#Line # each of source and destination trimmed outside the other ##
689Given:
690#Formula
691Sa as source Alpha, Sc as source Color component,
692Da as destination Alpha, Dc as destination Color component
693##
694; SkBlendMode::kXor replaces destination with:
695#Formula
696[Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + Dc * (1 - Sa)]
697##
698, exchanging the transparency of the source and destination.
699#Example
700 SkPaint paint;
701 paint.setBlendMode(SkBlendMode::kXor);
702 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
703 SkColor colors[] = { color, SkColorSetA(color, 192), SkColorSetA(color, 128),
704 SkColorSetA(color, 0) };
705 paint.setShader(SkGradientShader::MakeRadial({ 64, 64}, 100,
706 colors, nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode));
707 canvas->drawCircle(64, 64, 100, paint);
708 canvas->translate(64, 64);
709 }
710##
711##
712
713#Subtopic Plus
714#Line # sum of colors ##
715Given:
716#Formula
717Sa as source Alpha, Sc as source Color component,
718Da as destination Alpha, Dc as destination Color component
719##
720; SkBlendMode::kPlus replaces destination with:
721#Formula
722[Sa + Da, Sc + Dc]
723##
724, summing the Alpha and Color components.
725#Example
726 canvas->drawColor(SK_ColorBLACK);
727 SkPaint paint;
728 paint.setBlendMode(SkBlendMode::kPlus);
729 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
730 SkColor colors[] = { color, SkColorSetA(color, 192), SkColorSetA(color, 128),
731 SkColorSetA(color, 0) };
732 paint.setShader(SkGradientShader::MakeRadial({ 64, 64}, 100,
733 colors, nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode));
734 canvas->drawCircle(64, 64, 100, paint);
735 canvas->translate(64, 64);
736 }
737##
738##
739
740#Subtopic Modulate
741#Line # product of Premultiplied colors; darkens destination ##
742Given:
743#Formula
744Sa as source Alpha, Sc as source Color component,
745Da as destination Alpha, Dc as destination Color component
746##
747; SkBlendMode::kModulate replaces destination with:
748#Formula
749[Sa * Da, Sc * Dc]
750##
751, scaling Alpha and Color components by the lesser of the values.
752SkBlendMode::kModulate differs from SkBlendMode::kMultiply in two ways.
753SkBlendMode::kModulate like SkBlendMode::kSrcATop alters the destination inside
Cary Clark80247e52018-07-11 16:18:41 -0400754the destination area, as if the destination Alpha defined the boundaries of a
Cary Clark224c7002018-06-27 11:00:21 -0400755soft clip. SkBlendMode::kMultiply like SkBlendMode::kSrcOver can alter the
756destination where the destination is transparent.
757SkBlendMode::kModulate computes the product of the source and destination using
758Premultiplied component values. SkBlendMode::kMultiply the product of the source
759and destination using Unpremultiplied component values.
760#Example
761#Description
762 If source and destination are opaque, SkBlendMode::kModulate and
763 SkBlendMode::kMultiply produce the same results.
764##
765 auto drawSquare = [=](int dx, int dy, SkBlendMode mode, const char* label) -> void {
766 const SkColor colors[] = { SK_ColorBLACK, SK_ColorWHITE };
767 const SkPoint horz[] = { { 0, 0 }, { 128, 0 } };
768 SkPaint paint;
769 paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors),
770 SkShader::kClamp_TileMode));
771 paint.setBlendMode(mode);
772 canvas->translate(dx, dy);
773 canvas->drawRect({0, 0, 128, 128}, paint);
774 paint.setBlendMode(SkBlendMode::kXor);
775 canvas->drawString(label, 40, 100, paint);
776 };
777 drawSquare(0, 0, SkBlendMode::kSrc, "destination");
778 drawSquare(128, 0, SkBlendMode::kSrc, "");
779 drawSquare(0, 128, SkBlendMode::kSrc, "");
780 canvas->translate(-128, -128);
781 canvas->rotate(90, 0, 128);
782 drawSquare(0, 0, SkBlendMode::kSrc, "source");
783 drawSquare(0, -128, SkBlendMode::kModulate, "modulate");
784 drawSquare(-128, 0, SkBlendMode::kMultiply, "multiply");
785##
786##
787
788#Subtopic Screen
789#Line # multiply inverse of pixels, inverting result; brightens destination ##
790Given:
791#Formula
792Sa as source Alpha, Sc as source Color component,
793Da as destination Alpha, Dc as destination Color component
794##
795; SkBlendMode::kScreen replaces destination with:
796#Formula
797[Sa + Da - Sa * Da, Sc + Dc - Sc * Dc]
798##
799.
800#Example
801 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE };
802 SkPoint horz[] = { { 0, 0 }, { 256, 0 } };
803 SkPaint paint;
804 paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors),
805 SkShader::kClamp_TileMode));
806 canvas->drawPaint(paint);
807 paint.setBlendMode(SkBlendMode::kDstATop);
808 SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT };
809 SkPoint vert[] = { { 0, 0 }, { 0, 256 } };
810 paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas),
811 SkShader::kClamp_TileMode));
812 canvas->drawPaint(paint);
813 canvas->clipRect( { 30, 30, 226, 226 } );
814 canvas->drawColor(SkColorSetA(SK_ColorGREEN, 128), SkBlendMode::kScreen);
815##
816##
817
818#Subtopic Overlay
819#Line # multiply or screen, depending on destination ##
820Given:
821#Formula
822Sa as source Alpha, Sc as source Color component,
823Da as destination Alpha, Dc as destination Color component
824##
825; SkBlendMode::kOverlay replaces destination with:
826#Formula
827[Sa + Da - Sa * Da, Sc * (1 - Da) + Dc * (1 - Sa) +
828 (2 * Dc <= Da ? 2 * Sc * Dc : Sa * Da - 2 * (Da - Dc) * (Sa - Sc))]
829##
830.
831#Example
832 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE };
833 SkPoint horz[] = { { 0, 0 }, { 256, 0 } };
834 SkPaint paint;
835 paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors),
836 SkShader::kClamp_TileMode));
837 canvas->drawPaint(paint);
838 paint.setBlendMode(SkBlendMode::kDstATop);
839 SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT };
840 SkPoint vert[] = { { 0, 0 }, { 0, 256 } };
841 paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas),
842 SkShader::kClamp_TileMode));
843 canvas->drawPaint(paint);
844 canvas->clipRect( { 30, 30, 226, 226 } );
845 canvas->drawColor(SkColorSetA(SK_ColorGREEN, 128), SkBlendMode::kOverlay);
846##
847##
848
849#Subtopic Darken
850#Line # darker of source and destination ##
851Given:
852#Formula
853Sa as source Alpha, Sc as source Color component,
854Da as destination Alpha, Dc as destination Color component
855##
856; SkBlendMode::kDarken replaces destination with:
857#Formula
858[Sa + Da - Sa * Da, Sc + Dc - max(Sc * Da, Dc * Sa)]
859##
860. SkBlendMode::kDarken does not make an image darker; it replaces the destination
861component with source if source is darker.
862#Example
Cary Clark53498e92018-06-28 19:13:56 -0400863#Image 3
Cary Clark224c7002018-06-27 11:00:21 -0400864 canvas->drawImage(image, 0, 0);
865 SkColor colors[] = { SK_ColorWHITE, SK_ColorBLACK };
866 SkPoint horz[] = { { 0, 0 }, { 256, 0 } };
867 SkPaint paint;
868 paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors),
869 SkShader::kClamp_TileMode));
870 paint.setBlendMode(SkBlendMode::kDarken);
871 canvas->drawPaint(paint);
872##
873##
874
875#Subtopic Lighten
876#Line # lighter of source and destination ##
877Given:
878#Formula
879Sa as source Alpha, Sc as source Color component,
880Da as destination Alpha, Dc as destination Color component
881##
882; SkBlendMode::kLighten replaces destination with:
883#Formula
884[Sa + Da - Sa * Da, Sc + Dc - min(Sc * Da, Dc * Sa)]
885##
886. SkBlendMode::kDarken does not make an image lighter; it replaces the destination
887component with source if source is lighter.
888#Example
Cary Clark53498e92018-06-28 19:13:56 -0400889#Image 3
Cary Clark224c7002018-06-27 11:00:21 -0400890 canvas->drawImage(image, 0, 0);
891 SkColor colors[] = { SK_ColorBLACK, SK_ColorWHITE };
892 SkPoint horz[] = { { 0, 0 }, { 256, 0 } };
893 SkPaint paint;
894 paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors),
895 SkShader::kClamp_TileMode));
896 paint.setBlendMode(SkBlendMode::kLighten);
897 canvas->drawPaint(paint);
898##
899##
900
901#Subtopic Color_Dodge
902#Line # brighten destination to reflect source ##
903Given:
904#Formula
905Sa as source Alpha, Sc as source Color component,
906Da as destination Alpha, Dc as destination Color component
907##
908; SkBlendMode::kColorDodge replaces destination with:
909#Formula
910[Sa + Da - Sa * Da, Dc == 0 ? Sc * (1 - Da) : Sc == Sa ? Sc + Da * (1 - Sa) :
911 Sa * min(Da, Dc * Sa / (Sa - Sc)) + Sc * (1 - Da) + Da * (1 - Sa)]
912##
913, making destination brighter to reflect source.
914#Example
915#Image 3
916 canvas->drawImage(image, 0, 0);
917 canvas->clipRect({128, 0, 256, 256});
918 canvas->drawColor(SkColorSetARGB(0x80, 0x90, 0x90, 0x90), SkBlendMode::kColorDodge);
919##
920##
921
922#Subtopic Color_Burn
923#Line # darken destination to reflect source ##
924Given:
925#Formula
926Sa as source Alpha, Sc as source Color component,
927Da as destination Alpha, Dc as destination Color component
928##
929; SkBlendMode::kColorBurn replaces destination with:
930#Formula
931[Sa + Da - Sa * Da, Dc == Da ? Dc + Sc * (1 - Da) : Sc == 0 ? Da * (1 - Sa) :
932 Sa * (Da - min(Da, (Da - Dc) * Sa / Sc)) + Sc * (1 - Da) + Da * (1 - Sa)]
933##
934, making destination darker to reflect source.
935#Example
936#Image 3
937 canvas->drawImage(image, 0, 0);
938 canvas->clipRect({128, 0, 256, 256});
939 canvas->drawColor(SkColorSetARGB(0x80, 0x90, 0x90, 0x90), SkBlendMode::kColorBurn);
940##
941##
942
943#Subtopic Hard_Light
944#Line # multiply or screen, depending on source ##
945Given:
946#Formula
947Sa as source Alpha, Sc as source Color component,
948Da as destination Alpha, Dc as destination Color component
949##
950; SkBlendMode::kHardLight replaces destination with:
951#Formula
952[Sa + Da - Sa * Da, Sc * (1 - Da) + Dc * (1 - Sa) +
953 2 * Sc <= Sa ? 2 * Sc * Dc : Sa * Da - 2 * (Da - Dc) * (Sa - Sc)]
954##
955, making destination lighter or darker, depending on source.
956#Example
957#Image 3
958 canvas->drawImage(image, 0, 0);
959 const SkColor colors[] = { 0xFFFFFFFF, 0x00000000 };
960 SkPaint paint;
961 paint.setBlendMode(SkBlendMode::kHardLight);
962 paint.setShader(SkGradientShader::MakeRadial({ 128, 128}, 100, colors,
963 nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode));
964 canvas->clipRect({0, 128, 256, 256});
965 canvas->drawPaint(paint);
966##
967##
968
969#Subtopic Soft_Light
970#Line # lighten or darken, depending on source ##
971Given:
972#Formula
973Sa as source Alpha, Sc as source Color component,
974Da as destination Alpha, Dc as destination Color component
975where m = Da > 0 ? Dc / Da : 0
976##
977; SkBlendMode::kSoftLight replaces destination with:
978#Formula
979[Sa + Da - Sa * Da, Sc / Da + Dc / Sa +
980 (2 * Sc <= Sa ? Dc * (Sa + (2 * Sc - Sa) * (1 - m)) : Dc * Sa + Da * (2 * Sc - Sa) *
981 (4 * Dc <= Da ? (16 * m * m + 4 * m) * (m - 1) + 7 * m : sqrt(m) - m))]\
982##
983, making destination lighter or darker, depending on source.
984#Example
985#Image 3
986 const SkColor colors[] = { 0xFFFFFFFF, 0x3FFFFFFF };
987 SkPaint paint;
988 paint.setBlendMode(SkBlendMode::kSoftLight);
989 paint.setShader(SkGradientShader::MakeRadial({ 128, 128}, 100, colors,
990 nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode));
991 canvas->drawImage(image, 0, 0);
992 canvas->drawCircle(128, 128, 100, paint);
993##
994##
995
996#Subtopic Difference
997#Line # subtract darker from lighter with higher contrast ##
998Given:
999#Formula
1000Sa as source Alpha, Sc as source Color component,
1001Da as destination Alpha, Dc as destination Color component
1002##
1003; SkBlendMode::kDifference replaces destination with:
1004#Formula
1005[Sa + Da - Sa * Da, Sc + Dc - 2 * min(Sc * Da, Dc * Sa)]
1006##
1007, replacing destination with lighter less darker.
1008#Example
1009#Image 5
1010 canvas->drawImage(image, 0, 0);
1011 canvas->drawImage(image, 128, 0);
1012 canvas->drawImage(image, 0, 128);
1013 canvas->drawImage(image, 128, 128);
1014 SkPaint paint;
1015 paint.setBlendMode(SkBlendMode::kDstATop);
1016 SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT };
1017 SkPoint vert[] = { { 0, 0 }, { 0, 256 } };
1018 paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas),
1019 SkShader::kClamp_TileMode));
1020 canvas->drawPaint(paint);
1021 canvas->clipRect( { 30, 30, 226, 226 } );
1022 canvas->drawColor(0x80bb9977, SkBlendMode::kDifference);
1023##
1024##
1025
1026#Subtopic Exclusion
1027#Line # subtract darker from lighter with lower contrast ##
1028Given:
1029#Formula
1030Sa as source Alpha, Sc as source Color,
1031Da as destination Alpha, Dc as destination Color component
1032##
1033; SkBlendMode::kExclusion replaces destination with:
1034#Formula
1035[Sa + Da - Sa * Da, Sc + Dc - 2 * Sc * Dc]
1036##
1037, replacing destination with lighter less darker, ignoring Alpha.
1038#Example
1039#Image 5
1040 canvas->drawImage(image, 0, 0);
1041 canvas->drawImage(image, 128, 0);
1042 canvas->drawImage(image, 0, 128);
1043 canvas->drawImage(image, 128, 128);
1044 SkPaint paint;
1045 paint.setBlendMode(SkBlendMode::kDstATop);
1046 SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT };
1047 SkPoint vert[] = { { 0, 0 }, { 0, 256 } };
1048 paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas),
1049 SkShader::kClamp_TileMode));
1050 canvas->drawPaint(paint);
1051 canvas->clipRect( { 30, 30, 226, 226 } );
1052 canvas->drawColor(0x80bb9977, SkBlendMode::kExclusion);
1053##
1054##
1055
1056#Subtopic Multiply
1057#Line # multiply source with destination, darkening image ##
1058Given:
1059#Formula
1060Sa as source Alpha, Sc as source Color component,
1061Da as destination Alpha, Dc as destination Color component
1062##
1063; SkBlendMode::kMultiply replaces destination with:
1064#Formula
1065[Sa + Da - Sa * Da, Sc * (1 - Da) + Dc * (1 - Sa) + Sc * Dc]
1066##
1067, the product of Unpremultiplied source and destination.
1068SkBlendMode::kMultiply makes the image darker.
1069#Example
Cary Clark53498e92018-06-28 19:13:56 -04001070#Image 5
Cary Clark224c7002018-06-27 11:00:21 -04001071 canvas->drawImage(image, 0, 0);
1072 canvas->drawImage(image, 128, 0);
1073 canvas->drawImage(image, 0, 128);
1074 canvas->drawImage(image, 128, 128);
1075 SkPaint paint;
1076 paint.setBlendMode(SkBlendMode::kDstATop);
1077 SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT };
1078 SkPoint vert[] = { { 0, 0 }, { 0, 256 } };
1079 paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas),
1080 SkShader::kClamp_TileMode));
1081 canvas->drawPaint(paint);
1082 canvas->clipRect( { 30, 30, 226, 226 } );
1083 canvas->drawColor(0x80bb9977, SkBlendMode::kMultiply);
1084##
1085##
1086
1087#Subtopic Hue
1088#Line # hue of source with saturation and luminosity of destination ##
1089Given:
1090#Formula
1091Sa as source Alpha, S as source Color,
1092Da as destination Alpha, D as destination Color
1093##
1094; SkBlendMode::kHue replaces destination with:
1095#Formula
1096[Sa + Da - Sa * Da, SetLuminosity(SetSaturation(S, Saturation(D)), Luminosity(D))]
1097##
1098, source hue, leaving destination luminosity and saturation unchanged.
1099#Example
Cary Clark53498e92018-06-28 19:13:56 -04001100#Image 3
Cary Clark224c7002018-06-27 11:00:21 -04001101canvas->drawImage(image, 0, 0);
1102canvas->drawColor(0xFF00FF00, SkBlendMode::kHue);
1103##
1104##
1105
1106#Subtopic Saturation
1107#Line # saturation of source with hue and luminosity of destination ##
1108Given:
1109#Formula
1110Sa as source Alpha, S as source Color,
1111Da as destination Alpha, D as destination Color
1112##
1113; SkBlendMode::kHue replaces destination with:
1114#Formula
1115[Sa + Da - Sa * Da, SetLuminosity(SetSaturation(D, Saturation(S)), Luminosity(D))]
1116##
1117, source hue, leaving destination luminosity and saturation unchanged.
1118#Example
Cary Clark53498e92018-06-28 19:13:56 -04001119#Image 3
Cary Clark224c7002018-06-27 11:00:21 -04001120canvas->drawImage(image, 0, 0);
1121canvas->drawColor(0xFF00FF00, SkBlendMode::kSaturation);
1122##
1123##
1124
1125#Subtopic Color
1126#Line # hue and saturation of source with luminosity of destination ##
1127Given:
1128#Formula
1129Sa as source Alpha, S as source Color,
1130Da as destination Alpha, D as destination Color
1131##
1132; SkBlendMode::kColor replaces destination with:
1133#Formula
1134[Sa + Da - Sa * Da, SetLuminosity(S, Luminosity(D))]
1135##
1136, source hue and saturation, leaving destination luminosity unchanged.
1137#Example
Cary Clark53498e92018-06-28 19:13:56 -04001138#Image 3
Cary Clark224c7002018-06-27 11:00:21 -04001139canvas->drawImage(image, 0, 0);
1140canvas->drawColor(0xFF00FF00, SkBlendMode::kColor);
1141##
1142##
1143
1144#Subtopic Luminosity
1145#Line # luminosity of source with hue and saturation of destination ##
1146Given:
1147#Formula
1148Sa as source Alpha, S as source Color,
1149Da as destination Alpha, D as destination Color
1150##
1151; SkBlendMode::kLuminosity replaces destination with:
1152#Formula
1153[Sa + Da - Sa * Da, SetLuminosity(D, Luminosity(S))]
1154##
1155, source luminosity, leaving destination hue and saturation unchanged.
1156#Example
Cary Clark53498e92018-06-28 19:13:56 -04001157#Image 3
Cary Clark224c7002018-06-27 11:00:21 -04001158canvas->drawImage(image, 0, 0);
1159canvas->drawColor(0xFF00FF00, SkBlendMode::kLuminosity);
1160##
1161##
1162
1163# ------------------------------------------------------------------------------
1164
1165#Method SK_API const char* SkBlendMode_Name(SkBlendMode blendMode)
1166#In Utility
1167#Line # returns mode as C string ##
1168
1169Returns name of blendMode as null-terminated C string.
1170
1171#Param blendMode one of: #list_of_blend_modes#
1172##
1173
1174#Return C string ##
1175
1176#Example
1177SkDebugf("default blend: SkBlendMode::k%s\n", SkBlendMode_Name(SkPaint().getBlendMode()));
1178#StdOut
1179default blend: SkBlendMode::kSrcOver
1180##
1181##
1182
1183#SeeAlso SkBlendMode
1184
1185#Method ##
1186
1187#Topic Blend_Mode ##