diff options
Diffstat (limited to 'src/effects/gradients/SkSweepGradient.cpp')
-rw-r--r-- | src/effects/gradients/SkSweepGradient.cpp | 146 |
1 files changed, 4 insertions, 142 deletions
diff --git a/src/effects/gradients/SkSweepGradient.cpp b/src/effects/gradients/SkSweepGradient.cpp index 81fdfe481b..b3a24cd16e 100644 --- a/src/effects/gradients/SkSweepGradient.cpp +++ b/src/effects/gradients/SkSweepGradient.cpp @@ -311,150 +311,12 @@ void SkSweepGradient::toString(SkString* str) const { str->append(")"); } -bool SkSweepGradient::onAppendStages(SkRasterPipeline* p, - SkColorSpace* dstCS, - SkArenaAlloc* alloc, - const SkMatrix& ctm, - const SkPaint& paint, - const SkMatrix* localM) const { - // Local matrix not supported currently. Remove once we have a generic RP wrapper. - if (localM || !getLocalMatrix().isIdentity()) { - return false; - } - - SkMatrix dstToSrc; - if (!ctm.invert(&dstToSrc)) { - return false; - } - - const auto dstToCenter = SkMatrix::Concat( - SkMatrix::MakeTrans(-fCenter.fX, -fCenter.fY), dstToSrc); - - auto* m = alloc->makeArrayDefault<float>(9); - if (dstToCenter.asAffine(m)) { - // TODO: mapping y is not needed; split the matrix stages to save some math? - p->append(SkRasterPipeline::matrix_2x3, m); - } else { - dstToCenter.get9(m); - p->append(SkRasterPipeline::matrix_perspective, m); - } - +bool SkSweepGradient::adjustMatrixAndAppendStages(SkArenaAlloc* alloc, + SkMatrix* matrix, + SkRasterPipeline* p) const { + matrix->postTranslate(-fCenter.fX, -fCenter.fY); p->append(SkRasterPipeline::xy_to_polar_unit); - const bool premulGrad = fGradFlags & SkGradientShader::kInterpolateColorsInPremul_Flag; - auto prepareColor = [premulGrad, dstCS, this](int i) { - SkColor4f c = dstCS ? to_colorspace(fOrigColors4f[i], fColorSpace.get(), dstCS) - : SkColor4f_from_SkColor(fOrigColors[i], nullptr); - return premulGrad ? c.premul() - : SkPM4f::From4f(Sk4f::Load(&c)); - }; - - // The two-stop case with stops at 0 and 1. - if (fColorCount == 2 && fOrigPos == nullptr) { - const SkPM4f c_l = prepareColor(0), - c_r = prepareColor(1); - - // See F and B below. - auto* f_and_b = alloc->makeArrayDefault<SkPM4f>(2); - f_and_b[0] = SkPM4f::From4f(c_r.to4f() - c_l.to4f()); - f_and_b[1] = c_l; - - p->append(SkRasterPipeline::linear_gradient_2stops, f_and_b); - } else { - - struct Stop { float t; SkPM4f f, b; }; - struct Ctx { size_t n; Stop* stops; SkPM4f start; }; - - auto* ctx = alloc->make<Ctx>(); - ctx->start = prepareColor(0); - - // For each stop we calculate a bias B and a scale factor F, such that - // for any t between stops n and n+1, the color we want is B[n] + F[n]*t. - auto init_stop = [](float t_l, float t_r, SkPM4f c_l, SkPM4f c_r, Stop *stop) { - auto F = SkPM4f::From4f((c_r.to4f() - c_l.to4f()) / (t_r - t_l)); - auto B = SkPM4f::From4f(c_l.to4f() - (F.to4f() * t_l)); - *stop = {t_l, F, B}; - }; - - if (fOrigPos == nullptr) { - // Handle evenly distributed stops. - - float dt = 1.0f / (fColorCount - 1); - // In the evenly distributed case, fColorCount is the number of stops. There are no - // dummy entries. - auto* stopsArray = alloc->makeArrayDefault<Stop>(fColorCount); - - float t_l = 0; - SkPM4f c_l = ctx->start; - for (int i = 0; i < fColorCount - 1; i++) { - // Use multiply instead of accumulating error using repeated addition. - float t_r = (i + 1) * dt; - SkPM4f c_r = prepareColor(i + 1); - init_stop(t_l, t_r, c_l, c_r, &stopsArray[i]); - - t_l = t_r; - c_l = c_r; - } - - // Force the last stop. - stopsArray[fColorCount - 1].t = 1; - stopsArray[fColorCount - 1].f = SkPM4f::From4f(Sk4f{0}); - stopsArray[fColorCount - 1].b = prepareColor(fColorCount - 1); - - ctx->n = fColorCount; - ctx->stops = stopsArray; - } else { - // Handle arbitrary stops. - - // Remove the dummy stops inserted by SkGradientShaderBase::SkGradientShaderBase - // because they are naturally handled by the search method. - int firstStop; - int lastStop; - if (fColorCount > 2) { - firstStop = fOrigColors4f[0] != fOrigColors4f[1] ? 0 : 1; - lastStop = fOrigColors4f[fColorCount - 2] != fOrigColors4f[fColorCount - 1] - ? fColorCount - 1 : fColorCount - 2; - } else { - firstStop = 0; - lastStop = 1; - } - int realCount = lastStop - firstStop + 1; - - // This is the maximum number of stops. There may be fewer stops because the duplicate - // points of hard stops are removed. - auto* stopsArray = alloc->makeArrayDefault<Stop>(realCount); - - size_t stopCount = 0; - float t_l = fOrigPos[firstStop]; - SkPM4f c_l = prepareColor(firstStop); - // N.B. lastStop is the index of the last stop, not one after. - for (int i = firstStop; i < lastStop; i++) { - float t_r = fOrigPos[i + 1]; - SkPM4f c_r = prepareColor(i + 1); - if (t_l < t_r) { - init_stop(t_l, t_r, c_l, c_r, &stopsArray[stopCount]); - stopCount += 1; - } - t_l = t_r; - c_l = c_r; - } - - stopsArray[stopCount].t = fOrigPos[lastStop]; - stopsArray[stopCount].f = SkPM4f::From4f(Sk4f{0}); - stopsArray[stopCount].b = prepareColor(lastStop); - stopCount += 1; - - ctx->n = stopCount; - ctx->stops = stopsArray; - } - - p->append(SkRasterPipeline::linear_gradient, ctx); - } - - if (!premulGrad && !this->colorsAreOpaque()) { - p->append(SkRasterPipeline::premul); - } - return true; } |