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