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); } }
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)); } } } }
//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(); } } } }
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(); } } }
//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"); } } }
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); } }
/** * 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); }
//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); }
//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"); }
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); } }
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); } } }
public void Translate(float dx, float dy) { _matrix = MatrixExt.PreTranslate(_matrix, dx, dy); }
public void Concat(DenseMatrix parentMatrix) { _matrix = MatrixExt.PreConcat(_matrix, parentMatrix); }
public void Scale(float sx, float sy, float px, float py) { _matrix = MatrixExt.PreScale(_matrix, sx, sy, px, py); }
public void Concat(Matrix3X3 parentMatrix) { _matrix = MatrixExt.PreConcat(_matrix, parentMatrix); }