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