Пример #1
0
        public CanvasCommandList GetCanvasImage(ICanvasResourceCreator resourceCreator, float scaleX, float scaleY)
        {
            lock (this)
            {
                var commandList = new CanvasCommandList(resourceCreator);
                using (var session = commandList.CreateDrawingSession())
                {
                    var width  = _composition.Bounds.Width * scaleX;
                    var height = _composition.Bounds.Height * scaleY;
                    if (_bitmapCanvas == null || _bitmapCanvas.Width < width || _bitmapCanvas.Height < height)
                    {
                        _bitmapCanvas?.Dispose();
                        _bitmapCanvas = new BitmapCanvas(width, height);
                    }

                    using (_bitmapCanvas.CreateSession(resourceCreator.Device, (float)width,
                                                       (float)height, session))
                    {
                        _bitmapCanvas.Clear(Colors.Transparent);
                        LottieLog.BeginSection("Drawable.Draw");
                        if (_compositionLayer == null)
                        {
                            return(null);
                        }

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

                return(commandList);
            }
        }
Пример #2
0
 public virtual void GetBounds(out Rect outBounds, Matrix3X3 parentMatrix)
 {
     _matrix.Set(parentMatrix);
     if (_transformAnimation != null)
     {
         _matrix = MatrixExt.PreConcat(_matrix, _transformAnimation.Matrix);
     }
     RectExt.Set(ref _rect, 0, 0, 0, 0);
     for (var i = _contents.Count - 1; i >= 0; i--)
     {
         if (_contents[i] is IDrawingContent drawingContent)
         {
             drawingContent.GetBounds(out _rect, _matrix);
             if (outBounds.IsEmpty)
             {
                 RectExt.Set(ref outBounds, _rect);
             }
             else
             {
                 RectExt.Set(ref outBounds,
                             Math.Min(outBounds.Left, _rect.Left),
                             Math.Min(outBounds.Top, _rect.Top),
                             Math.Max(outBounds.Right, _rect.Right),
                             Math.Max(outBounds.Bottom, _rect.Bottom));
             }
         }
     }
 }
Пример #3
0
        //public int Opacity
        //{
        //    get
        //    {
        //        return PixelFormat.TRANSLUCENT;
        //    }
        //}

        private void CanvasControlOnDraw(ICanvasAnimatedControl canvasControl, CanvasAnimatedDrawEventArgs args)
        {
            lock (this)
            {
                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();
                    }
                }
            }
        }
Пример #4
0
        private static void Draw(CanvasDevice device, BitmapCanvas bitmapCanvas, CompositionLayer compositionLayer, Rect bounds, float scale, byte alpha, Matrix3X3 matrix, double width, double height, CanvasDrawingSession canvasDrawingSession)
        {
            using (bitmapCanvas.CreateSession(device, width, height, canvasDrawingSession))
            {
                bitmapCanvas.Clear(Colors.Transparent);
                LottieLog.BeginSection("Drawable.Draw");
                if (compositionLayer == null)
                {
                    return;
                }

                var   localScale = scale;
                float extraScale = 1f;

                float maxScale = GetMaxScale(bitmapCanvas, bounds);
                if (localScale > maxScale)
                {
                    localScale = maxScale;
                    extraScale = scale / localScale;
                }

                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)bounds.Width / 2f;
                    float halfHeight       = (float)bounds.Height / 2f;
                    float scaledHalfWidth  = halfWidth * localScale;
                    float scaledHalfHeight = halfHeight * localScale;
                    bitmapCanvas.Translate(
                        scale * halfWidth - scaledHalfWidth,
                        scale * halfHeight - scaledHalfHeight);
                    bitmapCanvas.Scale(extraScale, extraScale, scaledHalfWidth, scaledHalfHeight);
                }

                matrix.Reset();
                matrix = MatrixExt.PreScale(matrix, localScale, localScale);
                compositionLayer.Draw(bitmapCanvas, matrix, alpha);
                LottieLog.EndSection("Drawable.Draw");

                if (extraScale > 1)
                {
                    bitmapCanvas.Restore();
                }
            }
        }
Пример #5
0
        //public int Opacity
        //{
        //    get
        //    {
        //        return PixelFormat.TRANSLUCENT;
        //    }
        //}

        private void CanvasControlOnDraw(ICanvasAnimatedControl canvasControl, CanvasAnimatedDrawEventArgs args)
        {
            lock (this)
            {
                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;
                    var   hasExtraScale = false;
                    float maxScale      = GetMaxScale(_bitmapCanvas);
                    if (_compositionLayer.HasMatte() || _compositionLayer.HasMasks())
                    {
                        // Since we can only scale up the animation so much before masks and mattes get clipped, we
                        // may have to scale the canvas to fake the rest. This isn't a problem for software rendering
                        // but hardware accelerated scaling is rasterized so it will appear pixelated.
                        extraScale = scale / maxScale;
                        scale      = Math.Min(scale, maxScale);
                        // This check fixes some floating point rounding issues.
                        hasExtraScale = extraScale > 1.001f;
                    }

                    if (hasExtraScale)
                    {
                        _bitmapCanvas.Save();
                        // This is extraScale ^2 because what happens is when the scale increases, the intrinsic size
                        // of the view increases. That causes the drawable to keep growing even though we are only
                        // rendering to the size of the view in the top left quarter, leaving the rest blank.
                        // The first scale by extraScale scales up the canvas so that we are back at the original
                        // size. The second extraScale is what actually has the scaling effect.
                        float extraScaleSquared = extraScale * extraScale;
                        int   px = (int)(_composition.Bounds.Width * scale / 2f);
                        int   py = (int)(_composition.Bounds.Height * scale / 2f);
                        _bitmapCanvas.Scale(extraScaleSquared, extraScaleSquared, px, py);
                    }

                    _matrix.Reset();
                    _matrix = MatrixExt.PreScale(_matrix, scale, scale);
                    _compositionLayer.Draw(_bitmapCanvas, _matrix, _alpha);
                    if (hasExtraScale)
                    {
                        _bitmapCanvas.Restore();
                    }
                    LottieLog.EndSection("Drawable.Draw");
                }
            }
        }
Пример #6
0
        public void Draw(BitmapCanvas canvas, DenseMatrix parentMatrix, byte alpha)
        {
            var copies       = _copies.Value.Value;
            var offset       = _offset.Value.Value;
            var startOpacity = _transform.StartOpacity.Value.Value / 100f;
            var endOpacity   = _transform.EndOpacity.Value.Value / 100f;

            for (var i = (int)copies - 1; i >= 0; i--)
            {
                _matrix.Set(parentMatrix);
                _matrix = MatrixExt.PreConcat(_matrix, _transform.GetMatrixForRepeater(i + offset));
                float newAlpha = alpha * MiscUtils.Lerp(startOpacity, endOpacity, i / copies);
                _contentGroup.Draw(canvas, _matrix, (byte)newAlpha);
            }
        }
Пример #7
0
        /**
         * TODO: see if we can use this for the main get_Matrix method.
         */
        internal Matrix3X3 GetMatrixForRepeater(float amount)
        {
            var position    = _position.Value;
            var anchorPoint = _anchorPoint.Value;
            var scale       = _scale.Value;
            var rotation    = _rotation.Value.Value;

            _matrix.Reset();
            _matrix = MatrixExt.PreTranslate(_matrix, position.Value.X * amount, position.Value.Y * amount);
            _matrix = MatrixExt.PreScale(_matrix,
                                         (float)Math.Pow(scale.ScaleX, amount),
                                         (float)Math.Pow(scale.ScaleY, amount));
            _matrix = MatrixExt.PreRotate(_matrix, rotation * amount, anchorPoint.Value.X, anchorPoint.Value.Y);

            return(_matrix);
        }
Пример #8
0
        //public int Opacity
        //{
        //    get
        //    {
        //        return PixelFormat.TRANSLUCENT;
        //    }
        //}

        public void Draw(BitmapCanvas canvas)
        {
            if (_compositionLayer == null)
            {
                return;
            }
            var scale = _scale;

            if (_compositionLayer.HasMatte())
            {
                scale = Math.Min(_scale, GetMaxScale(canvas));
            }

            _matrix.Reset();
            _matrix = MatrixExt.PreScale(_matrix, scale, scale);
            _compositionLayer.Draw(canvas, _matrix, _alpha);
        }
Пример #9
0
        //public int Opacity
        //{
        //    get
        //    {
        //        return PixelFormat.TRANSLUCENT;
        //    }
        //}

        public void Draw(BitmapCanvas canvas)
        {
            LottieLog.BeginSection("Drawable.Draw");
            if (_compositionLayer == null)
            {
                return;
            }
            var scale = _scale;

            if (_compositionLayer.HasMatte())
            {
                scale = Math.Min(_scale, GetMaxScale(canvas));
            }

            _matrix.Reset();
            _matrix = MatrixExt.PreScale(_matrix, scale, scale);
            _compositionLayer.Draw(canvas, _matrix, _alpha);
            LottieLog.EndSection("Drawable.Draw");
        }
Пример #10
0
        public virtual void Draw(BitmapCanvas canvas, Matrix3X3 parentMatrix, byte parentAlpha)
        {
            _matrix.Set(parentMatrix);
            byte alpha;

            if (_transformAnimation != null)
            {
                _matrix = MatrixExt.PreConcat(_matrix, _transformAnimation.Matrix);
                alpha   = (byte)(_transformAnimation.Opacity.Value / 100f * parentAlpha / 255f * 255);
            }
            else
            {
                alpha = parentAlpha;
            }

            for (var i = _contents.Count - 1; i >= 0; i--)
            {
                var drawingContent = _contents[i] as IDrawingContent;
                drawingContent?.Draw(canvas, _matrix, alpha);
            }
        }
Пример #11
0
        private void DrawCharacterAsGlyph(FontCharacter character, Matrix3X3 parentMatrix, float fontScale, DocumentData documentData, BitmapCanvas canvas)
        {
            var contentGroups = GetContentsForCharacter(character);

            for (var j = 0; j < contentGroups.Count; j++)
            {
                var path = contentGroups[j].Path;
                //path.ComputeBounds(out _rectF);
                Matrix.Set(parentMatrix);
                Matrix = MatrixExt.PreScale(Matrix, fontScale, fontScale);
                path.Transform(Matrix);
                if (documentData.StrokeOverFill)
                {
                    DrawGlyph(path, _fillPaint, canvas);
                    DrawGlyph(path, _strokePaint, canvas);
                }
                else
                {
                    DrawGlyph(path, _strokePaint, canvas);
                    DrawGlyph(path, _fillPaint, canvas);
                }
            }
        }
Пример #12
0
 public void Translate(float dx, float dy)
 {
     _matrix = MatrixExt.PreTranslate(_matrix, dx, dy);
 }
Пример #13
0
 public void Concat(DenseMatrix parentMatrix)
 {
     _matrix = MatrixExt.PreConcat(_matrix, parentMatrix);
 }
Пример #14
0
 public void Scale(float sx, float sy, float px, float py)
 {
     _matrix = MatrixExt.PreScale(_matrix, sx, sy, px, py);
 }
Пример #15
0
 public void Concat(Matrix3X3 parentMatrix)
 {
     _matrix = MatrixExt.PreConcat(_matrix, parentMatrix);
 }