1 /* 2 * Copyright (c) 2023 - 2024 the ThorVG project. All rights reserved. 3 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to deal 6 * in the Software without restriction, including without limitation the rights 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 * copies of the Software, and to permit persons to whom the Software is 9 * furnished to do so, subject to the following conditions: 10 11 * The above copyright notice and this permission notice shall be included in all 12 * copies or substantial portions of the Software. 13 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 * SOFTWARE. 21 */ 22 23 #include "../../lv_conf_internal.h" 24 #if LV_USE_THORVG_INTERNAL 25 26 #ifndef _TVG_LOTTIE_MODEL_H_ 27 #define _TVG_LOTTIE_MODEL_H_ 28 29 #include <cstring> 30 31 #include "tvgCommon.h" 32 #include "tvgRender.h" 33 #include "tvgLottieProperty.h" 34 #include "tvgLottieRenderPooler.h" 35 36 37 struct LottieComposition; 38 39 struct LottieStroke 40 { 41 struct DashAttr 42 { 43 //0: offset, 1: dash, 2: gap 44 LottieFloat value[3] = {0.0f, 0.0f, 0.0f}; 45 }; 46 ~LottieStrokeLottieStroke47 virtual ~LottieStroke() 48 { 49 delete(dashattr); 50 } 51 dashLottieStroke52 LottieFloat& dash(int no) 53 { 54 if (!dashattr) dashattr = new DashAttr; 55 return dashattr->value[no]; 56 } 57 dashOffsetLottieStroke58 float dashOffset(float frameNo, LottieExpressions* exps) 59 { 60 return dash(0)(frameNo, exps); 61 } 62 dashGapLottieStroke63 float dashGap(float frameNo, LottieExpressions* exps) 64 { 65 return dash(2)(frameNo, exps); 66 } 67 dashSizeLottieStroke68 float dashSize(float frameNo, LottieExpressions* exps) 69 { 70 auto d = dash(1)(frameNo, exps); 71 if (d == 0.0f) return 0.1f; 72 else return d; 73 } 74 75 LottieFloat width = 0.0f; 76 DashAttr* dashattr = nullptr; 77 float miterLimit = 0; 78 StrokeCap cap = StrokeCap::Round; 79 StrokeJoin join = StrokeJoin::Round; 80 }; 81 82 83 struct LottieEffect 84 { 85 enum Type : uint8_t 86 { 87 GaussianBlur = 0, 88 }; 89 ~LottieEffectLottieEffect90 virtual ~LottieEffect() {} 91 92 Type type; 93 bool enable = false; 94 }; 95 96 97 struct LottieGaussianBlur : LottieEffect 98 { 99 LottieSlider blurness = 0.0f; 100 LottieCheckbox direction = 0; 101 LottieCheckbox wrap = 0; 102 LottieGaussianBlurLottieGaussianBlur103 LottieGaussianBlur() 104 { 105 type = GaussianBlur; 106 } 107 }; 108 109 110 struct LottieMask 111 { 112 LottiePathSet pathset; 113 LottieFloat expand = 0.0f; 114 LottieOpacity opacity = 255; 115 CompositeMethod method; 116 bool inverse = false; 117 }; 118 119 120 struct LottieObject 121 { 122 enum Type : uint8_t 123 { 124 Composition = 0, 125 Layer, 126 Group, 127 Transform, 128 SolidFill, 129 SolidStroke, 130 GradientFill, 131 GradientStroke, 132 Rect, 133 Ellipse, 134 Path, 135 Polystar, 136 Image, 137 Trimpath, 138 Text, 139 Repeater, 140 RoundedCorner, 141 OffsetPath 142 }; 143 ~LottieObjectLottieObject144 virtual ~LottieObject() 145 { 146 } 147 overrideLottieObject148 virtual void override(LottieProperty* prop) 149 { 150 TVGERR("LOTTIE", "Unsupported slot type"); 151 } 152 mergeableLottieObject153 virtual bool mergeable() { return false; } propertyLottieObject154 virtual LottieProperty* property(uint16_t ix) { return nullptr; } 155 156 unsigned long id = 0; 157 Type type; 158 bool hidden = false; //remove? 159 }; 160 161 162 struct LottieGlyph 163 { 164 Array<LottieObject*> children; //glyph shapes. 165 float width; 166 char* code; 167 char* family = nullptr; 168 char* style = nullptr; 169 uint16_t size; 170 uint8_t len; 171 prepareLottieGlyph172 void prepare() 173 { 174 len = strlen(code); 175 } 176 ~LottieGlyphLottieGlyph177 ~LottieGlyph() 178 { 179 for (auto p = children.begin(); p < children.end(); ++p) delete(*p); 180 free(code); 181 } 182 }; 183 184 185 struct LottieTextStyle 186 { 187 LottieColor fillColor = RGB24{255, 255, 255}; 188 LottieColor strokeColor = RGB24{255, 255, 255}; 189 LottiePosition position = Point{0, 0}; 190 LottiePoint scale = Point{100, 100}; 191 LottieFloat letterSpacing = 0.0f; 192 LottieFloat lineSpacing = 0.0f; 193 LottieFloat strokeWidth = 0.0f; 194 LottieFloat rotation = 0.0f; 195 LottieOpacity fillOpacity = 255; 196 LottieOpacity strokeOpacity = 255; 197 LottieOpacity opacity = 255; 198 }; 199 200 201 struct LottieTextRange 202 { 203 enum Based : uint8_t { Chars = 1, CharsExcludingSpaces, Words, Lines }; 204 enum Shape : uint8_t { Square = 1, RampUp, RampDown, Triangle, Round, Smooth }; 205 enum Unit : uint8_t { Percent = 1, Index }; 206 207 LottieTextStyle style; 208 LottieFloat offset = 0.0f; 209 LottieFloat maxEase = 0.0f; 210 LottieFloat minEase = 0.0f; 211 LottieFloat maxAmount = 0.0f; 212 LottieFloat smoothness = 0.0f; 213 LottieFloat start = 0.0f; 214 LottieFloat end = FLT_MAX; 215 Based based = Chars; 216 Shape shape = Square; 217 Unit rangeUnit = Percent; 218 uint8_t random = 0; 219 bool expressible = false; 220 221 void range(float frameNo, float totalLen, float& start, float& end); 222 }; 223 224 225 struct LottieFont 226 { 227 enum Origin : uint8_t { Local = 0, CssURL, ScriptURL, FontURL, Embedded }; 228 ~LottieFontLottieFont229 ~LottieFont() 230 { 231 for (auto c = chars.begin(); c < chars.end(); ++c) delete(*c); 232 free(style); 233 free(family); 234 free(name); 235 } 236 237 Array<LottieGlyph*> chars; 238 char* name = nullptr; 239 char* family = nullptr; 240 char* style = nullptr; 241 float ascent = 0.0f; 242 Origin origin = Embedded; 243 }; 244 245 struct LottieMarker 246 { 247 char* name = nullptr; 248 float time = 0.0f; 249 float duration = 0.0f; 250 ~LottieMarkerLottieMarker251 ~LottieMarker() 252 { 253 free(name); 254 } 255 }; 256 257 struct LottieText : LottieObject, LottieRenderPooler<tvg::Shape> 258 { prepareLottieText259 void prepare() 260 { 261 LottieObject::type = LottieObject::Text; 262 } 263 overrideLottieText264 void override(LottieProperty* prop) override 265 { 266 this->doc = *static_cast<LottieTextDoc*>(prop); 267 this->prepare(); 268 } 269 propertyLottieText270 LottieProperty* property(uint16_t ix) override 271 { 272 if (doc.ix == ix) return &doc; 273 return nullptr; 274 } 275 276 LottieTextDoc doc; 277 LottieFont* font; 278 Array<LottieTextRange*> ranges; 279 ~LottieTextLottieText280 ~LottieText() 281 { 282 for (auto r = ranges.begin(); r < ranges.end(); ++r) delete(*r); 283 } 284 }; 285 286 287 struct LottieTrimpath : LottieObject 288 { 289 enum Type : uint8_t { Simultaneous = 1, Individual = 2 }; 290 prepareLottieTrimpath291 void prepare() 292 { 293 LottieObject::type = LottieObject::Trimpath; 294 } 295 mergeableLottieTrimpath296 bool mergeable() override 297 { 298 if (!start.frames && start.value == 0.0f && !end.frames && end.value == 100.0f && !offset.frames && offset.value == 0.0f) return true; 299 return false; 300 } 301 propertyLottieTrimpath302 LottieProperty* property(uint16_t ix) override 303 { 304 if (start.ix == ix) return &start; 305 if (end.ix == ix) return &end; 306 if (offset.ix == ix) return &offset; 307 return nullptr; 308 } 309 310 void segment(float frameNo, float& start, float& end, LottieExpressions* exps); 311 312 LottieFloat start = 0.0f; 313 LottieFloat end = 100.0f; 314 LottieFloat offset = 0.0f; 315 Type type = Simultaneous; 316 }; 317 318 319 struct LottieShape : LottieObject, LottieRenderPooler<tvg::Shape> 320 { 321 bool clockwise = true; //clockwise or counter-clockwise 322 ~LottieShapeLottieShape323 virtual ~LottieShape() {} 324 mergeableLottieShape325 bool mergeable() override 326 { 327 return true; 328 } 329 prepareLottieShape330 void prepare(LottieObject::Type type) 331 { 332 LottieObject::type = type; 333 } 334 }; 335 336 337 struct LottieRoundedCorner : LottieObject 338 { prepareLottieRoundedCorner339 void prepare() 340 { 341 LottieObject::type = LottieObject::RoundedCorner; 342 } 343 propertyLottieRoundedCorner344 LottieProperty* property(uint16_t ix) override 345 { 346 if (radius.ix == ix) return &radius; 347 return nullptr; 348 } 349 350 LottieFloat radius = 0.0f; 351 }; 352 353 354 struct LottiePath : LottieShape 355 { prepareLottiePath356 void prepare() 357 { 358 LottieShape::prepare(LottieObject::Path); 359 } 360 propertyLottiePath361 LottieProperty* property(uint16_t ix) override 362 { 363 if (pathset.ix == ix) return &pathset; 364 return nullptr; 365 } 366 367 LottiePathSet pathset; 368 }; 369 370 371 struct LottieRect : LottieShape 372 { prepareLottieRect373 void prepare() 374 { 375 LottieShape::prepare(LottieObject::Rect); 376 } 377 propertyLottieRect378 LottieProperty* property(uint16_t ix) override 379 { 380 if (position.ix == ix) return &position; 381 if (size.ix == ix) return &size; 382 if (radius.ix == ix) return &radius; 383 return nullptr; 384 } 385 386 LottiePosition position = Point{0.0f, 0.0f}; 387 LottiePoint size = Point{0.0f, 0.0f}; 388 LottieFloat radius = 0.0f; //rounded corner radius 389 }; 390 391 392 struct LottiePolyStar : LottieShape 393 { 394 enum Type : uint8_t {Star = 1, Polygon}; 395 prepareLottiePolyStar396 void prepare() 397 { 398 LottieShape::prepare(LottieObject::Polystar); 399 } 400 propertyLottiePolyStar401 LottieProperty* property(uint16_t ix) override 402 { 403 if (position.ix == ix) return &position; 404 if (innerRadius.ix == ix) return &innerRadius; 405 if (outerRadius.ix == ix) return &outerRadius; 406 if (innerRoundness.ix == ix) return &innerRoundness; 407 if (outerRoundness.ix == ix) return &outerRoundness; 408 if (rotation.ix == ix) return &rotation; 409 if (ptsCnt.ix == ix) return &ptsCnt; 410 return nullptr; 411 } 412 413 LottiePosition position = Point{0.0f, 0.0f}; 414 LottieFloat innerRadius = 0.0f; 415 LottieFloat outerRadius = 0.0f; 416 LottieFloat innerRoundness = 0.0f; 417 LottieFloat outerRoundness = 0.0f; 418 LottieFloat rotation = 0.0f; 419 LottieFloat ptsCnt = 0.0f; 420 Type type = Polygon; 421 }; 422 423 424 struct LottieEllipse : LottieShape 425 { prepareLottieEllipse426 void prepare() 427 { 428 LottieShape::prepare(LottieObject::Ellipse); 429 } 430 propertyLottieEllipse431 LottieProperty* property(uint16_t ix) override 432 { 433 if (position.ix == ix) return &position; 434 if (size.ix == ix) return &size; 435 return nullptr; 436 } 437 438 LottiePosition position = Point{0.0f, 0.0f}; 439 LottiePoint size = Point{0.0f, 0.0f}; 440 }; 441 442 443 struct LottieTransform : LottieObject 444 { 445 struct SeparateCoord 446 { 447 LottieFloat x = 0.0f; 448 LottieFloat y = 0.0f; 449 }; 450 451 struct RotationEx 452 { 453 LottieFloat x = 0.0f; 454 LottieFloat y = 0.0f; 455 }; 456 ~LottieTransformLottieTransform457 ~LottieTransform() 458 { 459 delete(coords); 460 delete(rotationEx); 461 } 462 prepareLottieTransform463 void prepare() 464 { 465 LottieObject::type = LottieObject::Transform; 466 } 467 mergeableLottieTransform468 bool mergeable() override 469 { 470 if (!opacity.frames && opacity.value == 255) return true; 471 return false; 472 } 473 propertyLottieTransform474 LottieProperty* property(uint16_t ix) override 475 { 476 if (position.ix == ix) return &position; 477 if (rotation.ix == ix) return &rotation; 478 if (scale.ix == ix) return &scale; 479 if (anchor.ix == ix) return &anchor; 480 if (opacity.ix == ix) return &opacity; 481 if (skewAngle.ix == ix) return &skewAngle; 482 if (skewAxis.ix == ix) return &skewAxis; 483 if (coords) { 484 if (coords->x.ix == ix) return &coords->x; 485 if (coords->y.ix == ix) return &coords->y; 486 } 487 return nullptr; 488 } 489 490 LottiePosition position = Point{0.0f, 0.0f}; 491 LottieFloat rotation = 0.0f; //z rotation 492 LottiePoint scale = Point{100.0f, 100.0f}; 493 LottiePoint anchor = Point{0.0f, 0.0f}; 494 LottieOpacity opacity = 255; 495 LottieFloat skewAngle = 0.0f; 496 LottieFloat skewAxis = 0.0f; 497 498 SeparateCoord* coords = nullptr; //either a position or separate coordinates 499 RotationEx* rotationEx = nullptr; //extension for 3d rotation 500 }; 501 502 503 struct LottieSolid : LottieObject 504 { 505 LottieColor color = RGB24{255, 255, 255}; 506 LottieOpacity opacity = 255; 507 propertyLottieSolid508 LottieProperty* property(uint16_t ix) override 509 { 510 if (color.ix == ix) return &color; 511 if (opacity.ix == ix) return &opacity; 512 return nullptr; 513 } 514 }; 515 516 517 struct LottieSolidStroke : LottieSolid, LottieStroke 518 { prepareLottieSolidStroke519 void prepare() 520 { 521 LottieObject::type = LottieObject::SolidStroke; 522 } 523 propertyLottieSolidStroke524 LottieProperty* property(uint16_t ix) override 525 { 526 if (width.ix == ix) return &width; 527 if (dashattr) { 528 if (dashattr->value[0].ix == ix) return &dashattr->value[0]; 529 if (dashattr->value[1].ix == ix) return &dashattr->value[1]; 530 if (dashattr->value[2].ix == ix) return &dashattr->value[2]; 531 } 532 return LottieSolid::property(ix); 533 } 534 overrideLottieSolidStroke535 void override(LottieProperty* prop) override 536 { 537 this->color = *static_cast<LottieColor*>(prop); 538 this->prepare(); 539 } 540 }; 541 542 543 struct LottieSolidFill : LottieSolid 544 { prepareLottieSolidFill545 void prepare() 546 { 547 LottieObject::type = LottieObject::SolidFill; 548 } 549 overrideLottieSolidFill550 void override(LottieProperty* prop) override 551 { 552 this->color = *static_cast<LottieColor*>(prop); 553 this->prepare(); 554 } 555 556 FillRule rule = FillRule::Winding; 557 }; 558 559 560 struct LottieGradient : LottieObject 561 { prepareLottieGradient562 bool prepare() 563 { 564 if (!colorStops.populated) { 565 auto count = colorStops.count; //colorstop count can be modified after population 566 if (colorStops.frames) { 567 for (auto v = colorStops.frames->begin(); v < colorStops.frames->end(); ++v) { 568 colorStops.count = populate(v->value, count); 569 } 570 } else { 571 colorStops.count = populate(colorStops.value, count); 572 } 573 colorStops.populated = true; 574 } 575 if (start.frames || end.frames || height.frames || angle.frames || opacity.frames || colorStops.frames) return true; 576 return false; 577 } 578 propertyLottieGradient579 LottieProperty* property(uint16_t ix) override 580 { 581 if (start.ix == ix) return &start; 582 if (end.ix == ix) return &end; 583 if (height.ix == ix) return &height; 584 if (angle.ix == ix) return ∠ 585 if (opacity.ix == ix) return &opacity; 586 if (colorStops.ix == ix) return &colorStops; 587 return nullptr; 588 } 589 590 591 uint32_t populate(ColorStop& color, size_t count); 592 Fill* fill(float frameNo, LottieExpressions* exps); 593 594 LottiePoint start = Point{0.0f, 0.0f}; 595 LottiePoint end = Point{0.0f, 0.0f}; 596 LottieFloat height = 0.0f; 597 LottieFloat angle = 0.0f; 598 LottieOpacity opacity = 255; 599 LottieColorStop colorStops; 600 uint8_t id = 0; //1: linear, 2: radial 601 }; 602 603 604 struct LottieGradientFill : LottieGradient 605 { prepareLottieGradientFill606 void prepare() 607 { 608 LottieObject::type = LottieObject::GradientFill; 609 LottieGradient::prepare(); 610 } 611 overrideLottieGradientFill612 void override(LottieProperty* prop) override 613 { 614 this->colorStops = *static_cast<LottieColorStop*>(prop); 615 this->prepare(); 616 } 617 618 FillRule rule = FillRule::Winding; 619 }; 620 621 622 struct LottieGradientStroke : LottieGradient, LottieStroke 623 { prepareLottieGradientStroke624 void prepare() 625 { 626 LottieObject::type = LottieObject::GradientStroke; 627 LottieGradient::prepare(); 628 } 629 propertyLottieGradientStroke630 LottieProperty* property(uint16_t ix) override 631 { 632 if (width.ix == ix) return &width; 633 if (dashattr) { 634 if (dashattr->value[0].ix == ix) return &dashattr->value[0]; 635 if (dashattr->value[1].ix == ix) return &dashattr->value[1]; 636 if (dashattr->value[2].ix == ix) return &dashattr->value[2]; 637 } 638 return LottieGradient::property(ix); 639 } 640 overrideLottieGradientStroke641 void override(LottieProperty* prop) override 642 { 643 this->colorStops = *static_cast<LottieColorStop*>(prop); 644 this->prepare(); 645 } 646 }; 647 648 649 struct LottieImage : LottieObject, LottieRenderPooler<tvg::Picture> 650 { 651 union { 652 char* b64Data = nullptr; 653 char* path; 654 }; 655 char* mimeType = nullptr; 656 uint32_t size = 0; 657 float width = 0.0f; 658 float height = 0.0f; 659 660 ~LottieImage(); 661 void prepare(); 662 }; 663 664 665 struct LottieRepeater : LottieObject 666 { prepareLottieRepeater667 void prepare() 668 { 669 LottieObject::type = LottieObject::Repeater; 670 } 671 propertyLottieRepeater672 LottieProperty* property(uint16_t ix) override 673 { 674 if (copies.ix == ix) return &copies; 675 if (offset.ix == ix) return &offset; 676 if (position.ix == ix) return &position; 677 if (rotation.ix == ix) return &rotation; 678 if (scale.ix == ix) return &scale; 679 if (anchor.ix == ix) return &anchor; 680 if (startOpacity.ix == ix) return &startOpacity; 681 if (endOpacity.ix == ix) return &endOpacity; 682 return nullptr; 683 } 684 685 LottieFloat copies = 0.0f; 686 LottieFloat offset = 0.0f; 687 688 //Transform 689 LottiePosition position = Point{0.0f, 0.0f}; 690 LottieFloat rotation = 0.0f; 691 LottiePoint scale = Point{100.0f, 100.0f}; 692 LottiePoint anchor = Point{0.0f, 0.0f}; 693 LottieOpacity startOpacity = 255; 694 LottieOpacity endOpacity = 255; 695 bool inorder = true; //true: higher, false: lower 696 }; 697 698 699 struct LottieOffsetPath : LottieObject 700 { prepareLottieOffsetPath701 void prepare() 702 { 703 LottieObject::type = LottieObject::OffsetPath; 704 } 705 706 LottieFloat offset = 0.0f; 707 LottieFloat miterLimit = 4.0f; 708 StrokeJoin join = StrokeJoin::Miter; 709 }; 710 711 712 struct LottieGroup : LottieObject, LottieRenderPooler<tvg::Shape> 713 { 714 LottieGroup(); 715 ~LottieGroupLottieGroup716 virtual ~LottieGroup() 717 { 718 for (auto p = children.begin(); p < children.end(); ++p) delete(*p); 719 } 720 721 void prepare(LottieObject::Type type = LottieObject::Group); mergeableLottieGroup722 bool mergeable() override { return allowMerge; } 723 contentLottieGroup724 LottieObject* content(unsigned long id) 725 { 726 if (this->id == id) return this; 727 728 //source has children, find recursively. 729 for (auto c = children.begin(); c < children.end(); ++c) { 730 auto child = *c; 731 if (child->type == LottieObject::Type::Group || child->type == LottieObject::Type::Layer) { 732 if (auto ret = static_cast<LottieGroup*>(child)->content(id)) return ret; 733 } else if (child->id == id) return child; 734 } 735 return nullptr; 736 } 737 738 Scene* scene = nullptr; 739 Array<LottieObject*> children; 740 741 bool reqFragment : 1; //requirement to fragment the render context 742 bool buildDone : 1; //completed in building the composition. 743 bool trimpath : 1; //this group has a trimpath. 744 bool visible : 1; //this group has visible contents. 745 bool allowMerge : 1; //if this group is consisted of simple (transformed) shapes. 746 }; 747 748 749 struct LottieLayer : LottieGroup 750 { 751 enum Type : uint8_t {Precomp = 0, Solid, Image, Null, Shape, Text}; 752 753 ~LottieLayer(); 754 opacityLottieLayer755 uint8_t opacity(float frameNo) 756 { 757 //return zero if the visibility is false. 758 if (type == Null) return 255; 759 return transform->opacity(frameNo); 760 } 761 mergeableLottieLayer762 bool mergeable() override { return false; } 763 764 void prepare(RGB24* color = nullptr); 765 float remap(LottieComposition* comp, float frameNo, LottieExpressions* exp); 766 767 char* name = nullptr; 768 LottieLayer* parent = nullptr; 769 LottieFloat timeRemap = 0.0f; 770 LottieLayer* comp = nullptr; //Precompositor, current layer is belonges. 771 LottieTransform* transform = nullptr; 772 Array<LottieMask*> masks; 773 Array<LottieEffect*> effects; 774 LottieLayer* matteTarget = nullptr; 775 776 LottieRenderPooler<tvg::Shape> statical; //static pooler for solid fill and clipper 777 778 float timeStretch = 1.0f; 779 float w = 0.0f, h = 0.0f; 780 float inFrame = 0.0f; 781 float outFrame = 0.0f; 782 float startFrame = 0.0f; 783 unsigned long rid = 0; //pre-composition reference id. 784 int16_t mid = -1; //id of the matte layer. 785 int16_t pidx = -1; //index of the parent layer. 786 int16_t idx = -1; //index of the current layer. 787 788 struct { 789 float frameNo = -1.0f; 790 Matrix matrix; 791 uint8_t opacity; 792 } cache; 793 794 CompositeMethod matteType = CompositeMethod::None; 795 BlendMethod blendMethod = BlendMethod::Normal; 796 Type type = Null; 797 bool autoOrient = false; 798 bool matteSrc = false; 799 layerByIdLottieLayer800 LottieLayer* layerById(unsigned long id) 801 { 802 for (auto child = children.begin(); child < children.end(); ++child) { 803 if ((*child)->type != LottieObject::Type::Layer) continue; 804 auto layer = static_cast<LottieLayer*>(*child); 805 if (layer->id == id) return layer; 806 } 807 return nullptr; 808 } 809 layerByIdxLottieLayer810 LottieLayer* layerByIdx(int16_t idx) 811 { 812 for (auto child = children.begin(); child < children.end(); ++child) { 813 if ((*child)->type != LottieObject::Type::Layer) continue; 814 auto layer = static_cast<LottieLayer*>(*child); 815 if (layer->idx == idx) return layer; 816 } 817 return nullptr; 818 } 819 }; 820 821 822 struct LottieSlot 823 { 824 struct Pair { 825 LottieObject* obj; 826 LottieProperty* prop; 827 }; 828 829 void assign(LottieObject* target); 830 void reset(); 831 LottieSlotLottieSlot832 LottieSlot(char* sid, LottieObject* obj, LottieProperty::Type type) : sid(sid), type(type) 833 { 834 pairs.push({obj, 0}); 835 } 836 ~LottieSlotLottieSlot837 ~LottieSlot() 838 { 839 free(sid); 840 if (!overridden) return; 841 for (auto pair = pairs.begin(); pair < pairs.end(); ++pair) { 842 delete(pair->prop); 843 } 844 } 845 846 char* sid; 847 Array<Pair> pairs; 848 LottieProperty::Type type; 849 bool overridden = false; 850 }; 851 852 853 struct LottieComposition 854 { 855 ~LottieComposition(); 856 durationLottieComposition857 float duration() const 858 { 859 return frameCnt() / frameRate; // in second 860 } 861 frameAtTimeLottieComposition862 float frameAtTime(float timeInSec) const 863 { 864 auto p = timeInSec / duration(); 865 if (p < 0.0f) p = 0.0f; 866 return p * frameCnt(); 867 } 868 timeAtFrameLottieComposition869 float timeAtFrame(float frameNo) 870 { 871 return (frameNo - root->inFrame) / frameRate; 872 } 873 frameCntLottieComposition874 float frameCnt() const 875 { 876 return root->outFrame - root->inFrame; 877 } 878 assetLottieComposition879 LottieLayer* asset(unsigned long id) 880 { 881 for (auto asset = assets.begin(); asset < assets.end(); ++asset) { 882 auto layer = static_cast<LottieLayer*>(*asset); 883 if (layer->id == id) return layer; 884 } 885 return nullptr; 886 } 887 888 LottieLayer* root = nullptr; 889 char* version = nullptr; 890 char* name = nullptr; 891 float w, h; 892 float frameRate; 893 Array<LottieObject*> assets; 894 Array<LottieInterpolator*> interpolators; 895 Array<LottieFont*> fonts; 896 Array<LottieSlot*> slots; 897 Array<LottieMarker*> markers; 898 bool expressions = false; 899 bool initiated = false; 900 }; 901 902 #endif //_TVG_LOTTIE_MODEL_H_ 903 904 #endif /* LV_USE_THORVG_INTERNAL */ 905 906