| /* |
| * Copyright 2018 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| // This top-level effect implements clamping on the layout coordinate and requires specifying the |
| // border colors that are used when outside the clamped boundary. Gradients with the |
| // SkShader::kClamp_TileMode should use the colors at their first and last stop (after adding |
| // default stops for t=0,t=1) as the border color. This will automatically replicate the edge color, |
| // even if when there is a hard stop. |
| // |
| // The SkShader::kDecal_TileMode can be produced by specifying transparent black as the border |
| // colors, regardless of the gradient's stop colors. |
| |
| in fragmentProcessor colorizer; |
| in fragmentProcessor gradLayout; |
| |
| layout(ctype=SkPMColor4f) in uniform half4 leftBorderColor; // t < 0.0 |
| layout(ctype=SkPMColor4f) in uniform half4 rightBorderColor; // t > 1.0 |
| |
| layout(key) in bool makePremul; |
| // Trust the creator that this matches the color spec of the gradient |
| in bool colorsAreOpaque; |
| layout(key) in bool layoutPreservesOpacity; |
| |
| half4 main() { |
| half4 t = sample(gradLayout); |
| half4 outColor; |
| |
| // If t.x is below 0, use the left border color without invoking the child processor. If any t.x |
| // is above 1, use the right border color. Otherwise, t is in the [0, 1] range assumed by the |
| // colorizer FP, so delegate to the child processor. |
| if (!layoutPreservesOpacity && t.y < 0) { |
| // layout has rejected this fragment (rely on sksl to remove this branch if the layout FP |
| // preserves opacity is false) |
| outColor = half4(0); |
| } else if (t.x < 0) { |
| outColor = leftBorderColor; |
| } else if (t.x > 1.0) { |
| outColor = rightBorderColor; |
| } else { |
| // Always sample from (x, 0), discarding y, since the layout FP can use y as a side-channel. |
| outColor = sample(colorizer, t.x0); |
| } |
| @if (makePremul) { |
| outColor.rgb *= outColor.a; |
| } |
| return outColor; |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| // If the layout does not preserve opacity, remove the opaque optimization, |
| // but otherwise respect the provided color opacity state (which should take |
| // into account the opacity of the border colors). |
| @optimizationFlags { |
| kCompatibleWithCoverageAsAlpha_OptimizationFlag | |
| (colorsAreOpaque && layoutPreservesOpacity ? kPreservesOpaqueInput_OptimizationFlag |
| : kNone_OptimizationFlags) |
| } |
| |
| @make{ |
| static std::unique_ptr<GrFragmentProcessor> Make( |
| std::unique_ptr<GrFragmentProcessor> colorizer, |
| std::unique_ptr<GrFragmentProcessor> gradLayout, |
| SkPMColor4f leftBorderColor, |
| SkPMColor4f rightBorderColor, |
| bool makePremul, |
| bool colorsAreOpaque) { |
| bool layoutPreservesOpacity = gradLayout->preservesOpaqueInput(); |
| return std::unique_ptr<GrFragmentProcessor>(new GrClampedGradientEffect( |
| std::move(colorizer), std::move(gradLayout), leftBorderColor, rightBorderColor, |
| makePremul, colorsAreOpaque, layoutPreservesOpacity)); |
| } |
| } |