Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 1 | #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 | |
| 16 | Describes how destination pixel is replaced with a combination of itself and |
| 17 | source pixel. Blend_Mode may use source, destination, or both. Blend_Mode may |
| 18 | operate on each Color component independently, or may allow all source pixel |
| 19 | components to contribute to one destination pixel component. |
| 20 | |
| 21 | Blend_Mode does not use adjacent pixels to determine the outcome. |
| 22 | |
| 23 | Blend_Mode uses source and read destination Alpha to determine written |
| 24 | destination Alpha; both source and destination Alpha may also affect written |
| 25 | destination Color components. |
| 26 | |
| 27 | Regardless of how Alpha is encoded in source and destination pixel, nearly all |
| 28 | Color_Types treat it as ranging from zero to one. And, nearly all Blend_Mode |
| 29 | algorithms limit the output so that all results are also zero to one. |
| 30 | |
| 31 | Two exceptions are SkBlendMode::kPlus and kRGBA_F16_SkColorType. |
| 32 | |
| 33 | SkBlendMode::kPlus permits computing Alpha and Color component values larger |
| 34 | than one. For Color_Types other than kRGBA_F16_SkColorType, resulting Alpha |
| 35 | and component values are clamped to one. |
| 36 | |
| 37 | kRGBA_F16_SkColorType permits values outside the zero to one range. It is up |
| 38 | to the client to ensure that the result is within the range of zero to one, |
| 39 | and therefore well-defined. |
| 40 | |
| 41 | #Subtopic Porter_Duff |
| 42 | |
| 43 | #A Compositing Digital Images # https://graphics.pixar.com/library/Compositing/paper.pdf ## |
| 44 | describes Porter_Duff modes SkBlendMode::kClear through SkBlendMode::kXor. |
| 45 | |
| 46 | Drawing a bitmap with transparency using Porter_Duff compositing is free to clear |
| 47 | the destination. |
| 48 | |
| 49 | #Illustration 1 |
| 50 | |
| 51 | Draw geometry with transparency using Porter_Duff compositing does not combine |
| 52 | transparent source pixels, leaving the destination outside the geometry untouched. |
| 53 | |
| 54 | #Illustration 2 |
| 55 | |
| 56 | ## |
| 57 | |
| 58 | #Subtopic Lighten_Darken |
| 59 | |
| 60 | Modes SkBlendMode::kPlus and SkBlendMode::kScreen use |
| 61 | simple arithmetic to lighten or darken the destination. Modes |
| 62 | SkBlendMode::kOverlay through SkBlendMode::kMultiply use more complicated |
| 63 | algorithms 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 |
| 72 | SkBlendMode::kModulate is a mashup of SkBlendMode::kSrcATop and SkBlendMode::kMultiply. |
| 73 | It multiplies all components, including Alpha; unlike SkBlendMode::kMultiply, if either |
| 74 | source or destination is transparent, result is transparent. SkBlendMode::kModulate |
| 75 | uses Premultiplied values to compute the product; SkBlendMode::kMultiply uses Unpremultiplied |
| 76 | values to compute the product. |
| 77 | |
| 78 | #Illustration |
| 79 | |
| 80 | ## |
| 81 | |
| 82 | #Subtopic Color_Blends |
| 83 | |
| 84 | Modes SkBlendMode::kHue, SkBlendMode::kSaturation, SkBlendMode::kColor, and |
| 85 | SkBlendMode::kLuminosity convert source and destination pixels using all |
| 86 | components 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 |
| 99 | SkBlendMode::kClear, SkBlendMode::kSrc, SkBlendMode::kDst, SkBlendMode::kSrcOver, |
| 100 | SkBlendMode::kDstOver, SkBlendMode::kSrcIn, SkBlendMode::kDstIn, |
| 101 | SkBlendMode::kSrcOut, SkBlendMode::kDstOut, SkBlendMode::kSrcATop, |
| 102 | SkBlendMode::kDstATop, SkBlendMode::kXor, SkBlendMode::kPlus, |
| 103 | SkBlendMode::kModulate, SkBlendMode::kScreen, SkBlendMode::kOverlay, |
| 104 | SkBlendMode::kDarken, SkBlendMode::kLighten, SkBlendMode::kColorDodge, |
| 105 | SkBlendMode::kColorBurn, SkBlendMode::kHardLight, SkBlendMode::kSoftLight, |
| 106 | SkBlendMode::kDifference, SkBlendMode::kExclusion, SkBlendMode::kMultiply, |
| 107 | SkBlendMode::kHue, SkBlendMode::kSaturation, SkBlendMode::kColor, |
| 108 | SkBlendMode::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 |
| 154 | Replaces destination with Alpha and Color components set to zero; |
| 155 | a fully transparent pixel. |
| 156 | ## |
| 157 | |
| 158 | #Const kSrc 1 |
| 159 | #Line # replaces destination ## |
| 160 | #Details Src |
| 161 | Replaces destination with source. Destination alpha and color component values |
| 162 | are ignored. |
| 163 | ## |
| 164 | |
| 165 | #Const kDst 2 |
| 166 | #Line # preserves destination ## |
| 167 | #Details Dst |
| 168 | Preserves destination, ignoring source. Drawing with Paint set to kDst has |
| 169 | no effect. |
| 170 | ## |
| 171 | |
| 172 | #Const kSrcOver 3 |
| 173 | #Line # source over destination ## |
| 174 | #Details Src_Over |
| 175 | Replaces destination with source blended with destination. If source is opaque, |
| 176 | replaces 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 |
| 182 | Replaces destination with destination blended with source. If destination is opaque, |
| 183 | has no effect. |
| 184 | ## |
| 185 | |
| 186 | #Const kSrcIn 5 |
| 187 | #Line # source trimmed inside destination ## |
| 188 | #Details Src_In |
| 189 | Replaces destination with source using destination opacity. |
| 190 | ## |
| 191 | |
| 192 | #Const kDstIn 6 |
| 193 | #Line # destination trimmed by source ## |
| 194 | #Details Dst_In |
| 195 | Scales destination opacity by source opacity. |
| 196 | ## |
| 197 | |
| 198 | #Const kSrcOut 7 |
| 199 | #Line # source trimmed outside destination ## |
| 200 | #Details Src_Out |
| 201 | Replaces destination with source using the inverse of destination opacity, |
| 202 | drawing source fully where destination opacity is zero. |
| 203 | ## |
| 204 | |
| 205 | #Const kDstOut 8 |
| 206 | #Line # destination trimmed outside source ## |
| 207 | #Details Dst_Out |
| 208 | Replaces destination opacity with inverse of source opacity. If source is |
| 209 | transparent, has no effect. |
| 210 | ## |
| 211 | |
| 212 | #Const kSrcATop 9 |
| 213 | #Line # source inside destination blended with destination ## |
| 214 | #Details Src_Atop |
| 215 | Blends 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 |
| 221 | Blends 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 |
| 227 | Blends destination by exchanging transparency of the source and destination. |
| 228 | ## |
| 229 | |
| 230 | #Const kPlus 12 |
| 231 | #Line # sum of colors ## |
| 232 | #Details Plus |
| 233 | Replaces destination with source and destination added together. |
| 234 | ## |
| 235 | |
| 236 | #Const kModulate 13 |
| 237 | #Line # product of Premultiplied colors; darkens destination ## |
| 238 | #Details Modulate |
| 239 | Replaces 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 |
| 245 | Replaces 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 |
| 255 | Replaces destination with multiply or screen, depending on destination. |
| 256 | ## |
| 257 | |
| 258 | #Const kDarken 16 |
| 259 | #Line # darker of source and destination ## |
| 260 | #Details Darken |
| 261 | Replaces destination with darker of source and destination. |
| 262 | ## |
| 263 | |
| 264 | #Const kLighten 17 |
| 265 | #Line # lighter of source and destination ## |
| 266 | #Details Lighten |
| 267 | Replaces destination with lighter of source and destination. |
| 268 | ## |
| 269 | |
| 270 | #Const kColorDodge 18 |
| 271 | #Line # brighten destination to reflect source ## |
| 272 | #Details Color_Dodge |
| 273 | Makes destination brighter to reflect source. |
| 274 | ## |
| 275 | |
| 276 | #Const kColorBurn 19 |
| 277 | #Line # darken destination to reflect source ## |
| 278 | #Details Color_Burn |
| 279 | Makes destination darker to reflect source. |
| 280 | ## |
| 281 | |
| 282 | #Const kHardLight 20 |
| 283 | #Line # multiply or screen, depending on source ## |
| 284 | #Details Hard_Light |
| 285 | Makes 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 |
| 291 | Makes 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 |
| 297 | Subtracts darker from lighter with higher contrast. |
| 298 | ## |
| 299 | |
| 300 | #Const kExclusion 23 |
| 301 | #Line # subtract darker from lighter with lower contrast ## |
| 302 | #Details Exclusion |
| 303 | Subtracts darker from lighter with lower contrast. |
| 304 | ## |
| 305 | |
| 306 | #Const kMultiply 24 |
| 307 | #Line # multiply source with destination, darkening image ## |
| 308 | #Details Multiply |
| 309 | Multiplies source with destination, darkening image. |
| 310 | ## |
| 311 | |
| 312 | #Const kLastSeparableMode 24 |
| 313 | #Line # last blend mode operating separately on components ## |
| 314 | Last 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 |
| 320 | Replaces hue of destination with hue of source, leaving saturation and luminosity |
| 321 | unchanged. |
| 322 | ## |
| 323 | |
| 324 | #Const kSaturation 26 |
| 325 | #Line # saturation of source with hue and luminosity of destination ## |
| 326 | #Details Saturation |
| 327 | Replaces saturation of destination saturation hue of source, leaving hue and |
| 328 | luminosity unchanged. |
| 329 | ## |
| 330 | |
| 331 | #Const kColor 27 |
| 332 | #Line # hue and saturation of source with luminosity of destination ## |
| 333 | #Details Color |
| 334 | Replaces hue and saturation of destination with hue and saturation of source, |
| 335 | leaving luminosity unchanged. |
| 336 | ## |
| 337 | |
| 338 | #Const kLuminosity 28 |
| 339 | #Line # luminosity of source with hue and saturation of destination ## |
| 340 | #Details Luminosity |
| 341 | Replaces luminosity of destination with luminosity of source, leaving hue and |
| 342 | saturation unchanged. |
| 343 | ## |
| 344 | |
| 345 | #Const kLastMode 28 |
| 346 | #Line # last valid value ## |
| 347 | Used 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 ## |
| 359 | SkBlendMode::kClear sets destination to: |
| 360 | #Formula |
| 361 | [0, 0] |
| 362 | ## |
| 363 | . Use SkBlendMode::kClear to initialize a buffer to fully transparent pixels when |
| 364 | creating a mask with irregular edges. |
| 365 | |
| 366 | #Example |
| 367 | #Description |
| 368 | SK_ColorYELLOW is ignored because SkBlendMode::kClear ignores the source pixel |
| 369 | value 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 ## |
| 388 | Given: |
| 389 | #Formula |
| 390 | Sa 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, |
| 397 | regardless of source and destination Alpha values. As a parameter to |
| 398 | SkCanvas::drawAtlas, selects sprites and ignores colors. |
| 399 | #Example |
| 400 | #Image 3 |
| 401 | #Description |
| 402 | SkBlendMode::kSrc does not blend transparent pixels with existing background; |
| 403 | it 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 ## |
| 421 | Given: |
| 422 | #Formula |
| 423 | Da 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 |
| 430 | Paint to have no effect. As a parameter to SkCanvas::drawAtlas, |
| 431 | selects 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 ## |
| 445 | Given: |
| 446 | #Formula |
| 447 | Sa as source Alpha, Sc as source Color component, |
| 448 | Da 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 | |
| 456 | SkBlendMode::kSrcOver cannot make destination more transparent; the result will |
| 457 | be 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 ## |
| 478 | Given: |
| 479 | #Formula |
| 480 | Sa as source Alpha, Sc as source Color component, |
| 481 | Da 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 ## |
| 508 | Given: |
| 509 | #Formula |
| 510 | Sa 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 ## |
| 537 | Given: |
| 538 | #Formula |
| 539 | Sa 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 |
| 546 | destination 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 ## |
| 567 | Given: |
| 568 | #Formula |
| 569 | Sa 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 |
| 576 | is 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 ## |
| 597 | Given: |
| 598 | #Formula |
| 599 | Sa 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 |
| 606 | destination is visible where source is transparent. If source is transparent, |
| 607 | has 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 ## |
| 628 | Given: |
| 629 | #Formula |
| 630 | Sa as source Alpha, Sc as source Color component, |
| 631 | Da 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 |
| 638 | is 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 ## |
| 659 | Given: |
| 660 | #Formula |
| 661 | Sa as source Alpha, Sc as source Color component, |
| 662 | Da 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 ## |
| 689 | Given: |
| 690 | #Formula |
| 691 | Sa as source Alpha, Sc as source Color component, |
| 692 | Da 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 ## |
| 715 | Given: |
| 716 | #Formula |
| 717 | Sa as source Alpha, Sc as source Color component, |
| 718 | Da 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 ## |
| 742 | Given: |
| 743 | #Formula |
| 744 | Sa as source Alpha, Sc as source Color component, |
| 745 | Da 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. |
| 752 | SkBlendMode::kModulate differs from SkBlendMode::kMultiply in two ways. |
| 753 | SkBlendMode::kModulate like SkBlendMode::kSrcATop alters the destination inside |
Cary Clark | 80247e5 | 2018-07-11 16:18:41 -0400 | [diff] [blame] | 754 | 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] | 755 | soft clip. SkBlendMode::kMultiply like SkBlendMode::kSrcOver can alter the |
| 756 | destination where the destination is transparent. |
| 757 | SkBlendMode::kModulate computes the product of the source and destination using |
| 758 | Premultiplied component values. SkBlendMode::kMultiply the product of the source |
| 759 | and 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 ## |
| 790 | Given: |
| 791 | #Formula |
| 792 | Sa as source Alpha, Sc as source Color component, |
| 793 | Da 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 ## |
| 820 | Given: |
| 821 | #Formula |
| 822 | Sa as source Alpha, Sc as source Color component, |
| 823 | Da 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 ## |
| 851 | Given: |
| 852 | #Formula |
| 853 | Sa as source Alpha, Sc as source Color component, |
| 854 | Da 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 |
| 861 | component with source if source is darker. |
| 862 | #Example |
Cary Clark | 53498e9 | 2018-06-28 19:13:56 -0400 | [diff] [blame] | 863 | #Image 3 |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 864 | 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 ## |
| 877 | Given: |
| 878 | #Formula |
| 879 | Sa as source Alpha, Sc as source Color component, |
| 880 | Da 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 |
| 887 | component with source if source is lighter. |
| 888 | #Example |
Cary Clark | 53498e9 | 2018-06-28 19:13:56 -0400 | [diff] [blame] | 889 | #Image 3 |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 890 | 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 ## |
| 903 | Given: |
| 904 | #Formula |
| 905 | Sa as source Alpha, Sc as source Color component, |
| 906 | Da 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 ## |
| 924 | Given: |
| 925 | #Formula |
| 926 | Sa as source Alpha, Sc as source Color component, |
| 927 | Da 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 ## |
| 945 | Given: |
| 946 | #Formula |
| 947 | Sa as source Alpha, Sc as source Color component, |
| 948 | Da 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 ## |
| 971 | Given: |
| 972 | #Formula |
| 973 | Sa as source Alpha, Sc as source Color component, |
| 974 | Da as destination Alpha, Dc as destination Color component |
| 975 | where 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 ## |
| 998 | Given: |
| 999 | #Formula |
| 1000 | Sa as source Alpha, Sc as source Color component, |
| 1001 | Da 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 ## |
| 1028 | Given: |
| 1029 | #Formula |
| 1030 | Sa as source Alpha, Sc as source Color, |
| 1031 | Da 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 ## |
| 1058 | Given: |
| 1059 | #Formula |
| 1060 | Sa as source Alpha, Sc as source Color component, |
| 1061 | Da 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. |
| 1068 | SkBlendMode::kMultiply makes the image darker. |
| 1069 | #Example |
Cary Clark | 53498e9 | 2018-06-28 19:13:56 -0400 | [diff] [blame] | 1070 | #Image 5 |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 1071 | 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 ## |
| 1089 | Given: |
| 1090 | #Formula |
| 1091 | Sa as source Alpha, S as source Color, |
| 1092 | Da 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 Clark | 53498e9 | 2018-06-28 19:13:56 -0400 | [diff] [blame] | 1100 | #Image 3 |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 1101 | canvas->drawImage(image, 0, 0);
|
| 1102 | canvas->drawColor(0xFF00FF00, SkBlendMode::kHue); |
| 1103 | ## |
| 1104 | ## |
| 1105 | |
| 1106 | #Subtopic Saturation |
| 1107 | #Line # saturation of source with hue and luminosity of destination ## |
| 1108 | Given: |
| 1109 | #Formula |
| 1110 | Sa as source Alpha, S as source Color, |
| 1111 | Da 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 Clark | 53498e9 | 2018-06-28 19:13:56 -0400 | [diff] [blame] | 1119 | #Image 3 |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 1120 | canvas->drawImage(image, 0, 0);
|
| 1121 | canvas->drawColor(0xFF00FF00, SkBlendMode::kSaturation); |
| 1122 | ## |
| 1123 | ## |
| 1124 | |
| 1125 | #Subtopic Color |
| 1126 | #Line # hue and saturation of source with luminosity of destination ## |
| 1127 | Given: |
| 1128 | #Formula |
| 1129 | Sa as source Alpha, S as source Color, |
| 1130 | Da 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 Clark | 53498e9 | 2018-06-28 19:13:56 -0400 | [diff] [blame] | 1138 | #Image 3 |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 1139 | canvas->drawImage(image, 0, 0);
|
| 1140 | canvas->drawColor(0xFF00FF00, SkBlendMode::kColor); |
| 1141 | ## |
| 1142 | ## |
| 1143 | |
| 1144 | #Subtopic Luminosity |
| 1145 | #Line # luminosity of source with hue and saturation of destination ## |
| 1146 | Given: |
| 1147 | #Formula |
| 1148 | Sa as source Alpha, S as source Color, |
| 1149 | Da 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 Clark | 53498e9 | 2018-06-28 19:13:56 -0400 | [diff] [blame] | 1157 | #Image 3 |
Cary Clark | 224c700 | 2018-06-27 11:00:21 -0400 | [diff] [blame] | 1158 | canvas->drawImage(image, 0, 0);
|
| 1159 | canvas->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 | |
| 1169 | Returns 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 |
| 1177 | SkDebugf("default blend: SkBlendMode::k%s\n", SkBlendMode_Name(SkPaint().getBlendMode()));
|
| 1178 | #StdOut
|
| 1179 | default blend: SkBlendMode::kSrcOver
|
| 1180 | ##
|
| 1181 | ## |
| 1182 | |
| 1183 | #SeeAlso SkBlendMode |
| 1184 | |
| 1185 | #Method ## |
| 1186 | |
| 1187 | #Topic Blend_Mode ## |