From 224c700a1fb0b7f6abd85a9729d29cbbdf5872dd Mon Sep 17 00:00:00 2001 From: Cary Clark Date: Wed, 27 Jun 2018 11:00:21 -0400 Subject: sync docs up with tip of tree Also check in work in progress for blend modes, round rects, and a placeholder for pictures. One minor include change to add a parameter name for SkBlendMode function. TBR=reed@google.com R=caryclark@google.com Docs-Preview: https://skia.org/?cl=134200 Bug: skia:6898 Change-Id: I5d2a9221d61edb32d9c7edbb3193401605b2b513 Reviewed-on: https://skia-review.googlesource.com/134200 Reviewed-by: Cary Clark Reviewed-by: Cary Clark Commit-Queue: Cary Clark Auto-Submit: Cary Clark --- docs/SkBlendMode_Reference.bmh | 1180 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1180 insertions(+) create mode 100644 docs/SkBlendMode_Reference.bmh (limited to 'docs/SkBlendMode_Reference.bmh') diff --git a/docs/SkBlendMode_Reference.bmh b/docs/SkBlendMode_Reference.bmh new file mode 100644 index 0000000000..1dbba49db3 --- /dev/null +++ b/docs/SkBlendMode_Reference.bmh @@ -0,0 +1,1180 @@ +#Topic Blend_Mode +#Alias BlendMode_Reference ## + +#Subtopic Overview +#Populate +## + +#Subtopic Member_Function +#Populate +## + +#Subtopic Constant +#Populate +## + +Describes how destination pixel is replaced with a combination of itself and +source pixel. Blend_Mode may use source, destination, or both. Blend_Mode may +operate on each Color component independently, or may allow all source pixel +components to contribute to one destination pixel component. + +Blend_Mode does not use adjacent pixels to determine the outcome. + +Blend_Mode uses source and read destination Alpha to determine written +destination Alpha; both source and destination Alpha may also affect written +destination Color components. + +Regardless of how Alpha is encoded in source and destination pixel, nearly all +Color_Types treat it as ranging from zero to one. And, nearly all Blend_Mode +algorithms limit the output so that all results are also zero to one. + +Two exceptions are SkBlendMode::kPlus and kRGBA_F16_SkColorType. + +SkBlendMode::kPlus permits computing Alpha and Color component values larger +than one. For Color_Types other than kRGBA_F16_SkColorType, resulting Alpha +and component values are clamped to one. + +kRGBA_F16_SkColorType permits values outside the zero to one range. It is up +to the client to ensure that the result is within the range of zero to one, +and therefore well-defined. + +#Subtopic Porter_Duff + +#A Compositing Digital Images # https://graphics.pixar.com/library/Compositing/paper.pdf ## +describes Porter_Duff modes SkBlendMode::kClear through SkBlendMode::kXor. + +Drawing a bitmap with transparency using Porter_Duff compositing is free to clear +the destination. + +#Illustration 1 + +Draw geometry with transparency using Porter_Duff compositing does not combine +transparent source pixels, leaving the destination outside the geometry untouched. + +#Illustration 2 + +## + +#Subtopic Lighten_Darken + +Modes SkBlendMode::kPlus and SkBlendMode::kScreen use +simple arithmetic to lighten or darken the destination. Modes +SkBlendMode::kOverlay through SkBlendMode::kMultiply use more complicated +algorithms to lighten or darken; sometimes one mode does both, as described by +#A Blend Modes # https://en.wikipedia.org/wiki/Blend_modes ## +. + +#Illustration + +## + +#Subtopic Modulate_Blend +SkBlendMode::kModulate is a mashup of SkBlendMode::kSrcATop and SkBlendMode::kMultiply. +It multiplies all components, including Alpha; unlike SkBlendMode::kMultiply, if either +source or destination is transparent, result is transparent. SkBlendMode::kModulate +uses Premultiplied values to compute the product; SkBlendMode::kMultiply uses Unpremultiplied +values to compute the product. + +#Illustration + +## + +#Subtopic Color_Blends + +Modes SkBlendMode::kHue, SkBlendMode::kSaturation, SkBlendMode::kColor, and +SkBlendMode::kLuminosity convert source and destination pixels using all +components color information, using +###$ +$A non-separable blend modes $ https://www.w3.org/TR/compositing-1/#blendingnonseparable $$ +$$$# +. + +#Illustration + +## + +# ------------------------------------------------------------------------------ + +#PhraseDef list_of_blend_modes +SkBlendMode::kClear, SkBlendMode::kSrc, SkBlendMode::kDst, SkBlendMode::kSrcOver, +SkBlendMode::kDstOver, SkBlendMode::kSrcIn, SkBlendMode::kDstIn, +SkBlendMode::kSrcOut, SkBlendMode::kDstOut, SkBlendMode::kSrcATop, +SkBlendMode::kDstATop, SkBlendMode::kXor, SkBlendMode::kPlus, +SkBlendMode::kModulate, SkBlendMode::kScreen, SkBlendMode::kOverlay, +SkBlendMode::kDarken, SkBlendMode::kLighten, SkBlendMode::kColorDodge, +SkBlendMode::kColorBurn, SkBlendMode::kHardLight, SkBlendMode::kSoftLight, +SkBlendMode::kDifference, SkBlendMode::kExclusion, SkBlendMode::kMultiply, +SkBlendMode::kHue, SkBlendMode::kSaturation, SkBlendMode::kColor, +SkBlendMode::kLuminosity +## + +#EnumClass SkBlendMode +#Line # algorithm combining source and destination pixels ## + +#Code + enum class SkBlendMode { + kClear, + kSrc, + kDst, + kSrcOver, + kDstOver, + kSrcIn, + kDstIn, + kSrcOut, + kDstOut, + kSrcATop, + kDstATop, + kXor, + kPlus, + kModulate, + kScreen, + kLastCoeffMode = kScreen, + kOverlay, + kDarken, + kLighten, + kColorDodge, + kColorBurn, + kHardLight, + kSoftLight, + kDifference, + kExclusion, + kMultiply, + kLastSeparableMode = kMultiply, + kHue, + kSaturation, + kColor, + kLuminosity, + kLastMode = kLuminosity, + }; +## + +#Const kClear 0 +#Line # replaces destination with zero: fully transparent ## +#Details Clear +Replaces destination with Alpha and Color components set to zero; +a fully transparent pixel. +## + +#Const kSrc 1 +#Line # replaces destination ## +#Details Src +Replaces destination with source. Destination alpha and color component values +are ignored. +## + +#Const kDst 2 +#Line # preserves destination ## +#Details Dst +Preserves destination, ignoring source. Drawing with Paint set to kDst has +no effect. +## + +#Const kSrcOver 3 +#Line # source over destination ## +#Details Src_Over +Replaces destination with source blended with destination. If source is opaque, +replaces destination with source. Used as the default Blend_Mode for SkPaint. +## + +#Const kDstOver 4 +#Line # destination over source ## +#Details Dst_Over +Replaces destination with destination blended with source. If destination is opaque, +has no effect. +## + +#Const kSrcIn 5 +#Line # source trimmed inside destination ## +#Details Src_In +Replaces destination with source using destination opacity. +## + +#Const kDstIn 6 +#Line # destination trimmed by source ## +#Details Dst_In +Scales destination opacity by source opacity. +## + +#Const kSrcOut 7 +#Line # source trimmed outside destination ## +#Details Src_Out +Replaces destination with source using the inverse of destination opacity, +drawing source fully where destination opacity is zero. +## + +#Const kDstOut 8 +#Line # destination trimmed outside source ## +#Details Dst_Out +Replaces destination opacity with inverse of source opacity. If source is +transparent, has no effect. +## + +#Const kSrcATop 9 +#Line # source inside destination blended with destination ## +#Details Src_Atop +Blends destination with source using read destination opacity. +## + +#Const kDstATop 10 +#Line # destination inside source blended with source ## +#Details Dst_Atop +Blends destination with source using source opacity. +## + +#Const kXor 11 +#Line # each of source and destination trimmed outside the other ## +#Details Xor +Blends destination by exchanging transparency of the source and destination. +## + +#Const kPlus 12 +#Line # sum of colors ## +#Details Plus +Replaces destination with source and destination added together. +## + +#Const kModulate 13 +#Line # product of Premultiplied colors; darkens destination ## +#Details Modulate +Replaces destination with source and destination multiplied together. +## + +#Const kScreen 14 +#Line # multiply inverse of pixels, inverting result; brightens destination ## +#Details Screen +Replaces destination with inverted source and destination multiplied together. +## + +#Const kLastCoeffMode 14 +#Line # last Porter_Duff blend mode ## +## + +#Const kOverlay 15 +#Line # multiply or screen, depending on destination ## +#Details Overlay +Replaces destination with multiply or screen, depending on destination. +## + +#Const kDarken 16 +#Line # darker of source and destination ## +#Details Darken +Replaces destination with darker of source and destination. +## + +#Const kLighten 17 +#Line # lighter of source and destination ## +#Details Lighten +Replaces destination with lighter of source and destination. +## + +#Const kColorDodge 18 +#Line # brighten destination to reflect source ## +#Details Color_Dodge +Makes destination brighter to reflect source. +## + +#Const kColorBurn 19 +#Line # darken destination to reflect source ## +#Details Color_Burn +Makes destination darker to reflect source. +## + +#Const kHardLight 20 +#Line # multiply or screen, depending on source ## +#Details Hard_Light +Makes destination lighter or darker, depending on source. +## + +#Const kSoftLight 21 +#Line # lighten or darken, depending on source ## +#Details Soft_Light +Makes destination lighter or darker, depending on source. +## + +#Const kDifference 22 +#Line # subtract darker from lighter with higher contrast ## +#Details Difference +Subtracts darker from lighter with higher contrast. +## + +#Const kExclusion 23 +#Line # subtract darker from lighter with lower contrast ## +#Details Exclusion +Subtracts darker from lighter with lower contrast. +## + +#Const kMultiply 24 +#Line # multiply source with destination, darkening image ## +#Details Multiply +Multiplies source with destination, darkening image. +## + +#Const kLastSeparableMode 24 +#Line # last blend mode operating separately on components ## +Last blend mode operating separately on components. +## + +#Const kHue 25 +#Line # hue of source with saturation and luminosity of destination ## +#Details Hue +Replaces hue of destination with hue of source, leaving saturation and luminosity +unchanged. +## + +#Const kSaturation 26 +#Line # saturation of source with hue and luminosity of destination ## +#Details Saturation +Replaces saturation of destination saturation hue of source, leaving hue and +luminosity unchanged. +## + +#Const kColor 27 +#Line # hue and saturation of source with luminosity of destination ## +#Details Color +Replaces hue and saturation of destination with hue and saturation of source, +leaving luminosity unchanged. +## + +#Const kLuminosity 28 +#Line # luminosity of source with hue and saturation of destination ## +#Details Luminosity +Replaces luminosity of destination with luminosity of source, leaving hue and +saturation unchanged. +## + +#Const kLastMode 28 +#Line # last valid value ## +Used by tests to iterate through all valid values. +## + +#NoExample +## + +#SeeAlso SkCanvas::drawColor SkCanvas::drawVertices SkPaint SkShader::MakeCompose SkXfermodeImageFilter + +#EnumClass SkBlendMode ## + +#Subtopic Clear +#Line # makes destination pixels transparent ## +SkBlendMode::kClear sets destination to: +#Formula +[0, 0] +## +. Use SkBlendMode::kClear to initialize a buffer to fully transparent pixels when +creating a mask with irregular edges. + +#Example +#Description +SK_ColorYELLOW is ignored because SkBlendMode::kClear ignores the source pixel +value and the destination pixel value, always setting the destination to zero. +## + canvas->saveLayer(nullptr, nullptr); + canvas->drawColor(SK_ColorYELLOW, SkBlendMode::kClear); + SkPaint paint; + for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) { + SkColor colors[] = { color, SkColorSetA(color, 0) }; + paint.setShader(SkGradientShader::MakeRadial({ 64, 64}, 100, + colors, nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode)); + canvas->drawCircle(64, 64, 100, paint); + canvas->translate(64, 64); + } + canvas->restore(); +## +#SeeAlso SkCanvas::clear +## + +#Subtopic Src +#Line # replaces destination, ignoring Alpha ## +Given: +#Formula +Sa as source Alpha, Sc as source Color component +## +; SkBlendMode::kSrc sets destination to: +#Formula +[Sa, Sc] +## +. Use SkBlendMode::kSrc to copy one buffer to another. All pixels are copied, +regardless of source and destination Alpha values. As a parameter to +SkCanvas::drawAtlas, selects sprites and ignores colors. +#Example +#Image 3 +#Description +SkBlendMode::kSrc does not blend transparent pixels with existing background; +it punches a transparent hole in the existing image. +## + canvas->drawImage(image, 0, 0); + canvas->clipRect({50, 50, 200, 200}); + SkPaint srcBlend; + srcBlend.setBlendMode(SkBlendMode::kSrc); + canvas->saveLayer(nullptr, &srcBlend); + canvas->drawColor(0); + SkPaint transRed; + transRed.setColor(SkColorSetA(SK_ColorRED, 127)); + canvas->drawCircle(125, 125, 75, transRed); + canvas->restore(); +## +#SeeAlso SkSurface::draw SkSurface::readPixels +## + +#Subtopic Dst +#Line # preserves destination, ignoring source ## +Given: +#Formula +Da as destination Alpha, Dc as destination Color component +## +; SkBlendMode::kDst preserves destination set to: +#Formula +[Da, Dc] +## +. Setting Paint Blend_Mode to SkBlendMode::kDst causes drawing with +Paint to have no effect. As a parameter to SkCanvas::drawAtlas, +selects colors and ignores sprites. +#Example +#Image 3 + SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 125, 128 } }; + SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } }; + SkColor colors[] = { 0x7f55aa00, 0x7f3333bf }; + canvas->drawAtlas(image.get(), xforms, tex, colors, 2, SkBlendMode::kSrc, nullptr, nullptr); + canvas->translate(128, 0); + canvas->drawAtlas(image.get(), xforms, tex, colors, 2, SkBlendMode::kDst, nullptr, nullptr); +## +## + +#Subtopic Src_Over +#Line # blends source with destination ## +Given: +#Formula +Sa as source Alpha, Sc as source Color component, +Da as destination Alpha, Dc as destination Color component +## +; SkBlendMode::kSrcOver replaces destination with: +#Formula +[Sa + Da * (1 - Sa), Sc + Dc * (1 - Sa)] +## +, drawing source over destination. SkBlendMode::kSrcOver is the default for Paint. + +SkBlendMode::kSrcOver cannot make destination more transparent; the result will +be at least as opaque as the less transparent of source and original destination. +#Example + SkColor colors[] = { SK_ColorRED, SK_ColorBLUE }; + SkPoint horz[] = { { 0, 0 }, { 256, 0 } }; + SkPaint paint; + paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors), + SkShader::kClamp_TileMode)); + canvas->drawPaint(paint); + paint.setBlendMode(SkBlendMode::kDstIn); + SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT }; + SkPoint vert[] = { { 0, 0 }, { 0, 256 } }; + paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas), + SkShader::kClamp_TileMode)); + canvas->drawPaint(paint); + canvas->clipRect( { 30, 30, 226, 226 } ); + canvas->drawColor(SkColorSetA(SK_ColorGREEN, 128), SkBlendMode::kSrcOver); +## +## + +#Subtopic Dst_Over +#Line # blends destination with source ## +Given: +#Formula +Sa as source Alpha, Sc as source Color component, +Da as destination Alpha, Dc as destination Color component +## +; SkBlendMode::kDstOver replaces destination with: +#Formula +[Da + Sa * (1 - Da), Dc + Sc * (1 - Da)] +## +, drawing destination over source. Has no effect destination if is opaque. +#Example + SkColor colors[] = { SK_ColorRED, SK_ColorBLUE }; + SkPoint horz[] = { { 0, 0 }, { 256, 0 } }; + SkPaint paint; + paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors), + SkShader::kClamp_TileMode)); + canvas->drawPaint(paint); + paint.setBlendMode(SkBlendMode::kDstIn); + SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT }; + SkPoint vert[] = { { 0, 0 }, { 0, 256 } }; + paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas), + SkShader::kClamp_TileMode)); + canvas->drawPaint(paint); + canvas->clipRect( { 30, 30, 226, 226 } ); + canvas->drawColor(SkColorSetA(SK_ColorGREEN, 128), SkBlendMode::kDstOver); +## +## + +#Subtopic Src_In +#Line # source trimmed inside destination ## +Given: +#Formula +Sa as source Alpha, Sc as source Color component, Da as destination Alpha +## +; SkBlendMode::kSrcIn replaces destination with: +#Formula +[Sa * Da, Sc * Da] +## +, drawing source with destination opacity. +#Example + SkColor colors[] = { SK_ColorRED, SK_ColorBLUE }; + SkPoint horz[] = { { 0, 0 }, { 256, 0 } }; + SkPaint paint; + paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors), + SkShader::kClamp_TileMode)); + canvas->drawPaint(paint); + paint.setBlendMode(SkBlendMode::kDstIn); + SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT }; + SkPoint vert[] = { { 0, 0 }, { 0, 256 } }; + paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas), + SkShader::kClamp_TileMode)); + canvas->drawPaint(paint); + canvas->clipRect( { 30, 30, 226, 226 } ); + canvas->drawColor(SkColorSetA(SK_ColorGREEN, 128), SkBlendMode::kSrcIn); +## +## + +#Subtopic Dst_In +#Line # destination trimmed by source ## +Given: +#Formula +Sa as source Alpha, Da as destination Alpha, Dc as destination Color component +## +; SkBlendMode::kDstIn replaces destination with: +#Formula +[Da * Sa, Dc * Sa] +## +, scaling destination Alpha by source Alpha. Resulting +destination is visible where source is visible. +#Example + SkColor colors[] = { SK_ColorRED, SK_ColorBLUE }; + SkPoint horz[] = { { 0, 0 }, { 256, 0 } }; + SkPaint paint; + paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors), + SkShader::kClamp_TileMode)); + canvas->drawPaint(paint); + paint.setBlendMode(SkBlendMode::kDstIn); + SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT }; + SkPoint vert[] = { { 0, 0 }, { 0, 256 } }; + paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas), + SkShader::kClamp_TileMode)); + canvas->drawPaint(paint); + canvas->clipRect( { 30, 30, 226, 226 } ); + canvas->drawColor(SkColorSetA(SK_ColorGREEN, 128), SkBlendMode::kDstIn); +## +## + +#Subtopic Src_Out +#Line # source trimmed outside destination ## +Given: +#Formula +Sa as source Alpha, Sc as source Color component, Da as destination Alpha +## +; SkBlendMode::kSrcOut replaces destination with: +#Formula +[Sa * (1 - Da), Sc * (1 - Da)] +## +, drawing source fully where destination Alpha is zero. Is destination +is opaque, has no effect. +#Example + SkColor colors[] = { SK_ColorRED, SK_ColorBLUE }; + SkPoint horz[] = { { 0, 0 }, { 256, 0 } }; + SkPaint paint; + paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors), + SkShader::kClamp_TileMode)); + canvas->drawPaint(paint); + paint.setBlendMode(SkBlendMode::kDstIn); + SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT }; + SkPoint vert[] = { { 0, 0 }, { 0, 256 } }; + paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas), + SkShader::kClamp_TileMode)); + canvas->drawPaint(paint); + canvas->clipRect( { 30, 30, 226, 226 } ); + canvas->drawColor(SkColorSetA(SK_ColorGREEN, 128), SkBlendMode::kSrcOut); +## +## + +#Subtopic Dst_Out +#Line # destination trimmed outside source ## +Given: +#Formula +Sa as source Alpha, Da as destination Alpha, Dc as destination Color component +## +; SkBlendMode::kDstOut replaces destination with: +#Formula +[Da * (1 - Sa), Dc * (1 - Sa)] +## +, scaling destination Alpha by source transparency. Resulting +destination is visible where source is transparent. If source is transparent, +has no effect. +#Example + SkColor colors[] = { SK_ColorRED, SK_ColorBLUE }; + SkPoint horz[] = { { 0, 0 }, { 256, 0 } }; + SkPaint paint; + paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors), + SkShader::kClamp_TileMode)); + canvas->drawPaint(paint); + paint.setBlendMode(SkBlendMode::kDstIn); + SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT }; + SkPoint vert[] = { { 0, 0 }, { 0, 256 } }; + paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas), + SkShader::kClamp_TileMode)); + canvas->drawPaint(paint); + canvas->clipRect( { 30, 30, 226, 226 } ); + canvas->drawColor(SkColorSetA(SK_ColorGREEN, 128), SkBlendMode::kDstOut); +## +## + +#Subtopic Src_Atop +#Line # source inside destination over destination ## +Given: +#Formula +Sa as source Alpha, Sc as source Color component, +Da as destination Alpha, Dc as destination Color component +## +; SkBlendMode::kSrcATop replaces destination with: +#Formula +[Da, Sc * Da + Dc * (1 - Sa)] +## +, replacing opaque destination with opaque source. If source or destination +is transparent, has no effect. +#Example + SkColor colors[] = { SK_ColorRED, SK_ColorBLUE }; + SkPoint horz[] = { { 0, 0 }, { 256, 0 } }; + SkPaint paint; + paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors), + SkShader::kClamp_TileMode)); + canvas->drawPaint(paint); + paint.setBlendMode(SkBlendMode::kDstIn); + SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT }; + SkPoint vert[] = { { 0, 0 }, { 0, 256 } }; + paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas), + SkShader::kClamp_TileMode)); + canvas->drawPaint(paint); + canvas->clipRect( { 30, 30, 226, 226 } ); + canvas->drawColor(SkColorSetA(SK_ColorGREEN, 128), SkBlendMode::kSrcATop); +## +## + +#Subtopic Dst_Atop +#Line # destination inside source over source ## +Given: +#Formula +Sa as source Alpha, Sc as source Color component, +Da as destination Alpha, Dc as destination Color component +## +; SkBlendMode::kDstATop replaces destination with: +#Formula +[Sa, Dc * Sa + Sc * (1 - Da)] +## +, making destination transparent where source is transparent. +#Example + SkColor colors[] = { SK_ColorRED, SK_ColorBLUE }; + SkPoint horz[] = { { 0, 0 }, { 256, 0 } }; + SkPaint paint; + paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors), + SkShader::kClamp_TileMode)); + canvas->drawPaint(paint); + paint.setBlendMode(SkBlendMode::kDstATop); + SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT }; + SkPoint vert[] = { { 0, 0 }, { 0, 256 } }; + paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas), + SkShader::kClamp_TileMode)); + canvas->drawPaint(paint); + canvas->clipRect( { 30, 30, 226, 226 } ); + canvas->drawColor(SkColorSetA(SK_ColorGREEN, 128), SkBlendMode::kSrcATop); +## +## + +#Subtopic Xor +#Line # each of source and destination trimmed outside the other ## +Given: +#Formula +Sa as source Alpha, Sc as source Color component, +Da as destination Alpha, Dc as destination Color component +## +; SkBlendMode::kXor replaces destination with: +#Formula +[Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + Dc * (1 - Sa)] +## +, exchanging the transparency of the source and destination. +#Example + SkPaint paint; + paint.setBlendMode(SkBlendMode::kXor); + for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) { + SkColor colors[] = { color, SkColorSetA(color, 192), SkColorSetA(color, 128), + SkColorSetA(color, 0) }; + paint.setShader(SkGradientShader::MakeRadial({ 64, 64}, 100, + colors, nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode)); + canvas->drawCircle(64, 64, 100, paint); + canvas->translate(64, 64); + } +## +## + +#Subtopic Plus +#Line # sum of colors ## +Given: +#Formula +Sa as source Alpha, Sc as source Color component, +Da as destination Alpha, Dc as destination Color component +## +; SkBlendMode::kPlus replaces destination with: +#Formula +[Sa + Da, Sc + Dc] +## +, summing the Alpha and Color components. +#Example + canvas->drawColor(SK_ColorBLACK); + SkPaint paint; + paint.setBlendMode(SkBlendMode::kPlus); + for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) { + SkColor colors[] = { color, SkColorSetA(color, 192), SkColorSetA(color, 128), + SkColorSetA(color, 0) }; + paint.setShader(SkGradientShader::MakeRadial({ 64, 64}, 100, + colors, nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode)); + canvas->drawCircle(64, 64, 100, paint); + canvas->translate(64, 64); + } +## +## + +#Subtopic Modulate +#Line # product of Premultiplied colors; darkens destination ## +Given: +#Formula +Sa as source Alpha, Sc as source Color component, +Da as destination Alpha, Dc as destination Color component +## +; SkBlendMode::kModulate replaces destination with: +#Formula +[Sa * Da, Sc * Dc] +## +, scaling Alpha and Color components by the lesser of the values. +SkBlendMode::kModulate differs from SkBlendMode::kMultiply in two ways. +SkBlendMode::kModulate like SkBlendMode::kSrcATop alters the destination inside +the destination area, as if the destination Alpha defined the boudaries of a +soft clip. SkBlendMode::kMultiply like SkBlendMode::kSrcOver can alter the +destination where the destination is transparent. +SkBlendMode::kModulate computes the product of the source and destination using +Premultiplied component values. SkBlendMode::kMultiply the product of the source +and destination using Unpremultiplied component values. +#Example +#Description + If source and destination are opaque, SkBlendMode::kModulate and + SkBlendMode::kMultiply produce the same results. +## + auto drawSquare = [=](int dx, int dy, SkBlendMode mode, const char* label) -> void { + const SkColor colors[] = { SK_ColorBLACK, SK_ColorWHITE }; + const SkPoint horz[] = { { 0, 0 }, { 128, 0 } }; + SkPaint paint; + paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors), + SkShader::kClamp_TileMode)); + paint.setBlendMode(mode); + canvas->translate(dx, dy); + canvas->drawRect({0, 0, 128, 128}, paint); + paint.setBlendMode(SkBlendMode::kXor); + canvas->drawString(label, 40, 100, paint); + }; + drawSquare(0, 0, SkBlendMode::kSrc, "destination"); + drawSquare(128, 0, SkBlendMode::kSrc, ""); + drawSquare(0, 128, SkBlendMode::kSrc, ""); + canvas->translate(-128, -128); + canvas->rotate(90, 0, 128); + drawSquare(0, 0, SkBlendMode::kSrc, "source"); + drawSquare(0, -128, SkBlendMode::kModulate, "modulate"); + drawSquare(-128, 0, SkBlendMode::kMultiply, "multiply"); +## +## + +#Subtopic Screen +#Line # multiply inverse of pixels, inverting result; brightens destination ## +Given: +#Formula +Sa as source Alpha, Sc as source Color component, +Da as destination Alpha, Dc as destination Color component +## +; SkBlendMode::kScreen replaces destination with: +#Formula +[Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] +## +. +#Example + SkColor colors[] = { SK_ColorRED, SK_ColorBLUE }; + SkPoint horz[] = { { 0, 0 }, { 256, 0 } }; + SkPaint paint; + paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors), + SkShader::kClamp_TileMode)); + canvas->drawPaint(paint); + paint.setBlendMode(SkBlendMode::kDstATop); + SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT }; + SkPoint vert[] = { { 0, 0 }, { 0, 256 } }; + paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas), + SkShader::kClamp_TileMode)); + canvas->drawPaint(paint); + canvas->clipRect( { 30, 30, 226, 226 } ); + canvas->drawColor(SkColorSetA(SK_ColorGREEN, 128), SkBlendMode::kScreen); +## +## + +#Subtopic Overlay +#Line # multiply or screen, depending on destination ## +Given: +#Formula +Sa as source Alpha, Sc as source Color component, +Da as destination Alpha, Dc as destination Color component +## +; SkBlendMode::kOverlay replaces destination with: +#Formula +[Sa + Da - Sa * Da, Sc * (1 - Da) + Dc * (1 - Sa) + + (2 * Dc <= Da ? 2 * Sc * Dc : Sa * Da - 2 * (Da - Dc) * (Sa - Sc))] +## +. +#Example + SkColor colors[] = { SK_ColorRED, SK_ColorBLUE }; + SkPoint horz[] = { { 0, 0 }, { 256, 0 } }; + SkPaint paint; + paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors), + SkShader::kClamp_TileMode)); + canvas->drawPaint(paint); + paint.setBlendMode(SkBlendMode::kDstATop); + SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT }; + SkPoint vert[] = { { 0, 0 }, { 0, 256 } }; + paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas), + SkShader::kClamp_TileMode)); + canvas->drawPaint(paint); + canvas->clipRect( { 30, 30, 226, 226 } ); + canvas->drawColor(SkColorSetA(SK_ColorGREEN, 128), SkBlendMode::kOverlay); +## +## + +#Subtopic Darken +#Line # darker of source and destination ## +Given: +#Formula +Sa as source Alpha, Sc as source Color component, +Da as destination Alpha, Dc as destination Color component +## +; SkBlendMode::kDarken replaces destination with: +#Formula +[Sa + Da - Sa * Da, Sc + Dc - max(Sc * Da, Dc * Sa)] +## +. SkBlendMode::kDarken does not make an image darker; it replaces the destination +component with source if source is darker. +#Example + canvas->drawImage(image, 0, 0); + SkColor colors[] = { SK_ColorWHITE, SK_ColorBLACK }; + SkPoint horz[] = { { 0, 0 }, { 256, 0 } }; + SkPaint paint; + paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors), + SkShader::kClamp_TileMode)); + paint.setBlendMode(SkBlendMode::kDarken); + canvas->drawPaint(paint); +## +## + +#Subtopic Lighten +#Line # lighter of source and destination ## +Given: +#Formula +Sa as source Alpha, Sc as source Color component, +Da as destination Alpha, Dc as destination Color component +## +; SkBlendMode::kLighten replaces destination with: +#Formula +[Sa + Da - Sa * Da, Sc + Dc - min(Sc * Da, Dc * Sa)] +## +. SkBlendMode::kDarken does not make an image lighter; it replaces the destination +component with source if source is lighter. +#Example + canvas->drawImage(image, 0, 0); + SkColor colors[] = { SK_ColorBLACK, SK_ColorWHITE }; + SkPoint horz[] = { { 0, 0 }, { 256, 0 } }; + SkPaint paint; + paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors), + SkShader::kClamp_TileMode)); + paint.setBlendMode(SkBlendMode::kLighten); + canvas->drawPaint(paint); +## +## + +#Subtopic Color_Dodge +#Line # brighten destination to reflect source ## +Given: +#Formula +Sa as source Alpha, Sc as source Color component, +Da as destination Alpha, Dc as destination Color component +## +; SkBlendMode::kColorDodge replaces destination with: +#Formula +[Sa + Da - Sa * Da, Dc == 0 ? Sc * (1 - Da) : Sc == Sa ? Sc + Da * (1 - Sa) : + Sa * min(Da, Dc * Sa / (Sa - Sc)) + Sc * (1 - Da) + Da * (1 - Sa)] +## +, making destination brighter to reflect source. +#Example +#Image 3 + canvas->drawImage(image, 0, 0); + canvas->clipRect({128, 0, 256, 256}); + canvas->drawColor(SkColorSetARGB(0x80, 0x90, 0x90, 0x90), SkBlendMode::kColorDodge); +## +## + +#Subtopic Color_Burn +#Line # darken destination to reflect source ## +Given: +#Formula +Sa as source Alpha, Sc as source Color component, +Da as destination Alpha, Dc as destination Color component +## +; SkBlendMode::kColorBurn replaces destination with: +#Formula +[Sa + Da - Sa * Da, Dc == Da ? Dc + Sc * (1 - Da) : Sc == 0 ? Da * (1 - Sa) : + Sa * (Da - min(Da, (Da - Dc) * Sa / Sc)) + Sc * (1 - Da) + Da * (1 - Sa)] +## +, making destination darker to reflect source. +#Example +#Image 3 + canvas->drawImage(image, 0, 0); + canvas->clipRect({128, 0, 256, 256}); + canvas->drawColor(SkColorSetARGB(0x80, 0x90, 0x90, 0x90), SkBlendMode::kColorBurn); +## +## + +#Subtopic Hard_Light +#Line # multiply or screen, depending on source ## +Given: +#Formula +Sa as source Alpha, Sc as source Color component, +Da as destination Alpha, Dc as destination Color component +## +; SkBlendMode::kHardLight replaces destination with: +#Formula +[Sa + Da - Sa * Da, Sc * (1 - Da) + Dc * (1 - Sa) + + 2 * Sc <= Sa ? 2 * Sc * Dc : Sa * Da - 2 * (Da - Dc) * (Sa - Sc)] +## +, making destination lighter or darker, depending on source. +#Example +#Image 3 + canvas->drawImage(image, 0, 0); + const SkColor colors[] = { 0xFFFFFFFF, 0x00000000 }; + SkPaint paint; + paint.setBlendMode(SkBlendMode::kHardLight); + paint.setShader(SkGradientShader::MakeRadial({ 128, 128}, 100, colors, + nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode)); + canvas->clipRect({0, 128, 256, 256}); + canvas->drawPaint(paint); +## +## + +#Subtopic Soft_Light +#Line # lighten or darken, depending on source ## +Given: +#Formula +Sa as source Alpha, Sc as source Color component, +Da as destination Alpha, Dc as destination Color component +where m = Da > 0 ? Dc / Da : 0 +## +; SkBlendMode::kSoftLight replaces destination with: +#Formula +[Sa + Da - Sa * Da, Sc / Da + Dc / Sa + + (2 * Sc <= Sa ? Dc * (Sa + (2 * Sc - Sa) * (1 - m)) : Dc * Sa + Da * (2 * Sc - Sa) * + (4 * Dc <= Da ? (16 * m * m + 4 * m) * (m - 1) + 7 * m : sqrt(m) - m))]\ +## +, making destination lighter or darker, depending on source. +#Example +#Image 3 + const SkColor colors[] = { 0xFFFFFFFF, 0x3FFFFFFF }; + SkPaint paint; + paint.setBlendMode(SkBlendMode::kSoftLight); + paint.setShader(SkGradientShader::MakeRadial({ 128, 128}, 100, colors, + nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode)); + canvas->drawImage(image, 0, 0); + canvas->drawCircle(128, 128, 100, paint); +## +## + +#Subtopic Difference +#Line # subtract darker from lighter with higher contrast ## +Given: +#Formula +Sa as source Alpha, Sc as source Color component, +Da as destination Alpha, Dc as destination Color component +## +; SkBlendMode::kDifference replaces destination with: +#Formula +[Sa + Da - Sa * Da, Sc + Dc - 2 * min(Sc * Da, Dc * Sa)] +## +, replacing destination with lighter less darker. +#Example +#Image 5 + canvas->drawImage(image, 0, 0); + canvas->drawImage(image, 128, 0); + canvas->drawImage(image, 0, 128); + canvas->drawImage(image, 128, 128); + SkPaint paint; + paint.setBlendMode(SkBlendMode::kDstATop); + SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT }; + SkPoint vert[] = { { 0, 0 }, { 0, 256 } }; + paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas), + SkShader::kClamp_TileMode)); + canvas->drawPaint(paint); + canvas->clipRect( { 30, 30, 226, 226 } ); + canvas->drawColor(0x80bb9977, SkBlendMode::kDifference); +## +## + +#Subtopic Exclusion +#Line # subtract darker from lighter with lower contrast ## +Given: +#Formula +Sa as source Alpha, Sc as source Color, +Da as destination Alpha, Dc as destination Color component +## +; SkBlendMode::kExclusion replaces destination with: +#Formula +[Sa + Da - Sa * Da, Sc + Dc - 2 * Sc * Dc] +## +, replacing destination with lighter less darker, ignoring Alpha. +#Example +#Image 5 + canvas->drawImage(image, 0, 0); + canvas->drawImage(image, 128, 0); + canvas->drawImage(image, 0, 128); + canvas->drawImage(image, 128, 128); + SkPaint paint; + paint.setBlendMode(SkBlendMode::kDstATop); + SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT }; + SkPoint vert[] = { { 0, 0 }, { 0, 256 } }; + paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas), + SkShader::kClamp_TileMode)); + canvas->drawPaint(paint); + canvas->clipRect( { 30, 30, 226, 226 } ); + canvas->drawColor(0x80bb9977, SkBlendMode::kExclusion); +## +## + +#Subtopic Multiply +#Line # multiply source with destination, darkening image ## +Given: +#Formula +Sa as source Alpha, Sc as source Color component, +Da as destination Alpha, Dc as destination Color component +## +; SkBlendMode::kMultiply replaces destination with: +#Formula +[Sa + Da - Sa * Da, Sc * (1 - Da) + Dc * (1 - Sa) + Sc * Dc] +## +, the product of Unpremultiplied source and destination. +SkBlendMode::kMultiply makes the image darker. +#Example + canvas->drawImage(image, 0, 0); + canvas->drawImage(image, 128, 0); + canvas->drawImage(image, 0, 128); + canvas->drawImage(image, 128, 128); + SkPaint paint; + paint.setBlendMode(SkBlendMode::kDstATop); + SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT }; + SkPoint vert[] = { { 0, 0 }, { 0, 256 } }; + paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas), + SkShader::kClamp_TileMode)); + canvas->drawPaint(paint); + canvas->clipRect( { 30, 30, 226, 226 } ); + canvas->drawColor(0x80bb9977, SkBlendMode::kMultiply); +## +## + +#Subtopic Hue +#Line # hue of source with saturation and luminosity of destination ## +Given: +#Formula +Sa as source Alpha, S as source Color, +Da as destination Alpha, D as destination Color +## +; SkBlendMode::kHue replaces destination with: +#Formula +[Sa + Da - Sa * Da, SetLuminosity(SetSaturation(S, Saturation(D)), Luminosity(D))] +## +, source hue, leaving destination luminosity and saturation unchanged. +#Example +canvas->drawImage(image, 0, 0); +canvas->drawColor(0xFF00FF00, SkBlendMode::kHue); +## +## + +#Subtopic Saturation +#Line # saturation of source with hue and luminosity of destination ## +Given: +#Formula +Sa as source Alpha, S as source Color, +Da as destination Alpha, D as destination Color +## +; SkBlendMode::kHue replaces destination with: +#Formula +[Sa + Da - Sa * Da, SetLuminosity(SetSaturation(D, Saturation(S)), Luminosity(D))] +## +, source hue, leaving destination luminosity and saturation unchanged. +#Example +canvas->drawImage(image, 0, 0); +canvas->drawColor(0xFF00FF00, SkBlendMode::kSaturation); +## +## + +#Subtopic Color +#Line # hue and saturation of source with luminosity of destination ## +Given: +#Formula +Sa as source Alpha, S as source Color, +Da as destination Alpha, D as destination Color +## +; SkBlendMode::kColor replaces destination with: +#Formula +[Sa + Da - Sa * Da, SetLuminosity(S, Luminosity(D))] +## +, source hue and saturation, leaving destination luminosity unchanged. +#Example +canvas->drawImage(image, 0, 0); +canvas->drawColor(0xFF00FF00, SkBlendMode::kColor); +## +## + +#Subtopic Luminosity +#Line # luminosity of source with hue and saturation of destination ## +Given: +#Formula +Sa as source Alpha, S as source Color, +Da as destination Alpha, D as destination Color +## +; SkBlendMode::kLuminosity replaces destination with: +#Formula +[Sa + Da - Sa * Da, SetLuminosity(D, Luminosity(S))] +## +, source luminosity, leaving destination hue and saturation unchanged. +#Example +canvas->drawImage(image, 0, 0); +canvas->drawColor(0xFF00FF00, SkBlendMode::kLuminosity); +## +## + +# ------------------------------------------------------------------------------ + +#Method SK_API const char* SkBlendMode_Name(SkBlendMode blendMode) +#In Utility +#Line # returns mode as C string ## + +Returns name of blendMode as null-terminated C string. + +#Param blendMode one of: #list_of_blend_modes# +## + +#Return C string ## + +#Example +SkDebugf("default blend: SkBlendMode::k%s\n", SkBlendMode_Name(SkPaint().getBlendMode())); +#StdOut +default blend: SkBlendMode::kSrcOver +## +## + +#SeeAlso SkBlendMode + +#Method ## + +#Topic Blend_Mode ## -- cgit v1.2.3