Temp fix for gradients w/ alpha For now, premul color stops to remove sparkle/glitches in CG gradients w/ alpha. More complete fix will be investigated, but will likely be slower. Diffs= 4924b2aa8 Temp fix for gradients w/ alpha
diff --git a/.rive_head b/.rive_head index aa0c0ba..bc01f7a 100644 --- a/.rive_head +++ b/.rive_head
@@ -1 +1 @@ -4f4b7985889978f2ab8b8aa9315780cb2b0c76a7 +4924b2aa8422fee47aceceecaad16377bea39d01
diff --git a/skia/renderer/src/cg_factory.cpp b/skia/renderer/src/cg_factory.cpp index 6af4db9..5a8450e 100644 --- a/skia/renderer/src/cg_factory.cpp +++ b/skia/renderer/src/cg_factory.cpp
@@ -168,6 +168,7 @@ CGRenderPaint() {} bool isStroke() const { return m_isStroke; } + float opacity() const { return m_rgba[3]; } CGRenderShader* shader() const { return static_cast<CGRenderShader*>(m_shader.get()); } @@ -202,6 +203,19 @@ for (size_t i = 0; i < count; ++i) { convertColor(colors[i], &c[i * 4]); + + // Rive wants the colors to be premultiplied *after* interpolation + // Unfortunately, CG doesn't know about this option, it just does + // a straight interpolation and uses the result (thinking it is + // in premul form already). This can lead to artifacts in the drawing + // (e.g. sparkles) so as a hack, we premul our color stops up front. + // Not exactly correct, but does remove the sparkles. + // A better fix might be to write a custom Shading proc... but that + // is likely to be be slower (but need to try/time it to know for sure). + CGFloat* p = &c[i * 4]; + p[0] *= p[3]; + p[1] *= p[3]; + p[2] *= p[3]; } if (stops) { for (size_t i = 0; i < count; ++i) { @@ -302,11 +316,16 @@ } CGContextSaveGState(m_ctx); CGContextClip(m_ctx); + + // so the gradient modulates with the color's alpha + CGContextSetAlpha(m_ctx, cgpaint->opacity()); + sh->draw(m_ctx); CGContextRestoreGState(m_ctx); } else { CGContextDrawPath(m_ctx, cgpath->drawingMode(cgpaint->isStroke())); } + assert(CGContextIsPathEmpty(m_ctx)); } void CGRenderer::clipPath(RenderPath* path) {