aboutsummaryrefslogtreecommitdiffhomepage
path: root/experimental
Commit message (Collapse)AuthorAge
...
* [skotty] Animator scrubbingGravatar Florin Malita2018-01-09
| | | | | | | | | | Less boilerplate, less template bloat. TBR= Change-Id: Ie0ef4808f4bcd8af9b6cdf89732d214311bc6101 Reviewed-on: https://skia-review.googlesource.com/92701 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
* [skotty] Pass animation frame/time as floatGravatar Florin Malita2018-01-09
| | | | | | | | | | No reason to punt through SkMSec, we just lose precision. TBR= Change-Id: I2f61e49658701a3b5a675f3dd44543fd9aa98708 Reviewed-on: https://skia-review.googlesource.com/92600 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
* [skotty] Layer in/out supportGravatar Florin Malita2018-01-09
| | | | | | | | TBR= Change-Id: I79a9f5f15c051fc2d08bc2d6788ff059ec2d36f0 Reviewed-on: https://skia-review.googlesource.com/92460 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
* [skotty] Animator cleanup passGravatar Florin Malita2018-01-09
| | | | | | | | TBR= Change-Id: I2849c1438a8b245f04a01977919b653f0a16492b Reviewed-on: https://skia-review.googlesource.com/92380 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
* [skotty] Initial opacity supportGravatar Florin Malita2018-01-08
| | | | | | | | | TBR= Change-Id: I62581d3a7a83af5ccf373f0f4edf66a2d7f06f07 Reviewed-on: https://skia-review.googlesource.com/92223 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
* [skotty] Tag animating paths as volatileGravatar Florin Malita2018-01-08
| | | | | | | Change-Id: Ib90634ef682dba49b99594b008a0615d04c61a49 Reviewed-on: https://skia-review.googlesource.com/92140 Reviewed-by: Chris Dalton <csmartdalton@google.com> Commit-Queue: Florin Malita <fmalita@chromium.org>
* move largest apis into privateGravatar Mike Reed2018-01-08
| | | | | | | | | Related to https://skia-review.googlesource.com/c/skia/+/91860 Bug: skia: Change-Id: Ia8fd981b422bbab75541b078277d2e09e1fc9d41 Reviewed-on: https://skia-review.googlesource.com/91940 Reviewed-by: Brian Salomon <bsalomon@google.com>
* [skotty,sksg] Initial image supportGravatar Florin Malita2018-01-08
| | | | | | | | TBR= Change-Id: Ib3c918b1d746e4f190ae05708681f2d5519afdb2 Reviewed-on: https://skia-review.googlesource.com/91980 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
* [skotty] More flexible property parsingGravatar Florin Malita2018-01-08
| | | | | | | | | | | Older Json versions don't tag properties wih an "a" animation marker, but appear to instead rely on a try-and-see-what-sticks approach. TBR= Change-Id: I8a3a7e43576c590aa5ac168891574ceb4811ad49 Reviewed-on: https://skia-review.googlesource.com/91861 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
* add skotty-dir slideGravatar Mike Reed2018-01-08
| | | | | | | | | | Shows a directory of skotties in a grid Bug: skia: Change-Id: I96b0700d8809c94a394cf517222123967afb20dc Reviewed-on: https://skia-review.googlesource.com/91407 Commit-Queue: Mike Reed <reed@google.com> Reviewed-by: Florin Malita <fmalita@chromium.org>
* [skotty,sksg] Initial trim path effectGravatar Florin Malita2018-01-07
| | | | | | | | TBR= Change-Id: I5b612c5aade23f727a3622daeff2534f68e6b66a Reviewed-on: https://skia-review.googlesource.com/91404 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
* [skotty] De-templatize the Animator apply functionGravatar Florin Malita2018-01-07
| | | | | | | | | | We can use a raw function pointer. TBR= Change-Id: I66d19ed563171dc314c862b35c3c98d462337f18 Reviewed-on: https://skia-review.googlesource.com/91461 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
* [skotty] Cubic Bezier lerpGravatar Florin Malita2018-01-05
| | | | | | | | Change-Id: I7eda67fb89c1ef54f4bc1470d10ee5ab797a8b6e Reviewed-on: https://skia-review.googlesource.com/91445 Reviewed-by: Mike Reed <reed@google.com> Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
* [sksg] More inval fixesGravatar Florin Malita2018-01-05
| | | | | | | | | | | | | | | | | | | | | | | | Backpedal on node/reval-time-determined damage: nodes cannot control the invalidation order, and shared descendants may be revalidated before a particular ancestor gets to query their state - thus making any decisions based on that invalid. Instead, apply damage suppression at invalidation time, based on node type/traits. Node types which don't generate direct damage are marked as such, and the invalidation logic bubbles damage past them, until it finds a valid damage receiver. Nodes which currently suppress damage: - PaintNode (and subclasses) - GeometryNode (and subclasses) - Matrix TBR= Change-Id: I843e683e64cb6253d8c26d8397c44d02a7d6026f Reviewed-on: https://skia-review.googlesource.com/91421 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
* Enable conditional-uninitialized flagGravatar Kevin Lubick2018-01-05
| | | | | | | | | Bug: skia:7462 Cq-Include-Trybots: skia.primary:Test-Debian9-Clang-GCE-CPU-AVX2-x86_64-Release-All-SKNX_NO_SIMD Change-Id: I1c0a09984bf28a5c620a89af56040f018bae6310 Reviewed-on: https://skia-review.googlesource.com/90941 Commit-Queue: Kevin Lubick <kjlubick@google.com> Reviewed-by: Mike Klein <mtklein@chromium.org>
* [skotty, sksg] Add layer transform inheritance supportGravatar Florin Malita2018-01-05
| | | | | | | | | | | | | | | | | Split the matrix component of sksg::Transform into its own, free-floating, chainable node. Update the composite transform animator to target matrix nodes instead of transform nodes. Update the layer transform attachment logic to follow "parent" references, and build matrix inheritance chains on the fly. TBR= Change-Id: I017e5e462274c2cc210730e057b3ea2e7de5c0cb Reviewed-on: https://skia-review.googlesource.com/90803 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
* [sksg] More inval fiddlingGravatar Florin Malita2018-01-05
| | | | | | | | | | | | | | | | | | | | | | | | | Node subclasses can now control whether their bounds (changes) contribute to damage. Tristate: * Default: The node bounds contribute to damage if the node itself was invalidated, observing hasSelfInval(). This is the default behavior. * ForceSelf: The node bounds contribute to damage, regardless of hasSelfInval(). Used for domain-boundary nodes (e.g. Draw), which gate blocked fragments (e.g. geometry, paint nodes). * BlockSelf: The node bounds do not contribute to damage, regardless of hasSelfInval(). Used for nodes which do not contribute damage directly (e.g. paints, geometry). TBR= Change-Id: I7c941c7ea12e14b008d846ec13108e66e34dbc73 Reviewed-on: https://skia-review.googlesource.com/91104 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
* [skotty] Add cubic Bezier lerp stubsGravatar Florin Malita2018-01-04
| | | | | | | | | | ... and refactor some of the keyframe parsing. TBR= Change-Id: If45922eab36412908036401cee693202f5c3e281 Reviewed-on: https://skia-review.googlesource.com/91100 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
* [skotty] Add polystar supportGravatar Florin Malita2018-01-04
| | | | | | | | | TBR= Change-Id: Ifcf6beb75eaf08a150785b72e322bb30ab84b779 Reviewed-on: https://skia-review.googlesource.com/90902 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
* [skotty] Add ellipse supportGravatar Florin Malita2018-01-04
| | | | | | | | TBR= Change-Id: I48bbc6aabaab1c3ab5cc9fb19c87ad1f5606eb54 Reviewed-on: https://skia-review.googlesource.com/90900 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
* [skotty,sksg] Add support for geometry mergeGravatar Florin Malita2018-01-04
| | | | | | | | TBR= Change-Id: Ia5edbfeae61779ead6031f6dd4e33794b3eefdc0 Reviewed-on: https://skia-review.googlesource.com/90382 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
* [sksg] Refine invalidation logicGravatar Florin Malita2018-01-04
| | | | | | | | | | | | | | | | | | | | | | | | | | | | We need to discriminate between nodes whose bounds updates contribute to the dirty region, and nodes whose bounds changes do not. E.g. animated shape in a group: the animated shape node bounds should yield damage, but the ancestor group bounds should not. To accomplish this, we refine the invalidation state: 1) self invalidation == the node itself was invalidated, and its bounds updates yield damage. 2) descendant invalidation == the node has some (self-)invalidated descendant, but its own bounds are not contributing damage. Also: * hoist the bounding box invalidation logic into the base class (Node::revalidate) and update to respect the states described above. * remove (now-redundant) GeometryNode bbox logic. * update revalidation methods to return the node bbox instead of void TBR= Change-Id: I8023d1793fb501c945a53f2dc2d2983e5b620ade Reviewed-on: https://skia-review.googlesource.com/90581 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
* [skotty] Fix native path lerpGravatar Florin Malita2018-01-02
| | | | | | | | | | SkPath::interpolate() seems to use 'weight' opposite from documentation. TBR= Change-Id: I678f7939776bfb21614095df8a2c2dcaa4ecd5f5 Reviewed-on: https://skia-review.googlesource.com/90341 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
* [skotty] Native SkPath interpolationGravatar Florin Malita2018-01-02
| | | | | | | | | | | | | | SkPath supports interpolation, no reason to handle that explicitly in Skotty. Change skotty::ShapeValue to convert to SkPaths upfront, when parsing, and then rely in native interpolation. TBR= Change-Id: I32d424ea359e0736909d4e51602ffeb14403feed Reviewed-on: https://skia-review.googlesource.com/90362 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
* [skotty] Improved shape & layer paint orderGravatar Florin Malita2018-01-02
| | | | | | | | | 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>
* [skotty,sksg] Initial RRect supportGravatar Florin Malita2018-01-02
| | | | | | | | Bug: skia: Change-Id: I51bf6619e8d857d5d14fcd6651c144bd3c59453f Reviewed-on: https://skia-review.googlesource.com/90027 Commit-Queue: Florin Malita <fmalita@chromium.org> Reviewed-by: Mike Reed <reed@google.com>
* [skotty] Add Json DM sourceGravatar Florin Malita2017-12-31
| | | | | | | | | | Generates a filmstrip with evenly distributed frames for a Skotty animation. TBR= Change-Id: Ia89e0d65d59fd5ab4ef221a231e9b3e0c033828a Reviewed-on: https://skia-review.googlesource.com/90025 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
* [skotty] Initial shape transform supportGravatar Florin Malita2017-12-31
| | | | | | | | | TBR= Change-Id: I29ce2e6a29492fb0ec51f28f095392594ea6781c Reviewed-on: https://skia-review.googlesource.com/90024 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
* [skotty] Fix path close handlingGravatar Florin Malita2017-12-31
| | | | | | | | | | ... and add a transform animation sample TBR= Change-Id: I27a67d7861dffb9ca22a5e7155ee0eba3b4575f6 Reviewed-on: https://skia-review.googlesource.com/90023 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
* Initial Lottie loader impl (Skotty)Gravatar Florin Malita2017-12-30
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | Coarse workflow: * Construction 1) build a Json tree 2) collect asset IDs (for preComp/image layer resolution) 3) "attach" pass - traverse the Json tree - build an SkSG dom, one fragment at a time - attach "animator" objects to the dom, for each animated prop 4) done, we can throw away the Json tree * For each animation tick 1) iterate over active animators and poke their respective dom nodes/attributes 2) revalidate the SkSG dom 3) draw the SkSG dom Note: post construction, things are super-simple - we just poke SkSG DOM attributes with interpolated values, and everything else is handled by SkSG (invalidation, revalidation, render). Change-Id: I96a02be7eb4fb4cb3831f59bf2b3908ea190c0dd Reviewed-on: https://skia-review.googlesource.com/89420 Reviewed-by: Mike Reed <reed@google.com> Commit-Queue: Florin Malita <fmalita@chromium.org>
* [sksg] Fix inval rect mappingGravatar Florin Malita2017-12-30
| | | | | | | | | | Return false from mapRect() doesn't mean the op failed. TBR= Change-Id: I0582fde3efaa792010f27e3684cfe9c4332e29dc Reviewed-on: https://skia-review.googlesource.com/90021 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
* [sksg] Refactor stroke logicGravatar Florin Malita2017-12-29
| | | | | | | | | | Instead of a specialized node, hoist attributes to base class. TBR= Change-Id: I4fa5a24dfc899307a8603577738972ebd32f57f5 Reviewed-on: https://skia-review.googlesource.com/89903 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
* [sksg] Fix paint invalGravatar Florin Malita2017-12-29
| | | | | | | | | | | Paint nodes contribute to invalidation. Hoist the inval logic from geometry nodes to draw nodes. TBR= Change-Id: Iab33086c377ef4940a84dae3cdccb2c9bdbee99c Reviewed-on: https://skia-review.googlesource.com/89901 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
* [sksg] Initial stroke wrapper supportGravatar Florin Malita2017-12-27
| | | | | | | | | TBR= Change-Id: I33e2fe076334de34c4427e7bfe6b6aaa724130b2 Reviewed-on: https://skia-review.googlesource.com/89641 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
* [sksg] Initial Path supportGravatar Florin Malita2017-12-27
| | | | | | | | | TBR= Change-Id: I594634d339b5e1ad9181dc5303af1a1c754d0fe3 Reviewed-on: https://skia-review.googlesource.com/89540 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
* Initial scene graph (SkSG)Gravatar Florin Malita2017-12-21
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Sketching a thin (as in close-to-skia-semantics) scene graph API, focused on external animation, inval tracking and minimal repaint. Only a few concrete classes/features so far: * Rect/Color/Transform/Group * basic inval tracking * a trivial animated sample with inval visualization Pretty much everything (especially naming) is volatile, so treat accordingly. The interesting bits to review are likely in Node.{h,cpp} for inval and SampleSGInval.cpp for usage. Initial class hierarchy: * Node: invalidation/ancestors tracking | -- * RenderNode: onRender(SkCanvas) | | | -- * Draw (concrete): rendering a [geometry, paint] tuple | | | -- * Group (concrete): grouping multiple RenderNodes | | | -- * EffectNode: single-descendant effect wrapper | | | -- * Transform (concrete): transform effect | -- * PaintNode: onMakePaint() | | | -- * Color (concrete): SkColor paint wrapper | -- * GeometryNode: onComputeBounds(), onDraw(SkCanvas, SkPaint) | -- * Rect (concrete): SkRect wrapper TBR= Change-Id: Iacf9b773c181a7582ecd31ee968562f179d1aa1b Reviewed-on: https://skia-review.googlesource.com/85502 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
* Update SkSurface MakeFromBackend* factories to take an SkColorType.Gravatar Greg Daniel2017-12-19
| | | | | | | | Bug: skia: Change-Id: Ib1b03b1181ec937843eac2e8d8cb03ebe53e32c1 Reviewed-on: https://skia-review.googlesource.com/86760 Commit-Queue: Greg Daniel <egdaniel@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com>
* experimental/tools/gerrit-change-id-to-numberGravatar Hal Canary2017-12-18
| | | | | | | Change-Id: I10a46d2d9c8a710f6816f697e48366366078e4f0 Reviewed-on: https://skia-review.googlesource.com/86640 Reviewed-by: Hal Canary <halcanary@google.com> Commit-Queue: Hal Canary <halcanary@google.com>
* resources: orgainize directory.Gravatar Hal Canary2017-12-08
| | | | | | | | | Should make it easier to ask just for images. Change-Id: If821743dc924c4bfbc6b2b2d29b14affde7b3afd Reviewed-on: https://skia-review.googlesource.com/82684 Commit-Queue: Hal Canary <halcanary@google.com> Reviewed-by: Leon Scroggins <scroggo@google.com>
* Remove a huge pile of views codeGravatar Brian Osman2017-11-22
| | | | | | | | | | | | | All of this is dead when not using the old SkWindow framework. TBR=reed@google.com Bug: skia: Change-Id: I0f6ab18987a98469bfd367d5bc10967300dfd3ca Reviewed-on: https://skia-review.googlesource.com/75384 Reviewed-by: Brian Osman <brianosman@google.com> Reviewed-by: Jim Van Verth <jvanverth@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
* Remove SampleApp and convert HelloWorld to sk_appGravatar Brian Osman2017-11-21
| | | | | | | | | | | | | There is still a large amount of views code that could be trimmed down, but which is used to implement samples (in viewer). Seemed simpler to remove some of this code in pieces. Bug: skia: Change-Id: Ia3415060d03c8de604a154e3dc38379b754daab6 Reviewed-on: https://skia-review.googlesource.com/72801 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Jim Van Verth <jvanverth@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com>
* Remove SkV8ExampleGravatar Brian Osman2017-11-21
| | | | | | | Bug: skia: Change-Id: I411787ae3ef7185e2909a683537799e51096fd62 Reviewed-on: https://skia-review.googlesource.com/74201 Reviewed-by: Greg Daniel <egdaniel@google.com>
* Remove expectations kruft from experimentalGravatar Brian Osman2017-11-21
| | | | | | | | Bug: skia: Change-Id: I8a35b4ce4463534d733d698ae1478de027e0e5f5 Reviewed-on: https://skia-review.googlesource.com/74143 Reviewed-by: Greg Daniel <egdaniel@google.com> Reviewed-by: Stephan Altmueller <stephana@google.com>
* Remove more iOS sample codeGravatar Brian Osman2017-11-21
| | | | | | | | | | I think this is generally obsoleted by sk_app? Bug: skia: Change-Id: Ie8e9dd1f11f2d2f97f0a21a7e79b37755e75cd44 Reviewed-on: https://skia-review.googlesource.com/74161 Reviewed-by: Jim Van Verth <jvanverth@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
* Remove clutter from experimentalGravatar Brian Osman2017-11-21
| | | | | | | | | | | | | SkMatrix has the canonical version of setPolyToPoly, we don't need three other copies sitting around. SkBorder appears to be useless. Bug: skia: Change-Id: Ie747ff7af6cf1d03e6276e8d7fe57e9b3e4ad411 Reviewed-on: https://skia-review.googlesource.com/74141 Reviewed-by: Greg Daniel <egdaniel@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
* style nit: s/RIGHT SINGLE QUOTATION MARK/APOSTROPHE/g when apropriateGravatar Hal Canary2017-11-20
| | | | | | | Change-Id: If834febee09266cad6a7a2fb64b06adc25790e33 Reviewed-on: https://skia-review.googlesource.com/73742 Reviewed-by: Ben Wagner <bungeman@google.com> Commit-Queue: Hal Canary <halcanary@google.com>
* [v8-platform] Store the platform in a unique_ptrGravatar Andreas Haas2017-11-09
| | | | | | | | | | | | | | We want to change the signature of {CreateDefaultPlatform} in the V8 API to return a unique_ptr instead of a raw pointer to indicate that the caller owns the platform. With this change we prepare pdfium for this change. R=egdaniel@google.com Change-Id: Ib0bb743ca0acd98018cb28828890868f1e0fc612 Reviewed-on: https://skia-review.googlesource.com/69320 Reviewed-by: Greg Daniel <egdaniel@google.com> Commit-Queue: Greg Daniel <egdaniel@google.com>
* experimental/documentation/gerrit: authenticationGravatar Hal Canary2017-10-17
| | | | | | | | NOTRY=true Change-Id: I8d4f86848dcc37bcc0aead3700969ea4df6417db Reviewed-on: https://skia-review.googlesource.com/59762 Reviewed-by: Hal Canary <halcanary@google.com> Commit-Queue: Hal Canary <halcanary@google.com>
* [SVGDom] Add 'stroke-dashoffset' supportGravatar Florin Malita2017-10-13
| | | | | | | | https://www.w3.org/TR/SVG/painting.html#StrokeDashoffsetProperty Change-Id: Ia25d0048a56ac3835cabcb4e1794d91667367d7c Reviewed-on: https://skia-review.googlesource.com/59820 Reviewed-by: Robert Phillips <robertphillips@google.com> Commit-Queue: Florin Malita <fmalita@chromium.org>
* [SVGDom] Add 'stroke-dasharray' supportGravatar Florin Malita2017-10-13
| | | | | | | | https://www.w3.org/TR/SVG/painting.html#StrokeDasharrayProperty Change-Id: I9a63ebbd958d661c865ed405570b86cca68f63bf Reviewed-on: https://skia-review.googlesource.com/59700 Commit-Queue: Florin Malita <fmalita@chromium.org> Reviewed-by: Robert Phillips <robertphillips@google.com>