SkBlendMode.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /*
  2. * Copyright 2017 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #include "src/core/SkBlendModePriv.h"
  8. #include "src/core/SkCoverageModePriv.h"
  9. #include "src/core/SkRasterPipeline.h"
  10. bool SkBlendMode_ShouldPreScaleCoverage(SkBlendMode mode, bool rgb_coverage) {
  11. // The most important things we do here are:
  12. // 1) never pre-scale with rgb coverage if the blend mode involves a source-alpha term;
  13. // 2) always pre-scale Plus.
  14. //
  15. // When we pre-scale with rgb coverage, we scale each of source r,g,b, with a distinct value,
  16. // and source alpha with one of those three values. This process destructively updates the
  17. // source-alpha term, so we can't evaluate blend modes that need its original value.
  18. //
  19. // Plus always requires pre-scaling as a specific quirk of its implementation in
  20. // SkRasterPipeline. This lets us put the clamp inside the blend mode itself rather
  21. // than as a separate stage that'd come after the lerp.
  22. //
  23. // This function is a finer-grained breakdown of SkBlendMode_SupportsCoverageAsAlpha().
  24. switch (mode) {
  25. case SkBlendMode::kDst: // d --> no sa term, ok!
  26. case SkBlendMode::kDstOver: // d + s*inv(da) --> no sa term, ok!
  27. case SkBlendMode::kPlus: // clamp(s+d) --> no sa term, ok!
  28. return true;
  29. case SkBlendMode::kDstOut: // d * inv(sa)
  30. case SkBlendMode::kSrcATop: // s*da + d*inv(sa)
  31. case SkBlendMode::kSrcOver: // s + d*inv(sa)
  32. case SkBlendMode::kXor: // s*inv(da) + d*inv(sa)
  33. return !rgb_coverage;
  34. default: break;
  35. }
  36. return false;
  37. }
  38. // Users of this function may want to switch to the rgb-coverage aware version above.
  39. bool SkBlendMode_SupportsCoverageAsAlpha(SkBlendMode mode) {
  40. return SkBlendMode_ShouldPreScaleCoverage(mode, false);
  41. }
  42. struct CoeffRec {
  43. SkBlendModeCoeff fSrc;
  44. SkBlendModeCoeff fDst;
  45. };
  46. const CoeffRec gCoeffs[] = {
  47. { SkBlendModeCoeff::kZero, SkBlendModeCoeff::kZero },
  48. { SkBlendModeCoeff::kOne, SkBlendModeCoeff::kZero },
  49. { SkBlendModeCoeff::kZero, SkBlendModeCoeff::kOne },
  50. { SkBlendModeCoeff::kOne, SkBlendModeCoeff::kISA },
  51. { SkBlendModeCoeff::kIDA, SkBlendModeCoeff::kOne },
  52. { SkBlendModeCoeff::kDA, SkBlendModeCoeff::kZero },
  53. { SkBlendModeCoeff::kZero, SkBlendModeCoeff::kSA },
  54. { SkBlendModeCoeff::kIDA, SkBlendModeCoeff::kZero },
  55. { SkBlendModeCoeff::kZero, SkBlendModeCoeff::kISA },
  56. { SkBlendModeCoeff::kDA, SkBlendModeCoeff::kISA },
  57. { SkBlendModeCoeff::kIDA, SkBlendModeCoeff::kSA },
  58. { SkBlendModeCoeff::kIDA, SkBlendModeCoeff::kISA },
  59. { SkBlendModeCoeff::kOne, SkBlendModeCoeff::kOne },
  60. { SkBlendModeCoeff::kZero, SkBlendModeCoeff::kSC },
  61. { SkBlendModeCoeff::kOne, SkBlendModeCoeff::kISC }, // screen
  62. };
  63. bool SkBlendMode_AsCoeff(SkBlendMode mode, SkBlendModeCoeff* src, SkBlendModeCoeff* dst) {
  64. if (mode > SkBlendMode::kScreen) {
  65. return false;
  66. }
  67. if (src) {
  68. *src = gCoeffs[static_cast<int>(mode)].fSrc;
  69. }
  70. if (dst) {
  71. *dst = gCoeffs[static_cast<int>(mode)].fDst;
  72. }
  73. return true;
  74. }
  75. void SkBlendMode_AppendStages(SkBlendMode mode, SkRasterPipeline* p) {
  76. auto stage = SkRasterPipeline::srcover;
  77. switch (mode) {
  78. case SkBlendMode::kClear: stage = SkRasterPipeline::clear; break;
  79. case SkBlendMode::kSrc: return; // This stage is a no-op.
  80. case SkBlendMode::kDst: stage = SkRasterPipeline::move_dst_src; break;
  81. case SkBlendMode::kSrcOver: stage = SkRasterPipeline::srcover; break;
  82. case SkBlendMode::kDstOver: stage = SkRasterPipeline::dstover; break;
  83. case SkBlendMode::kSrcIn: stage = SkRasterPipeline::srcin; break;
  84. case SkBlendMode::kDstIn: stage = SkRasterPipeline::dstin; break;
  85. case SkBlendMode::kSrcOut: stage = SkRasterPipeline::srcout; break;
  86. case SkBlendMode::kDstOut: stage = SkRasterPipeline::dstout; break;
  87. case SkBlendMode::kSrcATop: stage = SkRasterPipeline::srcatop; break;
  88. case SkBlendMode::kDstATop: stage = SkRasterPipeline::dstatop; break;
  89. case SkBlendMode::kXor: stage = SkRasterPipeline::xor_; break;
  90. case SkBlendMode::kPlus: stage = SkRasterPipeline::plus_; break;
  91. case SkBlendMode::kModulate: stage = SkRasterPipeline::modulate; break;
  92. case SkBlendMode::kScreen: stage = SkRasterPipeline::screen; break;
  93. case SkBlendMode::kOverlay: stage = SkRasterPipeline::overlay; break;
  94. case SkBlendMode::kDarken: stage = SkRasterPipeline::darken; break;
  95. case SkBlendMode::kLighten: stage = SkRasterPipeline::lighten; break;
  96. case SkBlendMode::kColorDodge: stage = SkRasterPipeline::colordodge; break;
  97. case SkBlendMode::kColorBurn: stage = SkRasterPipeline::colorburn; break;
  98. case SkBlendMode::kHardLight: stage = SkRasterPipeline::hardlight; break;
  99. case SkBlendMode::kSoftLight: stage = SkRasterPipeline::softlight; break;
  100. case SkBlendMode::kDifference: stage = SkRasterPipeline::difference; break;
  101. case SkBlendMode::kExclusion: stage = SkRasterPipeline::exclusion; break;
  102. case SkBlendMode::kMultiply: stage = SkRasterPipeline::multiply; break;
  103. case SkBlendMode::kHue: stage = SkRasterPipeline::hue; break;
  104. case SkBlendMode::kSaturation: stage = SkRasterPipeline::saturation; break;
  105. case SkBlendMode::kColor: stage = SkRasterPipeline::color; break;
  106. case SkBlendMode::kLuminosity: stage = SkRasterPipeline::luminosity; break;
  107. }
  108. p->append(stage);
  109. }
  110. SkPMColor4f SkBlendMode_Apply(SkBlendMode mode, const SkPMColor4f& src, const SkPMColor4f& dst) {
  111. // special-case simple/common modes...
  112. switch (mode) {
  113. case SkBlendMode::kClear: return SK_PMColor4fTRANSPARENT;
  114. case SkBlendMode::kSrc: return src;
  115. case SkBlendMode::kDst: return dst;
  116. case SkBlendMode::kSrcOver: {
  117. Sk4f r = Sk4f::Load(src.vec()) + Sk4f::Load(dst.vec()) * Sk4f(1 - src.fA);
  118. return { r[0], r[1], r[2], r[3] };
  119. }
  120. default:
  121. break;
  122. }
  123. SkRasterPipeline_<256> p;
  124. SkPMColor4f src_storage = src,
  125. dst_storage = dst,
  126. res_storage;
  127. SkRasterPipeline_MemoryCtx src_ctx = { &src_storage, 0 },
  128. dst_ctx = { &dst_storage, 0 },
  129. res_ctx = { &res_storage, 0 };
  130. p.append(SkRasterPipeline::load_f32, &dst_ctx);
  131. p.append(SkRasterPipeline::move_src_dst);
  132. p.append(SkRasterPipeline::load_f32, &src_ctx);
  133. SkBlendMode_AppendStages(mode, &p);
  134. p.append(SkRasterPipeline::store_f32, &res_ctx);
  135. p.run(0,0, 1,1);
  136. return res_storage;
  137. }
  138. ///////////////////////////////////////////////////////////////////////////////////////////////////
  139. const SkBlendMode gUncorrelatedCoverageToBlend[] = {
  140. SkBlendMode::kSrcOver, // or DstOver
  141. SkBlendMode::kSrcIn, // or kDstIn
  142. SkBlendMode::kSrcOut,
  143. SkBlendMode::kDstOut,
  144. SkBlendMode::kXor,
  145. };
  146. SkBlendMode SkUncorrelatedCoverageModeToBlendMode(SkCoverageMode cm) {
  147. unsigned index = static_cast<unsigned>(cm);
  148. SkASSERT(index < SK_ARRAY_COUNT(gUncorrelatedCoverageToBlend));
  149. return gUncorrelatedCoverageToBlend[index];
  150. }