aboutsummaryrefslogtreecommitdiffhomepage
path: root/experimental
diff options
context:
space:
mode:
authorGravatar Florin Malita <fmalita@chromium.org>2018-01-02 12:52:43 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-01-02 18:14:31 +0000
commit2a8275b7825e61c3bed5b1e86c3d70408d9ccf3a (patch)
treeb78b7b52e76572268aca4df519c505f5b937eb07 /experimental
parentefe9842af0a9ef0564ae45e288bd821620de7dc2 (diff)
[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>
Diffstat (limited to 'experimental')
-rw-r--r--experimental/skotty/Skotty.cpp59
1 files changed, 46 insertions, 13 deletions
diff --git a/experimental/skotty/Skotty.cpp b/experimental/skotty/Skotty.cpp
index b94cad243b..f2006bac0b 100644
--- a/experimental/skotty/Skotty.cpp
+++ b/experimental/skotty/Skotty.cpp
@@ -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;
+ }
+
+ for (int i = draws.count() - 1; i >= 0; --i) {
+ shape_group->addChild(std::move(draws[i]));
}
- LOG("** Attached shape - geometries: %d, paints: %d\n", geos.count(), paints.count());
+ 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;
}