#region license // This file is part of Vocaluxe. // // Vocaluxe is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Vocaluxe is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Vocaluxe. If not, see . #endregion using System; using System.Collections.Generic; using System.Drawing; using System.Globalization; using System.IO; using System.Linq; using System.Text.RegularExpressions; using SkiaSharp; using VocaluxeLib.Log; namespace VocaluxeLib { public static class CHelper { private static readonly Regex _TextFileTypesRegex = new Regex("\\.txt|\\.txd", RegexOptions.IgnoreCase); private static readonly Regex _SoundFileTypesRegex = new Regex("\\.mp3|\\.wma|\\.ogg|\\.wav", RegexOptions.IgnoreCase); private static readonly Regex _ImageFileTypesRegex = new Regex("\\.jpg|\\.jpeg|\\.png|\\.gif", RegexOptions.IgnoreCase); public static int CombinationCount(int n, int k) { if (k > n) { return 0; } if (k == 0 || k == n) { return 1; } if (k < 0 || n <= 0) { return 0; //is not defined } if (k * 2 > n) { k = n - k; } long result = n; for (long i = 1; i <= k - 1; i++) { result = result * (n - i) / (i + 1); } return (int)result; } /// /// Concat strings into one string with ", " as separator. /// public static string ListStrings(string[] str) { var result = string.Empty; for (var i = 0; i < str.Length; i++) { result += str[i]; if (i < str.Length - 1) { result += ", "; } } return result; } /// /// Places a rect within the bounds maintaining the aspectRatio and using the given aspect /// /// Bounds to fit the rect in /// The original aspectRatio of the rect/image/... /// /// Crop: No empty space in bounds but has overhanging parts (same on both sides)
/// LetterBox: Fit the long side possibly leaving some space on the other (rect will be centered)
/// StretcH: Just fit the rect in the bounds (rect=bounds) /// public static SRectF FitInBounds(SRectF bounds, float aspectRatio, EAspect aspect) { if (aspect == EAspect.Stretch) { return bounds; } var boundsAspectRatio = bounds.W / bounds.H; float scaledWidth, scaledHeight; switch (aspect) { case EAspect.Automatic: case EAspect.Crop: if (boundsAspectRatio >= aspectRatio) { scaledWidth = bounds.W; scaledHeight = bounds.W / aspectRatio; } else { scaledHeight = bounds.H; scaledWidth = bounds.H * aspectRatio; } break; case EAspect.Zoom1: if (boundsAspectRatio >= aspectRatio) { scaledWidth = bounds.W * 1.33f; scaledHeight = bounds.W * 1.33f / aspectRatio; } else { scaledHeight = bounds.H / 1.33f; scaledWidth = bounds.H / 1.33f * aspectRatio; } break; case EAspect.Zoom2: if (boundsAspectRatio >= aspectRatio) { scaledWidth = bounds.W * 1.17f; scaledHeight = bounds.W * 1.17f / aspectRatio; } else { scaledHeight = bounds.H / 1.17f; scaledWidth = bounds.H / 1.17f * aspectRatio; } break; case EAspect.LetterBox: if (boundsAspectRatio < aspectRatio) { scaledWidth = bounds.W; scaledHeight = bounds.W / aspectRatio; } else { scaledHeight = bounds.H; scaledWidth = bounds.H * aspectRatio; } break; case EAspect.PillarBox: scaledWidth = bounds.W * 0.77f; scaledHeight = bounds.W / aspectRatio; break; default: return bounds; } var left = (bounds.W - scaledWidth) / 2 + bounds.X; var top = (bounds.H - scaledHeight) / 2 + bounds.Y; return new SRectF(left, top, scaledWidth, scaledHeight, bounds.Z); } /// /// Returns a list with all files in the given path that match a given pattern /// /// Path to search /// Pattern to match (e.g. "*.jpg") /// Search directories recursively /// False for just file names, True for full path /// List of file names public static IEnumerable ListFiles(string path, string searchPattern, bool recursive = false, bool fullpath = false) { var files = Enumerable.Empty(); var dir = new DirectoryInfo(path); if (!dir.Exists) { return files; } if (recursive && !fullpath) { throw new NotSupportedException("recursive file listing with relative path names is not supported"); } try { files = Directory.EnumerateFiles(dir.FullName, searchPattern, recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly); files = files.Select(fullpath ? (Func)Path.GetFullPath : Path.GetFileName); } catch (Exception e) { CLog.Error(e, "Error listing files for path " + path + " with search pattern " + searchPattern); return Enumerable.Empty(); } return files; } /// /// Returns a list with all files in the given path that match a given extension pattern /// /// Path to search /// File extension regex to match (e.g. "\\.jpg|\\.png") /// Search directories recursively /// False for just file names, True for full path /// List of file names public static IEnumerable ListFilesForExtPattern(string path, Regex extPattern, bool recursive = false, bool fullpath = false) { var files = Enumerable.Empty(); var dir = new DirectoryInfo(path); if (!dir.Exists) { return files; } if (recursive && !fullpath) { throw new NotSupportedException("recursive file listing with relative path names is not supported"); } try { files = Directory.EnumerateFiles(path, "*", recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly) .Where(file => extPattern.IsMatch(Path.GetExtension(file))); files = files.Select(fullpath ? (Func)Path.GetFullPath : Path.GetFileName); } catch (Exception e) { CLog.Error(e, "Error listing files for path " + path + " with regex " + extPattern.ToString()); return Enumerable.Empty(); } return files; } /// /// Returns a list with all text files in the given path /// /// Path to search for /// Search directories recursively /// False for just file names, True for full path /// List of text file names public static IEnumerable ListTextFiles(string path, bool recursive = false, bool fullpath = false) { return ListFilesForExtPattern(path, _TextFileTypesRegex, recursive, fullpath); } /// /// Returns a list with all image files in the given path /// /// Path to search for /// Search directories recursively /// False for just file names, True for full path /// List of image file names public static IEnumerable ListImageFiles(string path, bool recursive = false, bool fullpath = false) { return ListFilesForExtPattern(path, _ImageFileTypesRegex, recursive, fullpath); } /// /// Returns a list with all image files in the given path /// /// Path to search for /// Search directories recursively /// False for just file names, True for full path /// List of image file names public static IEnumerable ListSoundFiles(string path, bool recursive = false, bool fullpath = false) { return ListFilesForExtPattern(path, _SoundFileTypesRegex, recursive, fullpath); } public static bool TryParse(string value, out T result, bool ignoreCase = false) where T : struct { result = default(T); try { result = (T)Enum.Parse(typeof(T), value, ignoreCase); return true; } catch { } return false; } public static bool TryParse(string value, out float result) { value = value.Replace(',', '.'); return Single.TryParse(value, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, NumberFormatInfo.InvariantInfo, out result); } public static bool IsInBounds(SRectF bounds, SMouseEvent mouseEvent) { return IsInBounds(bounds, mouseEvent.X, mouseEvent.Y); } public static bool IsInBounds(SRectF bounds, int x, int y) { return ((float)x).IsInRange(bounds.X, bounds.X + bounds.W) && ((float)y).IsInRange(bounds.Y, bounds.Y + bounds.H); } /// /// Returns a filename that is unique in that path /// /// Path in which the file should be stored /// filename (including extension) /// Whether the fullpath or only the filename should be returned /// public static string GetUniqueFileName(string path, string filename, bool withPath = true) { var ext = Path.GetExtension(filename); filename = Path.GetFileNameWithoutExtension(filename) ?? "1"; if (File.Exists(Path.Combine(path, filename + ext))) { var i = 1; while (File.Exists(Path.Combine(path, filename + "_" + i + ext))) { i++; } filename += "_" + i; } if (withPath) { filename = Path.Combine(path, filename); } return filename + ext; } public static int Sum(int n) { return (n * n + n) / 2; } /// /// Loads a bitmap from a file logging errors /// /// Full path to image file /// Bitmap or null on error public static SKBitmap LoadBitmap(string filePath) { if (!File.Exists(filePath)) { CLog.Error("Can't find File: " + filePath); return null; } SKBitmap bmp; try { bmp = SKBitmap.Decode(filePath); } catch (Exception) { bmp = null; } if (bmp == null) { CLog.Error("Error loading bitmap: " + filePath); return null; } return bmp; } public static float EaseOutBack(float t) { const float overshoot = 1.70158f; t -= 1f; return t * t * ((overshoot + 1f) * t + overshoot) + 1f; } public static float EaseOutCubic(float t) { t = 1f - t; return 1f - t * t * t; } } }