//public int Opacity
        //{
        //    get
        //    {
        //        return PixelFormat.TRANSLUCENT;
        //    }
        //}

        private void CanvasControlOnDraw(ICanvasAnimatedControl canvasControl, CanvasAnimatedDrawEventArgs args)
        {
            lock (this)
            {
                if (_bitmapCanvas == null)
                {
                    return;
                }

                using (_bitmapCanvas.CreateSession(canvasControl.Device, canvasControl.Size.Width, canvasControl.Size.Height, args.DrawingSession))
                {
                    _bitmapCanvas.Clear(Colors.Transparent);
                    LottieLog.BeginSection("Drawable.Draw");
                    if (_compositionLayer == null)
                    {
                        return;
                    }

                    var   scale      = _scale;
                    float extraScale = 1f;

                    float maxScale = GetMaxScale(_bitmapCanvas);
                    if (scale > maxScale)
                    {
                        scale      = maxScale;
                        extraScale = _scale / scale;
                    }

                    if (extraScale > 1)
                    {
                        // This is a bit tricky...
                        // We can't draw on a canvas larger than ViewConfiguration.get(context).getScaledMaximumDrawingCacheSize()
                        // which works out to be roughly the size of the screen because Android can't generate a
                        // bitmap large enough to render to.
                        // As a result, we cap the scale such that it will never be wider/taller than the screen
                        // and then only render in the top left corner of the canvas. We then use extraScale
                        // to scale up the rest of the scale. However, since we rendered the animation to the top
                        // left corner, we need to scale up and translate the canvas to zoom in on the top left
                        // corner.
                        _bitmapCanvas.Save();
                        float halfWidth        = (float)_composition.Bounds.Width / 2f;
                        float halfHeight       = (float)_composition.Bounds.Height / 2f;
                        float scaledHalfWidth  = halfWidth * scale;
                        float scaledHalfHeight = halfHeight * scale;
                        _bitmapCanvas.Translate(
                            Scale * halfWidth - scaledHalfWidth,
                            Scale * halfHeight - scaledHalfHeight);
                        _bitmapCanvas.Scale(extraScale, extraScale, scaledHalfWidth, scaledHalfHeight);
                    }

                    _matrix.Reset();
                    _matrix = MatrixExt.PreScale(_matrix, scale, scale);
                    _compositionLayer.Draw(_bitmapCanvas, _matrix, _alpha);
                    LottieLog.EndSection("Drawable.Draw");

                    if (extraScale > 1)
                    {
                        _bitmapCanvas.Restore();
                    }
                }
            }
        }
Exemple #2
0
        internal static void ApplyTrimPathIfNeeded(Path path, float startValue, float endValue, float offsetValue)
        {
            LottieLog.BeginSection("applyTrimPathIfNeeded");
            PathMeasure.SetPath(path);

            var length = PathMeasure.Length;

            if (startValue == 1f && endValue == 0f)
            {
                LottieLog.EndSection("applyTrimPathIfNeeded");
                return;
            }
            if (length == 0f || Math.Abs(endValue - startValue - 1) < .01)
            {
                LottieLog.EndSection("applyTrimPathIfNeeded");
                return;
            }
            var start    = length * startValue;
            var end      = length * endValue;
            var newStart = Math.Min(start, end);
            var newEnd   = Math.Max(start, end);

            var offset = offsetValue * length;

            newStart += offset;
            newEnd   += offset;

            // If the trim path has rotated around the path, we need to shift it back.
            if (newStart >= length && newEnd >= length)
            {
                newStart = MiscUtils.FloorMod(newStart, length);
                newEnd   = MiscUtils.FloorMod(newEnd, length);
            }

            if (newStart < 0)
            {
                newStart = MiscUtils.FloorMod(newStart, length);
            }
            if (newEnd < 0)
            {
                newEnd = MiscUtils.FloorMod(newEnd, length);
            }

            // If the start and end are equals, return an empty path.
            if (newStart == newEnd)
            {
                path.Reset();
                LottieLog.EndSection("applyTrimPathIfNeeded");
                return;
            }

            if (newStart >= newEnd)
            {
                newStart -= length;
            }

            _tempPath.Reset();
            PathMeasure.GetSegment(newStart, newEnd, ref _tempPath, true);

            if (newEnd > length)
            {
                _tempPath2.Reset();
                PathMeasure.GetSegment(0, newEnd % length, ref _tempPath2, true);
                _tempPath.AddPath(_tempPath2);
            }
            else if (newStart < 0)
            {
                _tempPath2.Reset();
                PathMeasure.GetSegment(length + newStart, length, ref _tempPath2, true);
                _tempPath.AddPath(_tempPath2);
            }
            path.Set(_tempPath);
            LottieLog.EndSection("applyTrimPathIfNeeded");
        }