Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 1 | #Topic Blend_Mode |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 2 | |
| 3 | #PhraseDef list_of_blend_modes |
| 4 | SkBlendMode::kClear, SkBlendMode::kSrc, SkBlendMode::kDst, SkBlendMode::kSrcOver, |
| 5 | SkBlendMode::kDstOver, SkBlendMode::kSrcIn, SkBlendMode::kDstIn, |
| 6 | SkBlendMode::kSrcOut, SkBlendMode::kDstOut, SkBlendMode::kSrcATop, |
| 7 | SkBlendMode::kDstATop, SkBlendMode::kXor, SkBlendMode::kPlus, |
| 8 | SkBlendMode::kModulate, SkBlendMode::kScreen, SkBlendMode::kOverlay, |
| 9 | SkBlendMode::kDarken, SkBlendMode::kLighten, SkBlendMode::kColorDodge, |
| 10 | SkBlendMode::kColorBurn, SkBlendMode::kHardLight, SkBlendMode::kSoftLight, |
| 11 | SkBlendMode::kDifference, SkBlendMode::kExclusion, SkBlendMode::kMultiply, |
| 12 | SkBlendMode::kHue, SkBlendMode::kSaturation, SkBlendMode::kColor, |
| 13 | SkBlendMode::kLuminosity |
| 14 | ## |
| 15 | |
Cary Clark | 61313f3 | 2018-10-08 14:57:48 -0400 | [diff] [blame] | 16 | #Code |
| 17 | #Populate |
| 18 | ## |
| 19 | |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 20 | #EnumClass SkBlendMode |
| 21 | #Line # algorithm combining source and destination pixels ## |
| 22 | |
Cary Clark | 61313f3 | 2018-10-08 14:57:48 -0400 | [diff] [blame] | 23 | # ------------------------------------------------------------------------------ |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 24 | |
| 25 | #Const kClear 0 |
| 26 | #Line # replaces destination with zero: fully transparent ## |
| 27 | #Details Clear |
| 28 | Replaces destination with Alpha and Color components set to zero; |
| 29 | a fully transparent pixel. |
| 30 | ## |
| 31 | |
| 32 | #Const kSrc 1 |
| 33 | #Line # replaces destination ## |
| 34 | #Details Src |
| 35 | Replaces destination with source. Destination alpha and color component values |
| 36 | are ignored. |
| 37 | ## |
| 38 | |
| 39 | #Const kDst 2 |
| 40 | #Line # preserves destination ## |
| 41 | #Details Dst |
| 42 | Preserves destination, ignoring source. Drawing with Paint set to kDst has |
| 43 | no effect. |
| 44 | ## |
| 45 | |
| 46 | #Const kSrcOver 3 |
| 47 | #Line # source over destination ## |
| 48 | #Details Src_Over |
| 49 | Replaces destination with source blended with destination. If source is opaque, |
| 50 | replaces destination with source. Used as the default Blend_Mode for SkPaint. |
| 51 | ## |
| 52 | |
| 53 | #Const kDstOver 4 |
| 54 | #Line # destination over source ## |
| 55 | #Details Dst_Over |
| 56 | Replaces destination with destination blended with source. If destination is opaque, |
| 57 | has no effect. |
| 58 | ## |
| 59 | |
| 60 | #Const kSrcIn 5 |
| 61 | #Line # source trimmed inside destination ## |
| 62 | #Details Src_In |
| 63 | Replaces destination with source using destination opacity. |
| 64 | ## |
| 65 | |
| 66 | #Const kDstIn 6 |
| 67 | #Line # destination trimmed by source ## |
| 68 | #Details Dst_In |
| 69 | Scales destination opacity by source opacity. |
| 70 | ## |
| 71 | |
| 72 | #Const kSrcOut 7 |
| 73 | #Line # source trimmed outside destination ## |
| 74 | #Details Src_Out |
| 75 | Replaces destination with source using the inverse of destination opacity, |
| 76 | drawing source fully where destination opacity is zero. |
| 77 | ## |
| 78 | |
| 79 | #Const kDstOut 8 |
| 80 | #Line # destination trimmed outside source ## |
| 81 | #Details Dst_Out |
| 82 | Replaces destination opacity with inverse of source opacity. If source is |
| 83 | transparent, has no effect. |
| 84 | ## |
| 85 | |
| 86 | #Const kSrcATop 9 |
| 87 | #Line # source inside destination blended with destination ## |
| 88 | #Details Src_Atop |
| 89 | Blends destination with source using read destination opacity. |
| 90 | ## |
| 91 | |
| 92 | #Const kDstATop 10 |
| 93 | #Line # destination inside source blended with source ## |
| 94 | #Details Dst_Atop |
| 95 | Blends destination with source using source opacity. |
| 96 | ## |
| 97 | |
| 98 | #Const kXor 11 |
| 99 | #Line # each of source and destination trimmed outside the other ## |
| 100 | #Details Xor |
| 101 | Blends destination by exchanging transparency of the source and destination. |
| 102 | ## |
| 103 | |
| 104 | #Const kPlus 12 |
| 105 | #Line # sum of colors ## |
| 106 | #Details Plus |
| 107 | Replaces destination with source and destination added together. |
| 108 | ## |
| 109 | |
| 110 | #Const kModulate 13 |
| 111 | #Line # product of Premultiplied colors; darkens destination ## |
| 112 | #Details Modulate |
| 113 | Replaces destination with source and destination multiplied together. |
| 114 | ## |
| 115 | |
| 116 | #Const kScreen 14 |
| 117 | #Line # multiply inverse of pixels, inverting result; brightens destination ## |
| 118 | #Details Screen |
| 119 | Replaces destination with inverted source and destination multiplied together. |
| 120 | ## |
| 121 | |
| 122 | #Const kLastCoeffMode 14 |
| 123 | #Line # last Porter_Duff blend mode ## |
| 124 | ## |
| 125 | |
| 126 | #Const kOverlay 15 |
| 127 | #Line # multiply or screen, depending on destination ## |
| 128 | #Details Overlay |
| 129 | Replaces destination with multiply or screen, depending on destination. |
| 130 | ## |
| 131 | |
| 132 | #Const kDarken 16 |
| 133 | #Line # darker of source and destination ## |
| 134 | #Details Darken |
| 135 | Replaces destination with darker of source and destination. |
| 136 | ## |
| 137 | |
| 138 | #Const kLighten 17 |
| 139 | #Line # lighter of source and destination ## |
| 140 | #Details Lighten |
| 141 | Replaces destination with lighter of source and destination. |
| 142 | ## |
| 143 | |
| 144 | #Const kColorDodge 18 |
| 145 | #Line # brighten destination to reflect source ## |
| 146 | #Details Color_Dodge |
| 147 | Makes destination brighter to reflect source. |
| 148 | ## |
| 149 | |
| 150 | #Const kColorBurn 19 |
| 151 | #Line # darken destination to reflect source ## |
| 152 | #Details Color_Burn |
| 153 | Makes destination darker to reflect source. |
| 154 | ## |
| 155 | |
| 156 | #Const kHardLight 20 |
| 157 | #Line # multiply or screen, depending on source ## |
| 158 | #Details Hard_Light |
| 159 | Makes destination lighter or darker, depending on source. |
| 160 | ## |
| 161 | |
| 162 | #Const kSoftLight 21 |
| 163 | #Line # lighten or darken, depending on source ## |
| 164 | #Details Soft_Light |
| 165 | Makes destination lighter or darker, depending on source. |
| 166 | ## |
| 167 | |
| 168 | #Const kDifference 22 |
| 169 | #Line # subtract darker from lighter with higher contrast ## |
| 170 | #Details Difference |
| 171 | Subtracts darker from lighter with higher contrast. |
| 172 | ## |
| 173 | |
| 174 | #Const kExclusion 23 |
| 175 | #Line # subtract darker from lighter with lower contrast ## |
| 176 | #Details Exclusion |
| 177 | Subtracts darker from lighter with lower contrast. |
| 178 | ## |
| 179 | |
| 180 | #Const kMultiply 24 |
| 181 | #Line # multiply source with destination, darkening image ## |
| 182 | #Details Multiply |
| 183 | Multiplies source with destination, darkening image. |
| 184 | ## |
| 185 | |
| 186 | #Const kLastSeparableMode 24 |
| 187 | #Line # last blend mode operating separately on components ## |
| 188 | Last blend mode operating separately on components. |
| 189 | ## |
| 190 | |
| 191 | #Const kHue 25 |
| 192 | #Line # hue of source with saturation and luminosity of destination ## |
| 193 | #Details Hue |
| 194 | Replaces hue of destination with hue of source, leaving saturation and luminosity |
| 195 | unchanged. |
| 196 | ## |
| 197 | |
| 198 | #Const kSaturation 26 |
| 199 | #Line # saturation of source with hue and luminosity of destination ## |
| 200 | #Details Saturation |
| 201 | Replaces saturation of destination saturation hue of source, leaving hue and |
| 202 | luminosity unchanged. |
| 203 | ## |
| 204 | |
| 205 | #Const kColor 27 |
| 206 | #Line # hue and saturation of source with luminosity of destination ## |
| 207 | #Details Color |
| 208 | Replaces hue and saturation of destination with hue and saturation of source, |
| 209 | leaving luminosity unchanged. |
| 210 | ## |
| 211 | |
| 212 | #Const kLuminosity 28 |
| 213 | #Line # luminosity of source with hue and saturation of destination ## |
| 214 | #Details Luminosity |
| 215 | Replaces luminosity of destination with luminosity of source, leaving hue and |
| 216 | saturation unchanged. |
| 217 | ## |
| 218 | |
| 219 | #Const kLastMode 28 |
| 220 | #Line # last valid value ## |
| 221 | Used by tests to iterate through all valid values. |
| 222 | ## |
| 223 | |
| 224 | #NoExample |
| 225 | ## |
| 226 | |
| 227 | #SeeAlso SkCanvas::drawColor SkCanvas::drawVertices SkPaint SkShader::MakeCompose SkXfermodeImageFilter |
| 228 | |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 229 | #Subtopic Clear |
| 230 | #Line # makes destination pixels transparent ## |
Cary Clark | 2be81cf | 2018-09-13 12:04:30 -0400 | [diff] [blame] | 231 | SkBlendMode::kClear sets destination to: #Formula # [0, 0] ##. |
| 232 | Use SkBlendMode::kClear to initialize a buffer to fully transparent pixels when |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 233 | creating a mask with irregular edges. |
| 234 | |
| 235 | #Example |
| 236 | #Description |
| 237 | SK_ColorYELLOW is ignored because SkBlendMode::kClear ignores the source pixel |
| 238 | value and the destination pixel value, always setting the destination to zero. |
| 239 | ## |
| 240 | canvas->saveLayer(nullptr, nullptr); |
| 241 | canvas->drawColor(SK_ColorYELLOW, SkBlendMode::kClear); |
| 242 | SkPaint paint; |
| 243 | for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) { |
| 244 | SkColor colors[] = { color, SkColorSetA(color, 0) }; |
| 245 | paint.setShader(SkGradientShader::MakeRadial({ 64, 64}, 100, |
| 246 | colors, nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode)); |
| 247 | canvas->drawCircle(64, 64, 100, paint); |
| 248 | canvas->translate(64, 64); |
| 249 | } |
| 250 | canvas->restore(); |
| 251 | ## |
| 252 | #SeeAlso SkCanvas::clear |
| 253 | ## |
| 254 | |
| 255 | #Subtopic Src |
| 256 | #Line # replaces destination, ignoring Alpha ## |
Cary Clark | 2be81cf | 2018-09-13 12:04:30 -0400 | [diff] [blame] | 257 | Given: #Formula # Sa ## as source Alpha, #Formula # Sc ## as source Color component; |
| 258 | SkBlendMode::kSrc sets destination to: #Formula # [Sa, Sc] ##. |
| 259 | Use SkBlendMode::kSrc to copy one buffer to another. All pixels are copied, |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 260 | regardless of source and destination Alpha values. As a parameter to |
| 261 | SkCanvas::drawAtlas, selects sprites and ignores colors. |
| 262 | #Example |
| 263 | #Image 3 |
| 264 | #Description |
| 265 | SkBlendMode::kSrc does not blend transparent pixels with existing background; |
| 266 | it punches a transparent hole in the existing image. |
| 267 | ## |
| 268 | canvas->drawImage(image, 0, 0); |
| 269 | canvas->clipRect({50, 50, 200, 200}); |
| 270 | SkPaint srcBlend; |
| 271 | srcBlend.setBlendMode(SkBlendMode::kSrc); |
| 272 | canvas->saveLayer(nullptr, &srcBlend); |
| 273 | canvas->drawColor(0); |
| 274 | SkPaint transRed; |
| 275 | transRed.setColor(SkColorSetA(SK_ColorRED, 127)); |
| 276 | canvas->drawCircle(125, 125, 75, transRed); |
| 277 | canvas->restore(); |
| 278 | ## |
| 279 | #SeeAlso SkSurface::draw SkSurface::readPixels |
| 280 | ## |
| 281 | |
| 282 | #Subtopic Dst |
| 283 | #Line # preserves destination, ignoring source ## |
Cary Clark | 2be81cf | 2018-09-13 12:04:30 -0400 | [diff] [blame] | 284 | Given: #Formula # Da ## as destination Alpha, #Formula # Dc ## as destination Color component; |
| 285 | SkBlendMode::kDst preserves destination set to: #Formula # [Da, Dc] ##. |
| 286 | Setting Paint Blend_Mode to SkBlendMode::kDst causes drawing with |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 287 | Paint to have no effect. As a parameter to SkCanvas::drawAtlas, |
| 288 | selects colors and ignores sprites. |
| 289 | #Example |
| 290 | #Image 3 |
| 291 | SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 125, 128 } }; |
| 292 | SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } }; |
| 293 | SkColor colors[] = { 0x7f55aa00, 0x7f3333bf }; |
| 294 | canvas->drawAtlas(image.get(), xforms, tex, colors, 2, SkBlendMode::kSrc, nullptr, nullptr); |
| 295 | canvas->translate(128, 0); |
| 296 | canvas->drawAtlas(image.get(), xforms, tex, colors, 2, SkBlendMode::kDst, nullptr, nullptr); |
| 297 | ## |
| 298 | ## |
| 299 | |
| 300 | #Subtopic Src_Over |
| 301 | #Line # blends source with destination ## |
Cary Clark | 2be81cf | 2018-09-13 12:04:30 -0400 | [diff] [blame] | 302 | Given: #Formula # Sa ## as source Alpha, #Formula # Sc ## as source Color component, |
| 303 | #Formula # Da ## as destination Alpha, #Formula # Dc ## as destination Color component; |
| 304 | SkBlendMode::kSrcOver replaces destination with: #Formula # [Sa + Da * (1 - Sa), Sc + Dc * (1 - Sa)] ##, |
| 305 | drawing source over destination. SkBlendMode::kSrcOver is the default for Paint. |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 306 | |
| 307 | SkBlendMode::kSrcOver cannot make destination more transparent; the result will |
| 308 | be at least as opaque as the less transparent of source and original destination. |
| 309 | #Example |
| 310 | SkColor colors[] = { SK_ColorRED, SK_ColorBLUE }; |
| 311 | SkPoint horz[] = { { 0, 0 }, { 256, 0 } }; |
| 312 | SkPaint paint; |
| 313 | paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors), |
| 314 | SkShader::kClamp_TileMode)); |
| 315 | canvas->drawPaint(paint); |
| 316 | paint.setBlendMode(SkBlendMode::kDstIn); |
| 317 | SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT }; |
| 318 | SkPoint vert[] = { { 0, 0 }, { 0, 256 } }; |
| 319 | paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas), |
| 320 | SkShader::kClamp_TileMode)); |
| 321 | canvas->drawPaint(paint); |
| 322 | canvas->clipRect( { 30, 30, 226, 226 } ); |
| 323 | canvas->drawColor(SkColorSetA(SK_ColorGREEN, 128), SkBlendMode::kSrcOver); |
| 324 | ## |
| 325 | ## |
| 326 | |
| 327 | #Subtopic Dst_Over |
| 328 | #Line # blends destination with source ## |
Cary Clark | 2be81cf | 2018-09-13 12:04:30 -0400 | [diff] [blame] | 329 | Given: #Formula # Sa ## as source Alpha, #Formula # Sc ## as source Color component, |
| 330 | #Formula # Da ## as destination Alpha, #Formula # Dc ## as destination Color component; |
| 331 | SkBlendMode::kDstOver replaces destination with: #Formula # [Da + Sa * (1 - Da), Dc + Sc * (1 - Da)] ##, |
| 332 | drawing destination over source. Has no effect destination if is opaque. |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 333 | #Example |
| 334 | SkColor colors[] = { SK_ColorRED, SK_ColorBLUE }; |
| 335 | SkPoint horz[] = { { 0, 0 }, { 256, 0 } }; |
| 336 | SkPaint paint; |
| 337 | paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors), |
| 338 | SkShader::kClamp_TileMode)); |
| 339 | canvas->drawPaint(paint); |
| 340 | paint.setBlendMode(SkBlendMode::kDstIn); |
| 341 | SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT }; |
| 342 | SkPoint vert[] = { { 0, 0 }, { 0, 256 } }; |
| 343 | paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas), |
| 344 | SkShader::kClamp_TileMode)); |
| 345 | canvas->drawPaint(paint); |
| 346 | canvas->clipRect( { 30, 30, 226, 226 } ); |
| 347 | canvas->drawColor(SkColorSetA(SK_ColorGREEN, 128), SkBlendMode::kDstOver); |
| 348 | ## |
| 349 | ## |
| 350 | |
| 351 | #Subtopic Src_In |
| 352 | #Line # source trimmed inside destination ## |
Cary Clark | 2be81cf | 2018-09-13 12:04:30 -0400 | [diff] [blame] | 353 | Given: #Formula # Sa ## as source Alpha, #Formula # Sc ## as source Color component, |
| 354 | #Formula # Da ## as destination Alpha; |
| 355 | SkBlendMode::kSrcIn replaces destination with: #Formula # [Sa * Da, Sc * Da] ##, |
| 356 | drawing source with destination opacity. |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 357 | #Example |
| 358 | SkColor colors[] = { SK_ColorRED, SK_ColorBLUE }; |
| 359 | SkPoint horz[] = { { 0, 0 }, { 256, 0 } }; |
| 360 | SkPaint paint; |
| 361 | paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors), |
| 362 | SkShader::kClamp_TileMode)); |
| 363 | canvas->drawPaint(paint); |
| 364 | paint.setBlendMode(SkBlendMode::kDstIn); |
| 365 | SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT }; |
| 366 | SkPoint vert[] = { { 0, 0 }, { 0, 256 } }; |
| 367 | paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas), |
| 368 | SkShader::kClamp_TileMode)); |
| 369 | canvas->drawPaint(paint); |
| 370 | canvas->clipRect( { 30, 30, 226, 226 } ); |
| 371 | canvas->drawColor(SkColorSetA(SK_ColorGREEN, 128), SkBlendMode::kSrcIn); |
| 372 | ## |
| 373 | ## |
| 374 | |
| 375 | #Subtopic Dst_In |
| 376 | #Line # destination trimmed by source ## |
Cary Clark | 2be81cf | 2018-09-13 12:04:30 -0400 | [diff] [blame] | 377 | Given: #Formula # Sa ## as source Alpha, |
| 378 | #Formula # Da ## as destination Alpha, #Formula # Dc ## as destination Color component; |
| 379 | SkBlendMode::kDstIn replaces destination with: #Formula # [Da * Sa, Dc * Sa] ##, |
| 380 | scaling destination Alpha by source Alpha. Resulting |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 381 | destination is visible where source is visible. |
| 382 | #Example |
| 383 | SkColor colors[] = { SK_ColorRED, SK_ColorBLUE }; |
| 384 | SkPoint horz[] = { { 0, 0 }, { 256, 0 } }; |
| 385 | SkPaint paint; |
| 386 | paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors), |
| 387 | SkShader::kClamp_TileMode)); |
| 388 | canvas->drawPaint(paint); |
| 389 | paint.setBlendMode(SkBlendMode::kDstIn); |
| 390 | SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT }; |
| 391 | SkPoint vert[] = { { 0, 0 }, { 0, 256 } }; |
| 392 | paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas), |
| 393 | SkShader::kClamp_TileMode)); |
| 394 | canvas->drawPaint(paint); |
| 395 | canvas->clipRect( { 30, 30, 226, 226 } ); |
| 396 | canvas->drawColor(SkColorSetA(SK_ColorGREEN, 128), SkBlendMode::kDstIn); |
| 397 | ## |
| 398 | ## |
| 399 | |
| 400 | #Subtopic Src_Out |
| 401 | #Line # source trimmed outside destination ## |
Cary Clark | 2be81cf | 2018-09-13 12:04:30 -0400 | [diff] [blame] | 402 | Given: #Formula # Sa ## as source Alpha, #Formula # Sc ## as source Color component, |
| 403 | #Formula # Da ## as destination Alpha; |
| 404 | SkBlendMode::kSrcOut replaces destination with: #Formula # [Sa * (1 - Da), Sc * (1 - Da)] ##, |
| 405 | drawing source fully where destination Alpha is zero. Is destination |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 406 | is opaque, has no effect. |
| 407 | #Example |
| 408 | SkColor colors[] = { SK_ColorRED, SK_ColorBLUE }; |
| 409 | SkPoint horz[] = { { 0, 0 }, { 256, 0 } }; |
| 410 | SkPaint paint; |
| 411 | paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors), |
| 412 | SkShader::kClamp_TileMode)); |
| 413 | canvas->drawPaint(paint); |
| 414 | paint.setBlendMode(SkBlendMode::kDstIn); |
| 415 | SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT }; |
| 416 | SkPoint vert[] = { { 0, 0 }, { 0, 256 } }; |
| 417 | paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas), |
| 418 | SkShader::kClamp_TileMode)); |
| 419 | canvas->drawPaint(paint); |
| 420 | canvas->clipRect( { 30, 30, 226, 226 } ); |
| 421 | canvas->drawColor(SkColorSetA(SK_ColorGREEN, 128), SkBlendMode::kSrcOut); |
| 422 | ## |
| 423 | ## |
| 424 | |
| 425 | #Subtopic Dst_Out |
| 426 | #Line # destination trimmed outside source ## |
Cary Clark | 2be81cf | 2018-09-13 12:04:30 -0400 | [diff] [blame] | 427 | Given: #Formula # Sa ## as source Alpha, |
| 428 | #Formula # Da ## as destination Alpha, #Formula # Dc ## as destination Color component; |
| 429 | SkBlendMode::kDstOut replaces destination with: #Formula # [Da * (1 - Sa), Dc * (1 - Sa)] ##, |
| 430 | scaling destination Alpha by source transparency. Resulting |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 431 | destination is visible where source is transparent. If source is transparent, |
| 432 | has no effect. |
| 433 | #Example |
| 434 | SkColor colors[] = { SK_ColorRED, SK_ColorBLUE }; |
| 435 | SkPoint horz[] = { { 0, 0 }, { 256, 0 } }; |
| 436 | SkPaint paint; |
| 437 | paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors), |
| 438 | SkShader::kClamp_TileMode)); |
| 439 | canvas->drawPaint(paint); |
| 440 | paint.setBlendMode(SkBlendMode::kDstIn); |
| 441 | SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT }; |
| 442 | SkPoint vert[] = { { 0, 0 }, { 0, 256 } }; |
| 443 | paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas), |
| 444 | SkShader::kClamp_TileMode)); |
| 445 | canvas->drawPaint(paint); |
| 446 | canvas->clipRect( { 30, 30, 226, 226 } ); |
| 447 | canvas->drawColor(SkColorSetA(SK_ColorGREEN, 128), SkBlendMode::kDstOut); |
| 448 | ## |
| 449 | ## |
| 450 | |
| 451 | #Subtopic Src_Atop |
| 452 | #Line # source inside destination over destination ## |
Cary Clark | 2be81cf | 2018-09-13 12:04:30 -0400 | [diff] [blame] | 453 | Given: #Formula # Sa ## as source Alpha, #Formula # Sc ## as source Color component, |
| 454 | #Formula # Da ## as destination Alpha, #Formula # Dc ## as destination Color component; |
| 455 | SkBlendMode::kSrcATop replaces destination with: #Formula # [Da, Sc * Da + Dc * (1 - Sa)] ##, |
| 456 | replacing opaque destination with opaque source. If source or destination |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 457 | is transparent, has no effect. |
| 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::kSrcATop); |
| 473 | ## |
| 474 | ## |
| 475 | |
| 476 | #Subtopic Dst_Atop |
| 477 | #Line # destination inside source over source ## |
Cary Clark | 2be81cf | 2018-09-13 12:04:30 -0400 | [diff] [blame] | 478 | Given: #Formula # Sa ## as source Alpha, #Formula # Sc ## as source Color component, |
| 479 | #Formula # Da ## as destination Alpha, #Formula # Dc ## as destination Color component; |
| 480 | SkBlendMode::kDstATop replaces destination with: #Formula # [Sa, Dc * Sa + Sc * (1 - Da)] ##, |
| 481 | making destination transparent where source is transparent. |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 482 | #Example |
| 483 | SkColor colors[] = { SK_ColorRED, SK_ColorBLUE }; |
| 484 | SkPoint horz[] = { { 0, 0 }, { 256, 0 } }; |
| 485 | SkPaint paint; |
| 486 | paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors), |
| 487 | SkShader::kClamp_TileMode)); |
| 488 | canvas->drawPaint(paint); |
| 489 | paint.setBlendMode(SkBlendMode::kDstATop); |
| 490 | SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT }; |
| 491 | SkPoint vert[] = { { 0, 0 }, { 0, 256 } }; |
| 492 | paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas), |
| 493 | SkShader::kClamp_TileMode)); |
| 494 | canvas->drawPaint(paint); |
| 495 | canvas->clipRect( { 30, 30, 226, 226 } ); |
| 496 | canvas->drawColor(SkColorSetA(SK_ColorGREEN, 128), SkBlendMode::kSrcATop); |
| 497 | ## |
| 498 | ## |
| 499 | |
| 500 | #Subtopic Xor |
| 501 | #Line # each of source and destination trimmed outside the other ## |
Cary Clark | 2be81cf | 2018-09-13 12:04:30 -0400 | [diff] [blame] | 502 | Given: #Formula # Sa ## as source Alpha, #Formula # Sc ## as source Color component, |
| 503 | #Formula # Da ## as destination Alpha, #Formula # Dc ## as destination Color component; |
| 504 | SkBlendMode::kXor replaces destination with: |
| 505 | #Formula # [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + Dc * (1 - Sa)] ##, |
| 506 | exchanging the transparency of the source and destination. |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 507 | #Example |
| 508 | SkPaint paint; |
| 509 | paint.setBlendMode(SkBlendMode::kXor); |
| 510 | for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) { |
| 511 | SkColor colors[] = { color, SkColorSetA(color, 192), SkColorSetA(color, 128), |
| 512 | SkColorSetA(color, 0) }; |
| 513 | paint.setShader(SkGradientShader::MakeRadial({ 64, 64}, 100, |
| 514 | colors, nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode)); |
| 515 | canvas->drawCircle(64, 64, 100, paint); |
| 516 | canvas->translate(64, 64); |
| 517 | } |
| 518 | ## |
| 519 | ## |
| 520 | |
| 521 | #Subtopic Plus |
| 522 | #Line # sum of colors ## |
Cary Clark | 2be81cf | 2018-09-13 12:04:30 -0400 | [diff] [blame] | 523 | Given: #Formula # Sa ## as source Alpha, #Formula # Sc ## as source Color component, |
| 524 | #Formula # Da ## as destination Alpha, #Formula # Dc ## as destination Color component; |
| 525 | SkBlendMode::kPlus replaces destination with: #Formula # [Sa + Da, Sc + Dc] ##, |
| 526 | summing the Alpha and Color components. |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 527 | #Example |
| 528 | canvas->drawColor(SK_ColorBLACK); |
| 529 | SkPaint paint; |
| 530 | paint.setBlendMode(SkBlendMode::kPlus); |
| 531 | for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) { |
| 532 | SkColor colors[] = { color, SkColorSetA(color, 192), SkColorSetA(color, 128), |
| 533 | SkColorSetA(color, 0) }; |
| 534 | paint.setShader(SkGradientShader::MakeRadial({ 64, 64}, 100, |
| 535 | colors, nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode)); |
| 536 | canvas->drawCircle(64, 64, 100, paint); |
| 537 | canvas->translate(64, 64); |
| 538 | } |
| 539 | ## |
| 540 | ## |
| 541 | |
| 542 | #Subtopic Modulate |
| 543 | #Line # product of Premultiplied colors; darkens destination ## |
Cary Clark | 2be81cf | 2018-09-13 12:04:30 -0400 | [diff] [blame] | 544 | Given: #Formula # Sa ## as source Alpha, #Formula # Sc ## as source Color component, |
| 545 | #Formula # Da ## as destination Alpha, #Formula # Dc ## as destination Color component; |
| 546 | SkBlendMode::kModulate replaces destination with: #Formula # [Sa * Da, Sc * Dc] ##, |
| 547 | scaling Alpha and Color components by the lesser of the values. |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 548 | SkBlendMode::kModulate differs from SkBlendMode::kMultiply in two ways. |
| 549 | SkBlendMode::kModulate like SkBlendMode::kSrcATop alters the destination inside |
Cary Clark | 80247e5 | 2018-07-11 16:18:41 -0400 | [diff] [blame] | 550 | the destination area, as if the destination Alpha defined the boundaries of a |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 551 | soft clip. SkBlendMode::kMultiply like SkBlendMode::kSrcOver can alter the |
| 552 | destination where the destination is transparent. |
| 553 | SkBlendMode::kModulate computes the product of the source and destination using |
| 554 | Premultiplied component values. SkBlendMode::kMultiply the product of the source |
| 555 | and destination using Unpremultiplied component values. |
| 556 | #Example |
| 557 | #Description |
| 558 | If source and destination are opaque, SkBlendMode::kModulate and |
| 559 | SkBlendMode::kMultiply produce the same results. |
| 560 | ## |
| 561 | auto drawSquare = [=](int dx, int dy, SkBlendMode mode, const char* label) -> void { |
| 562 | const SkColor colors[] = { SK_ColorBLACK, SK_ColorWHITE }; |
| 563 | const SkPoint horz[] = { { 0, 0 }, { 128, 0 } }; |
| 564 | SkPaint paint; |
| 565 | paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors), |
| 566 | SkShader::kClamp_TileMode)); |
| 567 | paint.setBlendMode(mode); |
| 568 | canvas->translate(dx, dy); |
| 569 | canvas->drawRect({0, 0, 128, 128}, paint); |
| 570 | paint.setBlendMode(SkBlendMode::kXor); |
| 571 | canvas->drawString(label, 40, 100, paint); |
| 572 | }; |
| 573 | drawSquare(0, 0, SkBlendMode::kSrc, "destination"); |
| 574 | drawSquare(128, 0, SkBlendMode::kSrc, ""); |
| 575 | drawSquare(0, 128, SkBlendMode::kSrc, ""); |
| 576 | canvas->translate(-128, -128); |
| 577 | canvas->rotate(90, 0, 128); |
| 578 | drawSquare(0, 0, SkBlendMode::kSrc, "source"); |
| 579 | drawSquare(0, -128, SkBlendMode::kModulate, "modulate"); |
| 580 | drawSquare(-128, 0, SkBlendMode::kMultiply, "multiply"); |
| 581 | ## |
| 582 | ## |
| 583 | |
| 584 | #Subtopic Screen |
| 585 | #Line # multiply inverse of pixels, inverting result; brightens destination ## |
Cary Clark | 2be81cf | 2018-09-13 12:04:30 -0400 | [diff] [blame] | 586 | Given: #Formula # Sa ## as source Alpha, #Formula # Sc ## as source Color component, |
| 587 | #Formula # Da ## as destination Alpha, #Formula # Dc ## as destination Color component; |
| 588 | SkBlendMode::kScreen replaces destination with: #Formula # [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] ##. |
| 589 | |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 590 | #Example |
| 591 | SkColor colors[] = { SK_ColorRED, SK_ColorBLUE }; |
| 592 | SkPoint horz[] = { { 0, 0 }, { 256, 0 } }; |
| 593 | SkPaint paint; |
| 594 | paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors), |
| 595 | SkShader::kClamp_TileMode)); |
| 596 | canvas->drawPaint(paint); |
| 597 | paint.setBlendMode(SkBlendMode::kDstATop); |
| 598 | SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT }; |
| 599 | SkPoint vert[] = { { 0, 0 }, { 0, 256 } }; |
| 600 | paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas), |
| 601 | SkShader::kClamp_TileMode)); |
| 602 | canvas->drawPaint(paint); |
| 603 | canvas->clipRect( { 30, 30, 226, 226 } ); |
| 604 | canvas->drawColor(SkColorSetA(SK_ColorGREEN, 128), SkBlendMode::kScreen); |
| 605 | ## |
| 606 | ## |
| 607 | |
| 608 | #Subtopic Overlay |
| 609 | #Line # multiply or screen, depending on destination ## |
Cary Clark | 2be81cf | 2018-09-13 12:04:30 -0400 | [diff] [blame] | 610 | Given: #Formula # Sa ## as source Alpha, #Formula # Sc ## as source Color component, |
| 611 | #Formula # Da ## as destination Alpha, #Formula # Dc ## as destination Color component; |
| 612 | SkBlendMode::kOverlay replaces destination with: |
| 613 | #Formula # [Sa + Da - Sa * Da, Sc * (1 - Da) + Dc * (1 - Sa) + |
| 614 | (2 * Dc <= Da ? 2 * Sc * Dc : Sa * Da - 2 * (Da - Dc) * (Sa - Sc))] ##. |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 615 | #Example |
| 616 | SkColor colors[] = { SK_ColorRED, SK_ColorBLUE }; |
| 617 | SkPoint horz[] = { { 0, 0 }, { 256, 0 } }; |
| 618 | SkPaint paint; |
| 619 | paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors), |
| 620 | SkShader::kClamp_TileMode)); |
| 621 | canvas->drawPaint(paint); |
| 622 | paint.setBlendMode(SkBlendMode::kDstATop); |
| 623 | SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT }; |
| 624 | SkPoint vert[] = { { 0, 0 }, { 0, 256 } }; |
| 625 | paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas), |
| 626 | SkShader::kClamp_TileMode)); |
| 627 | canvas->drawPaint(paint); |
| 628 | canvas->clipRect( { 30, 30, 226, 226 } ); |
| 629 | canvas->drawColor(SkColorSetA(SK_ColorGREEN, 128), SkBlendMode::kOverlay); |
| 630 | ## |
| 631 | ## |
| 632 | |
| 633 | #Subtopic Darken |
| 634 | #Line # darker of source and destination ## |
Cary Clark | 2be81cf | 2018-09-13 12:04:30 -0400 | [diff] [blame] | 635 | Given: #Formula # Sa ## as source Alpha, #Formula # Sc ## as source Color component, |
| 636 | #Formula # Da ## as destination Alpha, #Formula # Dc ## as destination Color component; |
| 637 | SkBlendMode::kDarken replaces destination with: |
| 638 | #Formula # [Sa + Da - Sa * Da, Sc + Dc - max(Sc * Da, Dc * Sa)] ##. |
| 639 | SkBlendMode::kDarken does not make an image darker; it replaces the destination |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 640 | component with source if source is darker. |
| 641 | #Example |
Cary Clark | 53498e9 | 2018-06-28 19:13:56 -0400 | [diff] [blame] | 642 | #Image 3 |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 643 | canvas->drawImage(image, 0, 0); |
| 644 | SkColor colors[] = { SK_ColorWHITE, SK_ColorBLACK }; |
| 645 | SkPoint horz[] = { { 0, 0 }, { 256, 0 } }; |
| 646 | SkPaint paint; |
| 647 | paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors), |
| 648 | SkShader::kClamp_TileMode)); |
| 649 | paint.setBlendMode(SkBlendMode::kDarken); |
| 650 | canvas->drawPaint(paint); |
| 651 | ## |
| 652 | ## |
| 653 | |
| 654 | #Subtopic Lighten |
| 655 | #Line # lighter of source and destination ## |
Cary Clark | 2be81cf | 2018-09-13 12:04:30 -0400 | [diff] [blame] | 656 | Given: #Formula # Sa ## as source Alpha, #Formula # Sc ## as source Color component, |
| 657 | #Formula # Da ## as destination Alpha, #Formula # Dc ## as destination Color component; |
| 658 | SkBlendMode::kLighten replaces destination with: |
| 659 | #Formula # [Sa + Da - Sa * Da, Sc + Dc - min(Sc * Da, Dc * Sa)] ##. |
| 660 | SkBlendMode::kDarken does not make an image lighter; it replaces the destination |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 661 | component with source if source is lighter. |
| 662 | #Example |
Cary Clark | 53498e9 | 2018-06-28 19:13:56 -0400 | [diff] [blame] | 663 | #Image 3 |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 664 | canvas->drawImage(image, 0, 0); |
| 665 | SkColor colors[] = { SK_ColorBLACK, SK_ColorWHITE }; |
| 666 | SkPoint horz[] = { { 0, 0 }, { 256, 0 } }; |
| 667 | SkPaint paint; |
| 668 | paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, SK_ARRAY_COUNT(colors), |
| 669 | SkShader::kClamp_TileMode)); |
| 670 | paint.setBlendMode(SkBlendMode::kLighten); |
| 671 | canvas->drawPaint(paint); |
| 672 | ## |
| 673 | ## |
| 674 | |
| 675 | #Subtopic Color_Dodge |
| 676 | #Line # brighten destination to reflect source ## |
Cary Clark | 2be81cf | 2018-09-13 12:04:30 -0400 | [diff] [blame] | 677 | Given: #Formula # Sa ## as source Alpha, #Formula # Sc ## as source Color component, |
| 678 | #Formula # Da ## as destination Alpha, #Formula # Dc ## as destination Color component; |
| 679 | SkBlendMode::kColorDodge replaces destination with: |
| 680 | #Formula # [Sa + Da - Sa * Da, Dc == 0 ? Sc * (1 - Da) : Sc == Sa ? Sc + Da * (1 - Sa) : |
| 681 | Sa * min(Da, Dc * Sa / (Sa - Sc)) + Sc * (1 - Da) + Da * (1 - Sa)] ##, |
| 682 | making destination brighter to reflect source. |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 683 | #Example |
| 684 | #Image 3 |
| 685 | canvas->drawImage(image, 0, 0); |
| 686 | canvas->clipRect({128, 0, 256, 256}); |
| 687 | canvas->drawColor(SkColorSetARGB(0x80, 0x90, 0x90, 0x90), SkBlendMode::kColorDodge); |
| 688 | ## |
| 689 | ## |
| 690 | |
| 691 | #Subtopic Color_Burn |
| 692 | #Line # darken destination to reflect source ## |
Cary Clark | 2be81cf | 2018-09-13 12:04:30 -0400 | [diff] [blame] | 693 | Given: #Formula # Sa ## as source Alpha, #Formula # Sc ## as source Color component, |
| 694 | #Formula # Da ## as destination Alpha, #Formula # Dc ## as destination Color component; |
| 695 | SkBlendMode::kColorBurn replaces destination with: |
| 696 | #Formula # [Sa + Da - Sa * Da, Dc == Da ? Dc + Sc * (1 - Da) : Sc == 0 ? Da * (1 - Sa) : |
| 697 | Sa * (Da - min(Da, (Da - Dc) * Sa / Sc)) + Sc * (1 - Da) + Da * (1 - Sa)] ##, |
| 698 | making destination darker to reflect source. |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 699 | #Example |
| 700 | #Image 3 |
| 701 | canvas->drawImage(image, 0, 0); |
| 702 | canvas->clipRect({128, 0, 256, 256}); |
| 703 | canvas->drawColor(SkColorSetARGB(0x80, 0x90, 0x90, 0x90), SkBlendMode::kColorBurn); |
| 704 | ## |
| 705 | ## |
| 706 | |
| 707 | #Subtopic Hard_Light |
| 708 | #Line # multiply or screen, depending on source ## |
Cary Clark | 2be81cf | 2018-09-13 12:04:30 -0400 | [diff] [blame] | 709 | Given: #Formula # Sa ## as source Alpha, #Formula # Sc ## as source Color component, |
| 710 | #Formula # Da ## as destination Alpha, #Formula # Dc ## as destination Color component; |
| 711 | SkBlendMode::kHardLight replaces destination with: |
| 712 | #Formula # [Sa + Da - Sa * Da, Sc * (1 - Da) + Dc * (1 - Sa) + |
| 713 | 2 * Sc <= Sa ? 2 * Sc * Dc : Sa * Da - 2 * (Da - Dc) * (Sa - Sc)] ##, |
| 714 | making destination lighter or darker, depending on source. |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 715 | #Example |
| 716 | #Image 3 |
| 717 | canvas->drawImage(image, 0, 0); |
| 718 | const SkColor colors[] = { 0xFFFFFFFF, 0x00000000 }; |
| 719 | SkPaint paint; |
| 720 | paint.setBlendMode(SkBlendMode::kHardLight); |
| 721 | paint.setShader(SkGradientShader::MakeRadial({ 128, 128}, 100, colors, |
| 722 | nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode)); |
| 723 | canvas->clipRect({0, 128, 256, 256}); |
| 724 | canvas->drawPaint(paint); |
| 725 | ## |
| 726 | ## |
| 727 | |
| 728 | #Subtopic Soft_Light |
| 729 | #Line # lighten or darken, depending on source ## |
Cary Clark | 2be81cf | 2018-09-13 12:04:30 -0400 | [diff] [blame] | 730 | Given: #Formula # Sa ## as source Alpha, #Formula # Sc ## as source Color component, |
| 731 | #Formula # Da ## as destination Alpha, #Formula # Dc ## as destination Color component; |
| 732 | where #Formula # m = Da > 0 ? Dc / Da : 0 ##; |
| 733 | SkBlendMode::kSoftLight replaces destination with: #Formula # [Sa + Da - Sa * Da, Sc / Da + Dc / Sa + |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 734 | (2 * Sc <= Sa ? Dc * (Sa + (2 * Sc - Sa) * (1 - m)) : Dc * Sa + Da * (2 * Sc - Sa) * |
Cary Clark | 2be81cf | 2018-09-13 12:04:30 -0400 | [diff] [blame] | 735 | (4 * Dc <= Da ? (16 * m * m + 4 * m) * (m - 1) + 7 * m : sqrt(m) - m))] ##, |
| 736 | making destination lighter or darker, depending on source. |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 737 | #Example |
| 738 | #Image 3 |
| 739 | const SkColor colors[] = { 0xFFFFFFFF, 0x3FFFFFFF }; |
| 740 | SkPaint paint; |
| 741 | paint.setBlendMode(SkBlendMode::kSoftLight); |
| 742 | paint.setShader(SkGradientShader::MakeRadial({ 128, 128}, 100, colors, |
| 743 | nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode)); |
| 744 | canvas->drawImage(image, 0, 0); |
| 745 | canvas->drawCircle(128, 128, 100, paint); |
| 746 | ## |
| 747 | ## |
| 748 | |
| 749 | #Subtopic Difference |
| 750 | #Line # subtract darker from lighter with higher contrast ## |
Cary Clark | 2be81cf | 2018-09-13 12:04:30 -0400 | [diff] [blame] | 751 | Given: #Formula # Sa ## as source Alpha, #Formula # Sc ## as source Color component, |
| 752 | #Formula # Da ## as destination Alpha, #Formula # Dc ## as destination Color component; |
| 753 | SkBlendMode::kDifference replaces destination with: |
| 754 | #Formula # [Sa + Da - Sa * Da, Sc + Dc - 2 * min(Sc * Da, Dc * Sa)] ##, |
| 755 | replacing destination with lighter less darker. |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 756 | #Example |
| 757 | #Image 5 |
Cary Clark | 09d80c0 | 2018-10-31 12:14:03 -0400 | [diff] [blame] | 758 | canvas->drawImage(image, 0, 0); |
| 759 | canvas->drawImage(image, 128, 0); |
| 760 | canvas->drawImage(image, 0, 128); |
| 761 | canvas->drawImage(image, 128, 128); |
| 762 | SkPaint paint; |
| 763 | paint.setBlendMode(SkBlendMode::kDstATop); |
| 764 | SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT }; |
| 765 | SkPoint vert[] = { { 0, 0 }, { 0, 256 } }; |
| 766 | paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas), |
| 767 | SkShader::kClamp_TileMode)); |
| 768 | canvas->drawPaint(paint); |
| 769 | canvas->clipRect( { 30, 30, 226, 226 } ); |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 770 | canvas->drawColor(0x80bb9977, SkBlendMode::kDifference); |
| 771 | ## |
| 772 | ## |
| 773 | |
| 774 | #Subtopic Exclusion |
| 775 | #Line # subtract darker from lighter with lower contrast ## |
Cary Clark | 2be81cf | 2018-09-13 12:04:30 -0400 | [diff] [blame] | 776 | Given: #Formula # Sa ## as source Alpha, #Formula # Sc ## as source Color component, |
| 777 | #Formula # Da ## as destination Alpha, #Formula # Dc ## as destination Color component; |
| 778 | SkBlendMode::kExclusion replaces destination with: |
| 779 | #Formula # [Sa + Da - Sa * Da, Sc + Dc - 2 * Sc * Dc] ##, |
| 780 | replacing destination with lighter less darker, ignoring Alpha. |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 781 | #Example |
| 782 | #Image 5 |
Cary Clark | 09d80c0 | 2018-10-31 12:14:03 -0400 | [diff] [blame] | 783 | canvas->drawImage(image, 0, 0); |
| 784 | canvas->drawImage(image, 128, 0); |
| 785 | canvas->drawImage(image, 0, 128); |
| 786 | canvas->drawImage(image, 128, 128); |
| 787 | SkPaint paint; |
| 788 | paint.setBlendMode(SkBlendMode::kDstATop); |
| 789 | SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT }; |
| 790 | SkPoint vert[] = { { 0, 0 }, { 0, 256 } }; |
| 791 | paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas), |
| 792 | SkShader::kClamp_TileMode)); |
| 793 | canvas->drawPaint(paint); |
| 794 | canvas->clipRect( { 30, 30, 226, 226 } ); |
| 795 | canvas->drawColor(0x80bb9977, SkBlendMode::kExclusion); |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 796 | ## |
| 797 | ## |
| 798 | |
| 799 | #Subtopic Multiply |
| 800 | #Line # multiply source with destination, darkening image ## |
Cary Clark | 2be81cf | 2018-09-13 12:04:30 -0400 | [diff] [blame] | 801 | Given: #Formula # Sa ## as source Alpha, #Formula # Sc ## as source Color component, |
| 802 | #Formula # Da ## as destination Alpha, #Formula # Dc ## as destination Color component; |
| 803 | SkBlendMode::kMultiply replaces destination with: |
| 804 | #Formula # [Sa + Da - Sa * Da, Sc * (1 - Da) + Dc * (1 - Sa) + Sc * Dc] ##, |
| 805 | the product of Unpremultiplied source and destination. |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 806 | SkBlendMode::kMultiply makes the image darker. |
| 807 | #Example |
Cary Clark | 53498e9 | 2018-06-28 19:13:56 -0400 | [diff] [blame] | 808 | #Image 5 |
Cary Clark | 09d80c0 | 2018-10-31 12:14:03 -0400 | [diff] [blame] | 809 | canvas->drawImage(image, 0, 0); |
| 810 | canvas->drawImage(image, 128, 0); |
| 811 | canvas->drawImage(image, 0, 128); |
| 812 | canvas->drawImage(image, 128, 128); |
| 813 | SkPaint paint; |
| 814 | paint.setBlendMode(SkBlendMode::kDstATop); |
| 815 | SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT }; |
| 816 | SkPoint vert[] = { { 0, 0 }, { 0, 256 } }; |
| 817 | paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, SK_ARRAY_COUNT(alphas), |
| 818 | SkShader::kClamp_TileMode)); |
| 819 | canvas->drawPaint(paint); |
| 820 | canvas->clipRect( { 30, 30, 226, 226 } ); |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 821 | canvas->drawColor(0x80bb9977, SkBlendMode::kMultiply); |
| 822 | ## |
| 823 | ## |
| 824 | |
| 825 | #Subtopic Hue |
| 826 | #Line # hue of source with saturation and luminosity of destination ## |
Cary Clark | 2be81cf | 2018-09-13 12:04:30 -0400 | [diff] [blame] | 827 | Given: #Formula # Sa ## as source Alpha, #Formula # S ## as source Color, |
| 828 | #Formula # Da ## as destination Alpha, #Formula # D ## as destination Color; |
| 829 | SkBlendMode::kHue replaces destination with: |
| 830 | #Formula # [Sa + Da - Sa * Da, SetLuminosity(SetSaturation(S, Saturation(D)), Luminosity(D))] ##, |
| 831 | source hue, leaving destination luminosity and saturation unchanged. |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 832 | #Example |
Cary Clark | 53498e9 | 2018-06-28 19:13:56 -0400 | [diff] [blame] | 833 | #Image 3 |
Cary Clark | 09d80c0 | 2018-10-31 12:14:03 -0400 | [diff] [blame] | 834 | canvas->drawImage(image, 0, 0); |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 835 | canvas->drawColor(0xFF00FF00, SkBlendMode::kHue); |
| 836 | ## |
| 837 | ## |
| 838 | |
| 839 | #Subtopic Saturation |
| 840 | #Line # saturation of source with hue and luminosity of destination ## |
Cary Clark | 2be81cf | 2018-09-13 12:04:30 -0400 | [diff] [blame] | 841 | Given: #Formula # Sa ## as source Alpha, #Formula # S ## as source Color, |
| 842 | #Formula # Da ## as destination Alpha, #Formula # D ## as destination Color; |
| 843 | SkBlendMode::kHue replaces destination with: |
| 844 | #Formula # [Sa + Da - Sa * Da, SetLuminosity(SetSaturation(D, Saturation(S)), Luminosity(D))] ##, |
| 845 | source hue, leaving destination luminosity and saturation unchanged. |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 846 | #Example |
Cary Clark | 53498e9 | 2018-06-28 19:13:56 -0400 | [diff] [blame] | 847 | #Image 3 |
Cary Clark | 09d80c0 | 2018-10-31 12:14:03 -0400 | [diff] [blame] | 848 | canvas->drawImage(image, 0, 0); |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 849 | canvas->drawColor(0xFF00FF00, SkBlendMode::kSaturation); |
| 850 | ## |
| 851 | ## |
| 852 | |
| 853 | #Subtopic Color |
| 854 | #Line # hue and saturation of source with luminosity of destination ## |
Cary Clark | 2be81cf | 2018-09-13 12:04:30 -0400 | [diff] [blame] | 855 | Given: #Formula # Sa ## as source Alpha, #Formula # S ## as source Color, |
| 856 | #Formula # Da ## as destination Alpha, #Formula # D ## as destination Color; |
| 857 | SkBlendMode::kColor replaces destination with: |
| 858 | #Formula # [Sa + Da - Sa * Da, SetLuminosity(S, Luminosity(D))] ##, |
| 859 | source hue and saturation, leaving destination luminosity unchanged. |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 860 | #Example |
Cary Clark | 53498e9 | 2018-06-28 19:13:56 -0400 | [diff] [blame] | 861 | #Image 3 |
Cary Clark | 09d80c0 | 2018-10-31 12:14:03 -0400 | [diff] [blame] | 862 | canvas->drawImage(image, 0, 0); |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 863 | canvas->drawColor(0xFF00FF00, SkBlendMode::kColor); |
| 864 | ## |
| 865 | ## |
| 866 | |
| 867 | #Subtopic Luminosity |
| 868 | #Line # luminosity of source with hue and saturation of destination ## |
Cary Clark | 2be81cf | 2018-09-13 12:04:30 -0400 | [diff] [blame] | 869 | Given: #Formula # Sa ## as source Alpha, #Formula # S ## as source Color, |
| 870 | #Formula # Da ## as destination Alpha, #Formula # D ## as destination Color; |
| 871 | SkBlendMode::kLuminosity replaces destination with: |
| 872 | #Formula # [Sa + Da - Sa * Da, SetLuminosity(D, Luminosity(S))] ##, |
| 873 | source luminosity, leaving destination hue and saturation unchanged. |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 874 | #Example |
Cary Clark | 53498e9 | 2018-06-28 19:13:56 -0400 | [diff] [blame] | 875 | #Image 3 |
Cary Clark | 09d80c0 | 2018-10-31 12:14:03 -0400 | [diff] [blame] | 876 | canvas->drawImage(image, 0, 0); |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 877 | canvas->drawColor(0xFF00FF00, SkBlendMode::kLuminosity); |
| 878 | ## |
| 879 | ## |
| 880 | |
Cary Clark | 61313f3 | 2018-10-08 14:57:48 -0400 | [diff] [blame] | 881 | #EnumClass SkBlendMode ## |
| 882 | |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 883 | # ------------------------------------------------------------------------------ |
| 884 | |
Cary Clark | 09d80c0 | 2018-10-31 12:14:03 -0400 | [diff] [blame] | 885 | #Method const char* SkBlendMode_Name(SkBlendMode blendMode) |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 886 | #In Utility |
| 887 | #Line # returns mode as C string ## |
Cary Clark | 09d80c0 | 2018-10-31 12:14:03 -0400 | [diff] [blame] | 888 | #Populate |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 889 | |
| 890 | #Example |
Cary Clark | 09d80c0 | 2018-10-31 12:14:03 -0400 | [diff] [blame] | 891 | SkDebugf("default blend: SkBlendMode::k%s\n", SkBlendMode_Name(SkPaint().getBlendMode())); |
| 892 | #StdOut |
| 893 | default blend: SkBlendMode::kSrcOver |
| 894 | ## |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 895 | ## |
| 896 | |
| 897 | #SeeAlso SkBlendMode |
| 898 | |
| 899 | #Method ## |
| 900 | |
| 901 | #Topic Blend_Mode ## |