internal static BaseLayer ForModel(Layer layerModel, LottieDrawable drawable, LottieComposition composition) { switch (layerModel.GetLayerType()) { case Layer.LayerType.Shape: return(new ShapeLayer(drawable, layerModel)); case Layer.LayerType.PreComp: return(new CompositionLayer(drawable, layerModel, composition.GetPrecomps(layerModel.RefId), composition)); case Layer.LayerType.Solid: return(new SolidLayer(drawable, layerModel)); case Layer.LayerType.Image: return(new ImageLayer(drawable, layerModel)); case Layer.LayerType.Null: return(new NullLayer(drawable, layerModel)); case Layer.LayerType.Text: return(new TextLayer(drawable, layerModel)); case Layer.LayerType.Unknown: default: // Do nothing LottieLog.Warn("Unknown layer type " + layerModel.GetLayerType()); return(null); } }
private static void ParseLayers(JsonReader reader, LottieComposition composition, List <Layer> layers, Dictionary <long, Layer> layerMap) { var imageCount = 0; reader.BeginArray(); while (reader.HasNext()) { var layer = LayerParser.Parse(reader, composition); if (layer.GetLayerType() == Layer.LayerType.Image) { imageCount++; } layers.Add(layer); layerMap[layer.Id] = layer; if (imageCount > 4) { LottieLog.Warn( $"You have {imageCount} images. Lottie should primarily be used with shapes. If you are using Adobe Illustrator, convert the Illustrator layers to shape layers."); } } reader.EndArray(); }
internal void InterpolateBetween(ShapeData shapeData1, ShapeData shapeData2, float percentage) { if (_initialPoint == null) { _initialPoint = new Vector2(); } _closed = shapeData1.Closed || shapeData2.Closed; if (shapeData1.Curves.Count != shapeData2.Curves.Count) { LottieLog.Warn($"Curves must have the same number of control points. Shape 1: {shapeData1.Curves.Count}\tShape 2: {shapeData2.Curves.Count}"); } if (_curves.Count == 0) { int points = Math.Min(shapeData1.Curves.Count, shapeData2.Curves.Count); for (int i = 0; i < points; i++) { _curves.Add(new CubicCurveData()); } } var initialPoint1 = shapeData1.InitialPoint; var initialPoint2 = shapeData2.InitialPoint; SetInitialPoint(MiscUtils.Lerp(initialPoint1.X, initialPoint2.X, percentage), MiscUtils.Lerp(initialPoint1.Y, initialPoint2.Y, percentage)); for (var i = _curves.Count - 1; i >= 0; i--) { var curve1 = shapeData1.Curves[i]; var curve2 = shapeData2.Curves[i]; var cp11 = curve1.ControlPoint1; var cp21 = curve1.ControlPoint2; var vertex1 = curve1.Vertex; var cp12 = curve2.ControlPoint1; var cp22 = curve2.ControlPoint2; var vertex2 = curve2.Vertex; _curves[i].SetControlPoint1(MiscUtils.Lerp(cp11.X, cp12.X, percentage), MiscUtils.Lerp(cp11.Y, cp12.Y, percentage)); _curves[i].SetControlPoint2(MiscUtils.Lerp(cp21.X, cp22.X, percentage), MiscUtils.Lerp(cp21.Y, cp22.Y, percentage)); _curves[i].SetVertex(MiscUtils.Lerp(vertex1.X, vertex2.X, percentage), MiscUtils.Lerp(vertex1.Y, vertex2.Y, percentage)); } }
/** * If the animation doesn't exist in the cache, null will be returned. * * Once the animation is successfully parsed, {@link #renameTempFile(FileExtension)} must be * called to move the file from a temporary location to its permanent cache location so it can * be used in the future. */ //internal async Task<KeyValuePair<FileExtension, Stream>?> FetchAsync(CancellationToken cancellationToken = default(CancellationToken)) //{ // StorageFile cachedFile = null; // try // { // cachedFile = await GetCachedFileAsync(_url, cancellationToken); // } // catch (FileNotFoundException) // { // return null; // } // if (cachedFile == null) // { // return null; // } // Stream inputStream; // try // { // inputStream = await cachedFile.OpenStreamForReadAsync().AsAsyncOperation().AsTask(cancellationToken); // } // catch (FileNotFoundException) // { // return null; // } // FileExtension extension; // if (cachedFile.Path.EndsWith(".zip")) // { // extension = FileExtension.Zip; // } // else // { // extension = FileExtension.Json; // } // Debug.WriteLine("Cache hit for " + _url + " at " + cachedFile.Path, LottieLog.Tag); // return new KeyValuePair<FileExtension, Stream>(extension, inputStream); //} ///// <summary> ///// Writes an InputStream from a network response to a temporary file. If the file successfully parses ///// to an composition, {@link #renameTempFile(FileExtension)} should be called to move the file ///// to its final location for future cache hits. ///// </summary> ///// <param name="stream"></param> ///// <param name="extension"></param> ///// <returns></returns> //internal async Task<StorageFile> WriteTempCacheFileAsync(Stream stream, FileExtension extension, CancellationToken cancellationToken = default(CancellationToken)) //{ // var fileName = FilenameForUrl(_url, extension, true); // var file = await ApplicationData.Current.LocalCacheFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting).AsTask(cancellationToken); // try // { // using (var output = await file.OpenStreamForWriteAsync().AsAsyncOperation().AsTask(cancellationToken)) // { // await stream.CopyToAsync(output).AsAsyncAction().AsTask(cancellationToken); // } // } // finally // { // stream.Dispose(); // } // return file; //} /// <summary> /// If the file created by {@link #writeTempCacheFile(InputStream, FileExtension)} was successfully parsed, /// this should be called to remove the temporary part of its name which will allow it to be a cache hit in the future. /// </summary> /// <param name="extension"></param> internal Task RenameTempFileAsync(FileExtension extension, CancellationToken cancellationToken = default) { return(Task.Run(() => { var fileName = FilenameForUrl(_url, extension, true); var file = new FileInfo(fileName); var newFileName = file.Name.Replace(".temp", ""); var oldFilename = file.Name; try { file.MoveTo(newFileName); Debug.WriteLine($"Copying temp file to real file ({file.Name})", LottieLog.Tag); } catch { LottieLog.Warn($"Unable to rename cache file {oldFilename} to {newFileName}."); } })); }
/// <summary> /// If the file created by {@link #writeTempCacheFile(InputStream, FileExtension)} was successfully parsed, /// this should be called to remove the temporary part of its name which will allow it to be a cache hit in the future. /// </summary> /// <param name="extension"></param> internal async Task RenameTempFileAsync(FileExtension extension, CancellationToken cancellationToken = default(CancellationToken)) { string fileName = FilenameForUrl(_url, extension, true); var file = await ApplicationData.Current.LocalCacheFolder.GetFileAsync(fileName).AsTask(cancellationToken); string newFileName = file.Name.Replace(".temp", ""); string oldFilename = file.Name; try { await file.RenameAsync(newFileName).AsTask(cancellationToken); Debug.WriteLine($"Copying temp file to real file ({file.Name})", LottieLog.Tag); } catch { LottieLog.Warn($"Unable to rename cache file {oldFilename} to {newFileName}."); } }