how to correctly render nested saveLayer groups (opacity + blendMode)

30 views
Skip to first unread message

Thomas Guittonneau

unread,
Oct 24, 2025, 8:19:02 AM (9 days ago) Oct 24
to skia-discuss

Hi everyone,

I'm trying to replicate a small React Native Skia scene using C++ and Skia directly.
In React Native Skia, I can easily nest <Group> elements with opacity and blendMode, and they seem to composite over the entire canvas (like in Photoshop).

Here’s the React Native Skia code I'm trying to reproduce:
import { Canvas, Circle, Group } from "@shopify/react-native-skia";

export default function App() {
  return (
    <Canvas style={{ flex: 1 }}>
      <Circle cx={128} cy={160} r={128} color="lightblue" />
      <Group opacity={0.8}>
        <Circle cx={64} cy={64} r={64} color="red" />
        <Group blendMode="multiply">
          <Circle cx={160} cy={96} r={96} color="lightgray" />
        </Group>
      </Group>
    </Canvas>
  );
}
And here’s my current C++ version: https://fiddle.skia.org/c/0639d69ea8e19156b7a9d452d896dcb5 void draw(SkCanvas* canvas) {

    SkPaint p;
    p.setAntiAlias(true);
    p.setStyle(SkPaint::kFill_Style);
    p.setColor(0xFFADD8E6); // lightblue
    canvas->drawCircle(128, 160, 128, p);

    // parent group with opacity 0.8
    SkPaint parentPaint;
    parentPaint.setAlphaf(0.8f);
    canvas->saveLayer(nullptr, &parentPaint);

    // red circle
    p.setColor(SK_ColorRED);
    canvas->drawCircle(64, 64, 64, p);

    // nested group with blend mode multiply
    SkPaint blendPaint;
    blendPaint.setBlendMode(SkBlendMode::kMultiply);
    canvas->saveLayer(nullptr, &blendPaint);

    // lightgray circle
    p.setColor(0xFFD3D3D3); // lightgray
    canvas->drawCircle(160, 96, 96, p);

    canvas->restore(); // nested group (apply multiply)
    canvas->restore(); // parent group (apply alpha)
}
The issue is that the blending and opacity results don’t quite match what I get in React Native Skia.
It looks like each layer only composites only over the previous layer, instead of over the entire canvas.

Questions:
How can I make nested saveLayer groups composite over the full canvas (like Photoshop or React Native Skia)?
Is there a recommended way to simulate “groups” with blendMode and opacity applied together in native Skia?
Is this related to backdrop management, or am I misunderstanding how saveLayer works internally?
Any insight would be appreciated!
Thanks, Thomas Guittonneau

thom...@google.com

unread,
Oct 24, 2025, 10:04:16 AM (9 days ago) Oct 24
to skia-discuss
Try this:
```
void draw(SkCanvas* canvas) {
    SkPaint multiplyPaint;
    multiplyPaint.setBlendMode(SkBlendMode::kMultiply);

  // lightblue circle

    SkPaint p;
    p.setAntiAlias(true);
    p.setStyle(SkPaint::kFill_Style);
    p.setColor(0xFFADD8E6); // lightblue
    canvas->drawCircle(128, 160, 128, p);
    canvas->saveLayer(nullptr, &multiplyPaint);

 
  p.setColor(SK_ColorRED);
    canvas->drawCircle(64, 64, 64, p);
    canvas->restore();
    canvas->saveLayer(nullptr, &multiplyPaint);

 
    p.setColor(0xFFD3D3D3); // lightgray
    canvas->drawCircle(160, 96, 96, p);
    canvas->restore();
}
```
Reply all
Reply to author
Forward
0 new messages