1 /*
2 * Copyright 2020 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "experimental/skrive/include/SkRive.h"
9
10 #include "experimental/skrive/src/reader/StreamReader.h"
11 #include "include/core/SkCanvas.h"
12
13 #include <tuple>
14 #include <vector>
15
16 namespace skrive {
17
18 namespace internal {
19
20 template <typename T>
21 size_t parse_node(StreamReader*, T*);
22
23 template <typename T, typename... Args>
make_from_stream(StreamReader * sr,Args &&...args)24 std::tuple<sk_sp<Component>, size_t> make_from_stream(StreamReader* sr, Args&&... args) {
25 auto node = sk_make_sp<T>(std::forward<Args>(args)...);
26
27 const auto parent_id = parse_node<T>(sr, node.get());
28
29 return std::make_tuple(std::move(node), parent_id);
30 }
31
parse_component(StreamReader * sr)32 std::tuple<sk_sp<Component>, size_t> parse_component(StreamReader* sr) {
33 StreamReader::AutoBlock block(sr);
34 switch (block.type()) {
35 case StreamReader::BlockType::kActorNode:
36 return make_from_stream<Node >(sr);
37 case StreamReader::BlockType::kActorShape:
38 return make_from_stream<Shape>(sr);
39 case StreamReader::BlockType::kColorFill:
40 return make_from_stream<ColorPaint>(sr, SkPaint::kFill_Style);
41 case StreamReader::BlockType::kColorStroke:
42 return make_from_stream<ColorPaint>(sr, SkPaint::kStroke_Style);
43 case StreamReader::BlockType::kActorEllipse:
44 return make_from_stream<Ellipse>(sr);
45 case StreamReader::BlockType::kActorRectangle:
46 return make_from_stream<Rectangle>(sr);
47 default:
48 break;
49 }
50
51 SkDebugf("!! unsupported node type: %d\n", block.type());
52 return {nullptr, 0};
53 }
54
parse_components(StreamReader * sr)55 sk_sp<Node> parse_components(StreamReader* sr) {
56 const auto count = sr->readLength16();
57
58 std::vector<sk_sp<Component>> components;
59 components.reserve(count);
60
61 for (size_t i = 0; i < count; ++i) {
62 auto [ component, parent_id ] = parse_component(sr);
63
64 // parent IDs are kinda-sorta one-based
65 if (parent_id > 0) {
66 parent_id -= 1;
67 }
68
69 if (component && parent_id < i && components[parent_id]) {
70 if (Node* node = *components[parent_id]) {
71 node->addChild(component);
72 }
73 }
74
75 components.push_back(std::move(component));
76 }
77
78 SkDebugf(".. parsed %zu components\n", components.size());
79
80 // hmm...
81 for (const auto& comp : components) {
82 if (comp && comp->is<Node>()) {
83 return sk_ref_sp(static_cast<Node*>(*comp));
84 }
85 }
86
87 return nullptr;
88 }
89
parse_artboard(StreamReader * sr)90 sk_sp<Artboard> parse_artboard(StreamReader* sr) {
91 auto ab = sk_make_sp<Artboard>();
92
93 ab->setName (sr->readString("name" ));
94 ab->setTranslation (sr->readV2 ("translation" ));
95 ab->setSize ({sr->readFloat ("width" ),
96 sr->readFloat ("height" )});
97 ab->setOrigin (sr->readV2 ("origin" ));
98 ab->setClipContents(sr->readBool ("clipContents"));
99 ab->setColor (sr->readColor ("color" ));
100
101 for (;;) {
102 StreamReader::AutoBlock block(sr);
103 if (block.type() == StreamReader::BlockType::kEoB) {
104 break;
105 }
106
107 switch (block.type()) {
108 case StreamReader::BlockType::kComponents:
109 ab->setRoot(parse_components(sr));
110 break;
111 default:
112 SkDebugf("!! Unsupported block type: %d\n", block.type());
113 break;
114 }
115 }
116
117 SkDebugf(".. parsed artboard \"%s\" [%f x %f]\n",
118 ab->getName().c_str(), ab->getSize().x, ab->getSize().y);
119
120 return ab;
121 }
122
123 } // namespace internal
124
render(SkCanvas * canvas) const125 void Artboard::render(SkCanvas* canvas) const {
126 SkAutoCanvasRestore acr(canvas, true);
127 canvas->translate(fTranslation.x, fTranslation.y);
128
129 SkPaint paint;
130 paint.setColor4f(fColor);
131
132 canvas->drawRect(SkRect::MakeWH(fSize.x, fSize.y), paint);
133
134 if (fRoot) {
135 fRoot->revalidate();
136 fRoot->render(canvas);
137 }
138 }
139
140 } // namespace skrive
141