<commit_before>﻿using System;
using System.Collections.Generic;
using Windows.Foundation;
using LottieUWP.Animation.Content;
using LottieUWP.Animation.Keyframe;
using LottieUWP.Value;

namespace LottieUWP.Model.Layer
{
    internal class CompositionLayer : BaseLayer
    {
        private IBaseKeyframeAnimation<float?, float?> _timeRemapping;
        private readonly List<BaseLayer> _layers = new List<BaseLayer>();
        private Rect _newClipRect;

        private bool? _hasMatte;
        private bool? _hasMasks;

        internal CompositionLayer(LottieDrawable lottieDrawable, Layer layerModel, List<Layer> layerModels, LottieComposition composition) : base(lottieDrawable, layerModel)
        {
            var timeRemapping = layerModel.TimeRemapping;
            if (timeRemapping != null)
            {
                _timeRemapping = timeRemapping.CreateAnimation();
                AddAnimation(_timeRemapping);
                _timeRemapping.ValueChanged += OnValueChanged;
            }
            else
            {
                _timeRemapping = null;
            }

            var layerMap = new Dictionary<long, BaseLayer>(composition.Layers.Count);

            BaseLayer mattedLayer = null;
            for (var i = layerModels.Count - 1; i >= 0; i--)
            {
                var lm = layerModels[i];
                var layer = ForModel(lm, lottieDrawable, composition);
                if (layer == null)
                {
                    continue;
                }
                layerMap[layer.LayerModel.Id] = layer;
                if (mattedLayer != null)
                {
                    mattedLayer.MatteLayer = layer;
                    mattedLayer = null;
                }
                else
                {
                    _layers.Insert(0, layer);
                    switch (lm.GetMatteType())
                    {
                        case Layer.MatteType.Add:
                        case Layer.MatteType.Invert:
                            mattedLayer = layer;
                            break;
                    }
                }
            }

            foreach (var layer in layerMap)
            {
                var layerView = layer.Value;
                AssertNonNullForGitHubIssue(layerMap, layerView);
                if (layerMap.TryGetValue(layerView.LayerModel.ParentId, out BaseLayer parentLayer))
                {
                    layerView.ParentLayer = parentLayer;
                }
            }
        }

        /// <summary>
        /// Extra logging for https://github.com/airbnb/lottie-android/issues/524 
        /// </summary>
        /// <param name="layerMap"></param>
        /// <param name="layerView"></param>
        private void AssertNonNullForGitHubIssue(Dictionary<long, BaseLayer> layerMap, BaseLayer layerView)
        {
            if (layerMap == null)
            {
                throw new NullReferenceException("layerMap is null!");
            }
            else if (layerView == null)
            {
                throw new NullReferenceException("layerView is null!");
            }
            else if (layerView.LayerModel == null)
            {
                throw new NullReferenceException("layerModel is null!");
            }
        }

        public override void DrawLayer(BitmapCanvas canvas, Matrix3X3 parentMatrix, byte parentAlpha)
        {
            LottieLog.BeginSection("CompositionLayer.Draw");
            canvas.Save();
            RectExt.Set(ref _newClipRect, 0, 0, LayerModel.PreCompWidth, LayerModel.PreCompHeight);
            parentMatrix.MapRect(ref _newClipRect);

            for (var i = _layers.Count - 1; i >= 0; i--)
            {
                var nonEmptyClip = true;
                if (!_newClipRect.IsEmpty)
                {
                    nonEmptyClip = canvas.ClipRect(_newClipRect);
                }
                if (nonEmptyClip)
                {
                    var layer = _layers[i];
                    layer.Draw(canvas, parentMatrix, parentAlpha);
                }
            }
            canvas.Restore();<commit_msg>Ignore null parent layers.<commit_after>﻿using System;
using System.Collections.Generic;
using Windows.Foundation;
using LottieUWP.Animation.Content;
using LottieUWP.Animation.Keyframe;
using LottieUWP.Value;

namespace LottieUWP.Model.Layer
{
    internal class CompositionLayer : BaseLayer
    {
        private IBaseKeyframeAnimation<float?, float?> _timeRemapping;
        private readonly List<BaseLayer> _layers = new List<BaseLayer>();
        private Rect _newClipRect;

        private bool? _hasMatte;
        private bool? _hasMasks;

        internal CompositionLayer(LottieDrawable lottieDrawable, Layer layerModel, List<Layer> layerModels, LottieComposition composition) : base(lottieDrawable, layerModel)
        {
            var timeRemapping = layerModel.TimeRemapping;
            if (timeRemapping != null)
            {
                _timeRemapping = timeRemapping.CreateAnimation();
                AddAnimation(_timeRemapping);
                _timeRemapping.ValueChanged += OnValueChanged;
            }
            else
            {
                _timeRemapping = null;
            }

            var layerMap = new Dictionary<long, BaseLayer>(composition.Layers.Count);

            BaseLayer mattedLayer = null;
            for (var i = layerModels.Count - 1; i >= 0; i--)
            {
                var lm = layerModels[i];
                var layer = ForModel(lm, lottieDrawable, composition);
                if (layer == null)
                {
                    continue;
                }
                layerMap[layer.LayerModel.Id] = layer;
                if (mattedLayer != null)
                {
                    mattedLayer.MatteLayer = layer;
                    mattedLayer = null;
                }
                else
                {
                    _layers.Insert(0, layer);
                    switch (lm.GetMatteType())
                    {
                        case Layer.MatteType.Add:
                        case Layer.MatteType.Invert:
                            mattedLayer = layer;
                            break;
                    }
                }
            }

            foreach (var layer in layerMap)
            {
                var layerView = layer.Value;
                // This shouldn't happen but it appears as if sometimes on pre-lollipop devices when 
                // compiled with d8, layerView is null sometimes. 
                // https://github.com/airbnb/lottie-android/issues/524 
                if (layerView == null)
                {
                    continue;
                }
                if (layerMap.TryGetValue(layerView.LayerModel.ParentId, out BaseLayer parentLayer))
                {
                    layerView.ParentLayer = parentLayer;
                }
            }
        }

        public override void DrawLayer(BitmapCanvas canvas, Matrix3X3 parentMatrix, byte parentAlpha)
        {
            LottieLog.BeginSection("CompositionLayer.Draw");
            canvas.Save();
            RectExt.Set(ref _newClipRect, 0, 0, LayerModel.PreCompWidth, LayerModel.PreCompHeight);
            parentMatrix.MapRect(ref _newClipRect);

            for (var i = _layers.Count - 1; i >= 0; i--)
            {
                var nonEmptyClip = true;
                if (!_newClipRect.IsEmpty)
                {
                    nonEmptyClip = canvas.ClipRect(_newClipRect);
                }
                if (nonEmptyClip)
                {
                    var layer = _layers[i];
                    layer.Draw(canvas, parentMatrix, parentAlpha);
                }
            }
            canvas.Restore();
{'fraction_non_alphanumeric': 0.08106372045220966, 'fraction_numerical': 0.003211716341212744, 'mean_word_length': 1.358376249621327, 'pattern_counts': {'":': 0, '<': 20, '<?xml version=': 0, '>': 24, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5513633', 'n_tokens_mistral': 2007, 'n_tokens_neox': 1875, 'n_words': 410}