1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <iostream>
17 #include <vector>
18 
19 #include "include/core/SkBitmap.h"
20 #include "include/core/SkCanvas.h"
21 #include "include/core/SkColor.h"
22 #include "include/core/SkImage.h"
23 #include "include/core/SkImageInfo.h"
24 #include "include/core/SkPaint.h"
25 #include "include/core/SkRect.h"
26 #include "wm/window.h"
27 
28 #include "animation/rs_transition.h"
29 #include "animation/rs_transition_effect.h"
30 #include "modifier/rs_extended_modifier.h"
31 #include "modifier/rs_property_modifier.h"
32 #include "transaction/rs_transaction.h"
33 #include "ui/rs_display_node.h"
34 #include "ui/rs_root_node.h"
35 #include "ui/rs_surface_node.h"
36 #include "ui/rs_ui_director.h"
37 
38 using namespace std;
39 using namespace OHOS;
40 using namespace OHOS::Rosen;
41 
42 constexpr int64_t START_NUMBER = 181154000809;
43 constexpr int64_t INCREASE_NUMBER = 10000000;
44 constexpr int64_t SLEEP_TIME = 10000;
45 constexpr int NUMBER_HALF = 2;
46 constexpr int NUMBER_TWO = 2;
47 constexpr int CLIP_NUMBER = 10;
48 constexpr int COLOR_VALUE_MAX = 255;
49 constexpr int WINDOW_WIDTH = 720;
50 constexpr int WINDOW_HEIGHT = 1280;
51 constexpr int ANIMATION_DURATION = 2000;
52 constexpr int ANIMATION_DELAY_TIME = 500;
53 std::shared_ptr<RSNode> rootNode;
54 std::vector<std::shared_ptr<RSCanvasNode>> nodes;
55 std::shared_ptr<RSUIDirector> rsUiDirector;
56 
57 class TransitionModifier1 : public RSTransitionModifier {
58 public:
Draw(RSDrawingContext & context) const59     void Draw(RSDrawingContext& context) const override
60     {
61         if (!radius_ || !backgroundColor_ || !alpha_) {
62             SkRect rect = SkRect::MakeXYWH(0, 0, 0, 0);
63             SkPaint p;
64             context.canvas->drawRect(rect, p);
65             return;
66         }
67         context.canvas->save();
68         SkPath path;
69         path.addCircle(context.width / NUMBER_HALF, context.height / NUMBER_HALF,
70             radius_->Get() * sqrt(pow(context.width / NUMBER_HALF, NUMBER_TWO) +
71             pow(context.height / NUMBER_HALF, NUMBER_TWO)));
72         context.canvas->clipPath(path);
73         SkRect rect = SkRect::MakeXYWH(0, 0, context.width, context.height);
74         SkPaint p;
75         p.setColor(backgroundColor_->Get().AsArgbInt());
76         p.setAlphaf(alpha_->Get());
77         context.canvas->drawRect(rect, p);
78         context.canvas->restore();
79     }
80 
SetRadius(float radius)81     void SetRadius(float radius)
82     {
83         if (radius_ == nullptr) {
84             radius_ = std::make_shared<RSAnimatableProperty<float>>(radius);
85             AttachProperty(radius_);
86         } else {
87             radius_->Set(radius);
88         }
89     }
90 
SetBackgroundColor(Color backgroundColor)91     void SetBackgroundColor(Color backgroundColor)
92     {
93         if (backgroundColor_ == nullptr) {
94             backgroundColor_ = std::make_shared<RSAnimatableProperty<Color>>(backgroundColor);
95             AttachProperty(backgroundColor_);
96         } else {
97             backgroundColor_->Set(backgroundColor);
98         }
99     }
100 
SetAlpha(float alpha)101     void SetAlpha(float alpha)
102     {
103         if (alpha_ == nullptr) {
104             alpha_ = std::make_shared<RSAnimatableProperty<float>>(alpha);
105             AttachProperty(alpha_);
106         } else {
107             alpha_->Set(alpha);
108         }
109     }
110 
Active()111     void Active() override
112     {
113         // should set property of before transition-in
114         SetRadius(0);
115         SetBackgroundColor(Color(COLOR_VALUE_MAX, 0, 0));
116         SetAlpha(0);
117     }
118 
Identity()119     void Identity() override
120     {
121         // should set property of after transition-in
122         SetRadius(1);
123         SetBackgroundColor(Color(0, 0, COLOR_VALUE_MAX));
124         SetAlpha(1);
125     }
126 
127 private:
128     std::shared_ptr<RSAnimatableProperty<float>> radius_;
129     std::shared_ptr<RSAnimatableProperty<Color>> backgroundColor_;
130     std::shared_ptr<RSAnimatableProperty<float>> alpha_;
131 };
132 
133 class TransitionModifier2 : public RSTransitionModifier {
134 public:
Draw(RSDrawingContext & context) const135     void Draw(RSDrawingContext& context) const override
136     {
137         float radius = 0;
138         if (radius_) {
139             radius = radius_->Get();
140         }
141         context.canvas->save();
142         SkPath path;
143         path.addCircle(0, 0, radius * sqrt(pow(context.width, NUMBER_TWO) + pow(context.height, NUMBER_TWO)));
144         context.canvas->clipPath(path);
145         SkRect rect = SkRect::MakeXYWH(0, 0, context.width, context.height);
146         SkPaint p;
147         p.setColor(backgroundColor_.AsArgbInt());
148         context.canvas->drawRect(rect, p);
149         context.canvas->restore();
150     }
151 
SetRadius(float radius)152     void SetRadius(float radius)
153     {
154         if (radius_ == nullptr) {
155             radius_ = std::make_shared<RSAnimatableProperty<float>>(radius);
156             AttachProperty(radius_);
157         } else {
158             radius_->Set(radius);
159         }
160     }
161 
SetBackgroundColor(Color backgroundColor)162     void SetBackgroundColor(Color backgroundColor)
163     {
164         backgroundColor_ = backgroundColor;
165     }
166 
Active()167     void Active() override
168     {
169         // should set property of before transition-in
170         SetRadius(0);
171     }
172 
Identity()173     void Identity() override
174     {
175         // should set property of after transition-in
176         SetRadius(1);
177     }
178 
179 private:
180     std::shared_ptr<RSAnimatableProperty<float>> radius_;
181     Color backgroundColor_ = Color(COLOR_VALUE_MAX, 0, 0);
182 };
183 
184 class TransitionModifier3 : public RSTransitionModifier {
185 public:
Draw(RSDrawingContext & context) const186     void Draw(RSDrawingContext& context) const override
187     {
188         float clipWidth = 0;
189         if (clipWidth_) {
190             clipWidth = clipWidth_->Get();
191         }
192         for (int i = 0; i < clipPieces_; i++) {
193             context.canvas->save();
194             SkRect clipRect = SkRect::MakeXYWH(context.width / clipPieces_ * i, 0,
195                 clipWidth * context.width / clipPieces_, context.height);
196             context.canvas->clipRect(clipRect);
197             SkRect rect = SkRect::MakeXYWH(0, 0, context.width, context.height);
198             SkPaint p;
199             p.setColor(backgroundColor_.AsArgbInt());
200             context.canvas->drawRect(rect, p);
201             context.canvas->restore();
202         }
203     }
204 
SetClipWidth(float clipWidth)205     void SetClipWidth(float clipWidth)
206     {
207         if (clipWidth_ == nullptr) {
208             clipWidth_ = std::make_shared<RSAnimatableProperty<float>>(clipWidth);
209             AttachProperty(clipWidth_);
210         } else {
211             clipWidth_->Set(clipWidth);
212         }
213     }
214 
SetBackgroundColor(Color backgroundColor)215     void SetBackgroundColor(Color backgroundColor)
216     {
217         backgroundColor_ = backgroundColor;
218     }
219 
Active()220     void Active() override
221     {
222         // should set property of before transition-in
223         SetClipWidth(0);
224     }
225 
Identity()226     void Identity() override
227     {
228         // should set property of after transition-in
229         SetClipWidth(1);
230     }
231 
232 private:
233     std::shared_ptr<RSAnimatableProperty<float>> clipWidth_;
234     Color backgroundColor_ = Color(COLOR_VALUE_MAX, 0, 0);
235     int clipPieces_ = CLIP_NUMBER;
236 };
237 
238 class TransitionModifier4 : public RSTransitionModifier {
239 public:
Draw(RSDrawingContext & context) const240     void Draw(RSDrawingContext& context) const override
241     {
242         float clipWidth = 0;
243         if (clipWidth_) {
244             clipWidth = clipWidth_->Get();
245         }
246         for (int i = 0; i < clipPieces_; i++) {
247             context.canvas->save();
248             SkRect clipRect = SkRect::MakeXYWH(
249                 context.width / clipPieces_ * (i + 1) - clipWidth * context.width / clipPieces_, 0,
250                 clipWidth * context.width / clipPieces_, context.height);
251             context.canvas->clipRect(clipRect);
252             SkRect rect = SkRect::MakeXYWH(0, 0, context.width, context.height);
253             SkPaint p;
254             p.setColor(backgroundColor_.AsArgbInt());
255             context.canvas->drawRect(rect, p);
256             context.canvas->restore();
257         }
258     }
259 
SetClipWidth(float clipWidth)260     void SetClipWidth(float clipWidth)
261     {
262         if (clipWidth_ == nullptr) {
263             clipWidth_ = std::make_shared<RSAnimatableProperty<float>>(clipWidth);
264             AttachProperty(clipWidth_);
265         } else {
266             clipWidth_->Set(clipWidth);
267         }
268     }
269 
SetBackgroundColor(Color backgroundColor)270     void SetBackgroundColor(Color backgroundColor)
271     {
272         backgroundColor_ = backgroundColor;
273     }
274 
Active()275     void Active() override
276     {
277         // should set property of before transition-in
278         SetClipWidth(0);
279     }
280 
Identity()281     void Identity() override
282     {
283         // should set property of after transition-in
284         SetClipWidth(1);
285     }
286 
287 private:
288     std::shared_ptr<RSAnimatableProperty<float>> clipWidth_;
289     Color backgroundColor_ = Color(COLOR_VALUE_MAX, 0, 0);
290     int clipPieces_ = CLIP_NUMBER;
291 };
292 
293 class TransitionModifier5 : public RSTransitionModifier {
294 public:
Draw(RSDrawingContext & context) const295     void Draw(RSDrawingContext& context) const override
296     {
297         float clipHeight = 0;
298         if (clipHeight_) {
299             clipHeight = clipHeight_->Get();
300         }
301         for (int i = 0; i < clipPieces_; i++) {
302             context.canvas->save();
303             SkRect clipRect = SkRect::MakeXYWH(0, context.height / clipPieces_ * i,
304                 context.width, clipHeight * context.height / clipPieces_);
305             context.canvas->clipRect(clipRect);
306             SkRect rect = SkRect::MakeXYWH(0, 0, context.width, context.height);
307             SkPaint p;
308             p.setColor(backgroundColor_.AsArgbInt());
309             context.canvas->drawRect(rect, p);
310             context.canvas->restore();
311         }
312     }
313 
SetClipHeight(float clipHeight)314     void SetClipHeight(float clipHeight)
315     {
316         if (clipHeight_ == nullptr) {
317             clipHeight_ = std::make_shared<RSAnimatableProperty<float>>(clipHeight);
318             AttachProperty(clipHeight_);
319         } else {
320             clipHeight_->Set(clipHeight);
321         }
322     }
323 
SetBackgroundColor(Color backgroundColor)324     void SetBackgroundColor(Color backgroundColor)
325     {
326         backgroundColor_ = backgroundColor;
327     }
328 
Active()329     void Active() override
330     {
331         // should set property of before transition-in
332         SetClipHeight(0);
333     }
334 
Identity()335     void Identity() override
336     {
337         // should set property of after transition-in
338         SetClipHeight(1);
339     }
340 
341 private:
342     std::shared_ptr<RSAnimatableProperty<float>> clipHeight_;
343     Color backgroundColor_ = Color(COLOR_VALUE_MAX, 0, 0);
344     int clipPieces_ = CLIP_NUMBER;
345 };
346 
Transition1()347 void Transition1()
348 {
349     nodes.emplace_back(RSCanvasNode::Create());
350     nodes[0]->SetBounds({ 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT});
351     // define custom modifier for transition
352     auto transitionModifier1 = std::make_shared<TransitionModifier1>();
353     auto transitionModifier2 = std::make_shared<TransitionModifier2>();
354     transitionModifier2->SetBackgroundColor(Color(0, 0, COLOR_VALUE_MAX));
355     // add the modifier to node
356     nodes[0]->AddModifier(transitionModifier1);
357     nodes[0]->AddModifier(transitionModifier2);
358     // create transition effect
359     auto transitionInEffect = RSTransitionEffect::Create()->Custom(transitionModifier1);
360     auto transitionOutEffect = RSTransitionEffect::Create()->Custom(transitionModifier2);
361     nodes[0]->SetTransitionEffect(RSTransitionEffect::Asymmetric(transitionInEffect, transitionOutEffect));
362     // define animation protocol
363     RSAnimationTimingProtocol protocol;
364     // set duration as 2000 millisecond
365     protocol.SetDuration(ANIMATION_DURATION);
366     // create transition-in animation
367     RSNode::Animate(protocol, RSAnimationTimingCurve::EASE_IN_OUT, [&]() {
368         rootNode->AddChild(nodes[0]);
369     }, []() {
370         std::cout << "nodes0 appears" << std::endl;
371     });
372     uint64_t timeStamp = START_NUMBER;
373     bool hasRunningAnimation = true;
374     while (hasRunningAnimation) {
375         hasRunningAnimation = rsUiDirector->FlushAnimation(timeStamp);
376         rsUiDirector->FlushModifier();
377         rsUiDirector->SendMessages();
378         timeStamp += INCREASE_NUMBER;
379         usleep(SLEEP_TIME);
380     }
381     nodes[0]->RemoveModifier(transitionModifier1);
382 }
383 
Transition2()384 void Transition2()
385 {
386     nodes.emplace_back(RSCanvasNode::Create());
387     nodes[1]->SetBounds({ 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT});
388     // define custom modifier for transition
389     auto transitionModifier2 = std::make_shared<TransitionModifier2>();
390     auto transitionModifier3 = std::make_shared<TransitionModifier3>();
391     transitionModifier2->SetBackgroundColor(Color(0, COLOR_VALUE_MAX, 0));
392     transitionModifier3->SetBackgroundColor(Color(0, COLOR_VALUE_MAX, 0));
393     // add the modifier to node
394     nodes[1]->AddModifier(transitionModifier2);
395     nodes[1]->AddModifier(transitionModifier3);
396     // create transition effect
397     auto transitionInEffect = RSTransitionEffect::Create()->Custom(transitionModifier2);
398     auto transitionOutEffect = RSTransitionEffect::Create()->Custom(transitionModifier3);
399     nodes[1]->SetTransitionEffect(RSTransitionEffect::Asymmetric(transitionInEffect, transitionOutEffect));
400     // define animation protocol
401     RSAnimationTimingProtocol protocol;
402     // set duration as 2000 millisecond
403     protocol.SetDuration(ANIMATION_DURATION);
404     // create transition-out animation
405     RSNode::Animate(protocol, RSAnimationTimingCurve::EASE_IN_OUT, [&]() {
406         rootNode->RemoveChild(nodes[0]);
407     }, []() {
408         std::cout << "nodes0 disappears" << std::endl;
409     });
410     protocol.SetStartDelay(ANIMATION_DELAY_TIME);
411     // create transition-in animation
412     RSNode::Animate(protocol, RSAnimationTimingCurve::EASE_IN_OUT, [&]() {
413         rootNode->AddChild(nodes[1]);
414     }, []() {
415         std::cout << "nodes1 appears" << std::endl;
416     });
417     uint64_t timeStamp = START_NUMBER;
418     bool hasRunningAnimation = true;
419     while (hasRunningAnimation) {
420         hasRunningAnimation = rsUiDirector->FlushAnimation(timeStamp);
421         rsUiDirector->FlushModifier();
422         rsUiDirector->SendMessages();
423         timeStamp += INCREASE_NUMBER;
424         usleep(SLEEP_TIME);
425     }
426     nodes[1]->RemoveModifier(transitionModifier2);
427 }
428 
Transition3()429 void Transition3()
430 {
431     nodes.emplace_back(RSCanvasNode::Create());
432     nodes[NUMBER_TWO]->SetBounds({ 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT});
433     // define custom modifier for transition
434     auto transitionModifier4 = std::make_shared<TransitionModifier4>();
435     auto transitionModifier5 = std::make_shared<TransitionModifier5>();
436     transitionModifier4->SetBackgroundColor(Color(0, COLOR_VALUE_MAX, COLOR_VALUE_MAX));
437     transitionModifier5->SetBackgroundColor(Color(0, COLOR_VALUE_MAX, COLOR_VALUE_MAX));
438     // add the modifier to node
439     nodes[NUMBER_TWO]->AddModifier(transitionModifier4);
440     nodes[NUMBER_TWO]->AddModifier(transitionModifier5);
441     // create transition effect
442     auto transitionInEffect = RSTransitionEffect::Create()->Custom(transitionModifier4);
443     auto transitionOutEffect = RSTransitionEffect::Create()->Custom(transitionModifier5);
444     nodes[NUMBER_TWO]->SetTransitionEffect(RSTransitionEffect::Asymmetric(transitionInEffect, transitionOutEffect));
445     // define animation protocol
446     RSAnimationTimingProtocol protocol;
447     // set duration as 2000 millisecond
448     protocol.SetDuration(ANIMATION_DURATION);
449     // create transition-out animation
450     RSNode::Animate(protocol, RSAnimationTimingCurve::EASE_IN_OUT, [&]() {
451         rootNode->RemoveChild(nodes[1]);
452     }, []() {
453         std::cout << "nodes1 disappears" << std::endl;
454     });
455     // create transition-in animation
456     RSNode::Animate(protocol, RSAnimationTimingCurve::EASE_IN_OUT, [&]() {
457         rootNode->AddChild(nodes[NUMBER_TWO]);
458     }, []() {
459         std::cout << "nodes2 appears" << std::endl;
460     });
461     uint64_t timeStamp = START_NUMBER;
462     bool hasRunningAnimation = true;
463     while (hasRunningAnimation) {
464         hasRunningAnimation = rsUiDirector->FlushAnimation(timeStamp);
465         rsUiDirector->FlushModifier();
466         rsUiDirector->SendMessages();
467         timeStamp += INCREASE_NUMBER;
468         usleep(SLEEP_TIME);
469     }
470     nodes[NUMBER_TWO]->RemoveModifier(transitionModifier4);
471 }
472 
Transition4()473 void Transition4()
474 {
475     // define animation protocol
476     RSAnimationTimingProtocol protocol;
477     // set duration as 2000 millisecond
478     protocol.SetDuration(ANIMATION_DURATION);
479     // create transition-out animation
480     RSNode::Animate(protocol, RSAnimationTimingCurve::EASE_IN_OUT, [&]() {
481         rootNode->RemoveChild(nodes[NUMBER_TWO]);
482     }, []() {
483         std::cout << "nodes2 disappears" << std::endl;
484     });
485     uint64_t timeStamp = START_NUMBER;
486     bool hasRunningAnimation = true;
487     while (hasRunningAnimation) {
488         hasRunningAnimation = rsUiDirector->FlushAnimation(timeStamp);
489         rsUiDirector->FlushModifier();
490         rsUiDirector->SendMessages();
491         timeStamp += INCREASE_NUMBER;
492         usleep(SLEEP_TIME);
493     }
494 }
495 
main()496 int main()
497 {
498     std::cout << "transition demo start!" << std::endl;
499 
500     // create window
501     sptr<WindowOption> option = new WindowOption();
502     option->SetWindowType(WindowType::WINDOW_TYPE_FLOAT);
503     option->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING);
504     option->SetWindowRect({ 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT });
505     auto window = Window::Create("transition", option);
506     window->Show();
507     auto rect = window->GetRect();
508     while (rect.width_ == 0 && rect.height_ == 0) {
509         std::cout << "create window failed: " << rect.width_ << " " << rect.height_ << std::endl;
510         window->Hide();
511         window->Destroy();
512         window = Window::Create("transition_demo", option);
513         window->Show();
514         rect = window->GetRect();
515     }
516     std::cout << "create window " << rect.width_ << " " << rect.height_ << std::endl;
517     auto surfaceNode = window->GetSurfaceNode();
518 
519     std::cout << "init rosen backend!" << std::endl;
520 
521     // init rosen backend
522     rsUiDirector = RSUIDirector::Create();
523     rsUiDirector->Init();
524     RSTransaction::FlushImplicitTransaction();
525     rsUiDirector->SetRSSurfaceNode(surfaceNode);
526 
527     rootNode = RSRootNode::Create();
528     rootNode->SetBounds(0, 0, rect.width_, rect.height_);
529     rootNode->SetFrame(0, 0, rect.width_, rect.height_);
530     rootNode->SetBackgroundColor(SK_ColorWHITE);
531     rsUiDirector->SetRoot(rootNode->GetId());
532 
533     std::cout << "nodes[0] appearing." << std::endl;
534     Transition1();
535     sleep(NUMBER_TWO);
536     std::cout << "nodes[0] disappearing and nodes[1] appearing." << std::endl;
537     Transition2();
538     sleep(NUMBER_TWO);
539     std::cout << "nodes[1] disappearing and nodes[2] appearing." << std::endl;
540     Transition3();
541     sleep(NUMBER_TWO);
542     std::cout << "nodes[2] disappearing." << std::endl;
543     Transition4();
544     sleep(NUMBER_TWO);
545 
546     std::cout << "transition demo end!" << std::endl;
547     window->Hide();
548     window->Destroy();
549     return 0;
550 }
551