[skotty] Improved shape & layer paint order
Closer to what I think the docs are trying to articulate. Change-Id: I784c4daaf3f6f2c70b2e9636c30a763ab0c711e7 Reviewed-on: https://skia-review.googlesource.com/90242 Reviewed-by: Mike Reed <reed@google.com> Commit-Queue: Florin Malita <fmalita@chromium.org>
This commit is contained in:
parent
efe9842af0
commit
2a8275b782
@ -292,11 +292,29 @@ sk_sp<sksg::RenderNode> AttachShape(const Json::Value& shapeArray, AttachContext
|
||||
if (!shapeArray.isArray())
|
||||
return nullptr;
|
||||
|
||||
// (https://helpx.adobe.com/after-effects/using/overview-shape-layers-paths-vector.html#groups_and_render_order_for_shapes_and_shape_attributes)
|
||||
//
|
||||
// Render order for shapes within a shape layer
|
||||
//
|
||||
// The rules for rendering a shape layer are similar to the rules for rendering a composition
|
||||
// that contains nested compositions:
|
||||
//
|
||||
// * Within a group, the shape at the bottom of the Timeline panel stacking order is rendered
|
||||
// first.
|
||||
//
|
||||
// * All path operations within a group are performed before paint operations. This means,
|
||||
// for example, that the stroke follows the distortions in the path made by the Wiggle Paths
|
||||
// path operation. Path operations within a group are performed from top to bottom.
|
||||
//
|
||||
// * Paint operations within a group are performed from the bottom to the top in the Timeline
|
||||
// panel stacking order. This means, for example, that a stroke is rendered on top of
|
||||
// (in front of) a stroke that appears after it in the Timeline panel.
|
||||
//
|
||||
sk_sp<sksg::Group> shape_group = sksg::Group::Make();
|
||||
sk_sp<sksg::RenderNode> xformed_group = shape_group;
|
||||
|
||||
SkSTArray<16, sk_sp<sksg::GeometryNode>, true> geos;
|
||||
SkSTArray<16, sk_sp<sksg::PaintNode> , true> paints;
|
||||
SkSTArray<16, sk_sp<sksg::RenderNode> , true> draws;
|
||||
|
||||
for (const auto& s : shapeArray) {
|
||||
const auto* info = FindShapeInfo(s);
|
||||
@ -315,30 +333,34 @@ sk_sp<sksg::RenderNode> AttachShape(const Json::Value& shapeArray, AttachContext
|
||||
case ShapeType::kPaint: {
|
||||
SkASSERT(info->fAttacherIndex < SK_ARRAY_COUNT(gPaintAttachers));
|
||||
if (auto paint = gPaintAttachers[info->fAttacherIndex](s, ctx)) {
|
||||
paints.push_back(std::move(paint));
|
||||
for (const auto& geo : geos) {
|
||||
draws.push_back(sksg::Draw::Make(geo, paint));
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case ShapeType::kGroup: {
|
||||
SkASSERT(info->fAttacherIndex < SK_ARRAY_COUNT(gGroupAttachers));
|
||||
if (auto group = gGroupAttachers[info->fAttacherIndex](s, ctx)) {
|
||||
shape_group->addChild(std::move(group));
|
||||
draws.push_back(std::move(group));
|
||||
}
|
||||
} break;
|
||||
case ShapeType::kTransform: {
|
||||
// TODO: BM appears to transform the grometry, not the draw op itself.
|
||||
// TODO: BM appears to transform the geometry, not the draw op itself.
|
||||
SkASSERT(info->fAttacherIndex < SK_ARRAY_COUNT(gTransformAttachers));
|
||||
xformed_group = gTransformAttachers[info->fAttacherIndex](s, ctx, xformed_group);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& geo : geos) {
|
||||
for (int i = paints.count() - 1; i >= 0; --i) {
|
||||
shape_group->addChild(sksg::Draw::Make(geo, paints[i]));
|
||||
}
|
||||
if (draws.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LOG("** Attached shape - geometries: %d, paints: %d\n", geos.count(), paints.count());
|
||||
for (int i = draws.count() - 1; i >= 0; --i) {
|
||||
shape_group->addChild(std::move(draws[i]));
|
||||
}
|
||||
|
||||
LOG("** Attached shape: %d draws.\n", draws.count());
|
||||
return xformed_group;
|
||||
}
|
||||
|
||||
@ -423,16 +445,27 @@ sk_sp<sksg::RenderNode> AttachComposition(const Json::Value& comp, AttachContext
|
||||
if (!comp.isObject())
|
||||
return nullptr;
|
||||
|
||||
LOG("** Attaching composition '%s'\n", ParseString(comp["id"], "").c_str());
|
||||
|
||||
auto comp_group = sksg::Group::Make();
|
||||
SkSTArray<16, sk_sp<sksg::RenderNode>, true> layers;
|
||||
|
||||
for (const auto& l : comp["layers"]) {
|
||||
if (auto layer_fragment = AttachLayer(l, ctx)) {
|
||||
comp_group->addChild(std::move(layer_fragment));
|
||||
layers.push_back(std::move(layer_fragment));
|
||||
}
|
||||
}
|
||||
|
||||
if (layers.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Layers are painted in bottom->top order.
|
||||
auto comp_group = sksg::Group::Make();
|
||||
for (int i = layers.count() - 1; i >= 0; --i) {
|
||||
comp_group->addChild(std::move(layers[i]));
|
||||
}
|
||||
|
||||
LOG("** Attached composition '%s': %d layers.\n",
|
||||
ParseString(comp["id"], "").c_str(), layers.count());
|
||||
|
||||
return comp_group;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user