[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:
Florin Malita 2018-01-02 12:52:43 -05:00 committed by Skia Commit-Bot
parent efe9842af0
commit 2a8275b782

View File

@ -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;
}