This commit is contained in:
Matthew Leibowitz 2021-03-20 00:20:12 +02:00
Родитель 87fbd9c536 1a779558b3
Коммит cb963f2fcf
25 изменённых файлов: 728 добавлений и 151 удалений

Просмотреть файл

@ -128,6 +128,8 @@ namespace SkiaSharp
public GRBackend Backend => SkiaApi.gr_direct_context_get_backend (Handle).FromNative ();
public bool IsAbandoned => SkiaApi.gr_direct_context_is_abandoned (Handle);
public void AbandonContext (bool releaseResources = false)
{
if (releaseResources)

Просмотреть файл

@ -510,6 +510,22 @@ namespace SkiaSharp
(gr_direct_context_get_resource_cache_usage_delegate ??= GetSymbol<Delegates.gr_direct_context_get_resource_cache_usage> ("gr_direct_context_get_resource_cache_usage")).Invoke (context, maxResources, maxResourceBytes);
#endif
// bool gr_direct_context_is_abandoned(gr_direct_context_t* context)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs (UnmanagedType.I1)]
internal static extern bool gr_direct_context_is_abandoned (gr_direct_context_t context);
#else
private partial class Delegates {
[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
[return: MarshalAs (UnmanagedType.I1)]
internal delegate bool gr_direct_context_is_abandoned (gr_direct_context_t context);
}
private static Delegates.gr_direct_context_is_abandoned gr_direct_context_is_abandoned_delegate;
internal static bool gr_direct_context_is_abandoned (gr_direct_context_t context) =>
(gr_direct_context_is_abandoned_delegate ??= GetSymbol<Delegates.gr_direct_context_is_abandoned> ("gr_direct_context_is_abandoned")).Invoke (context);
#endif
// gr_direct_context_t* gr_direct_context_make_gl(const gr_glinterface_t* glInterface)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]

Просмотреть файл

@ -3,7 +3,7 @@
#addin nuget:?package=Cake.FileHelpers&version=3.2.1
#addin nuget:?package=Cake.Json&version=4.0.0
#addin nuget:?package=SharpCompress&version=0.24.0
#addin nuget:?package=Mono.ApiTools.NuGetDiff&version=1.3.0&loaddependencies=true
#addin nuget:?package=Mono.ApiTools.NuGetDiff&version=1.3.2&loaddependencies=true
#addin nuget:?package=Xamarin.Nuget.Validator&version=1.1.1
#tool nuget:?package=mdoc&version=5.7.4.10
@ -29,6 +29,7 @@ DirectoryPath ROOT_PATH = MakeAbsolute(Directory("."));
var SKIP_EXTERNALS = Argument ("skipexternals", "")
.ToLower ().Split (new [] { ',' }, StringSplitOptions.RemoveEmptyEntries);
var SKIP_BUILD = Argument ("skipbuild", false);
var PACK_ALL_PLATFORMS = Argument ("packall", Argument ("PackAllPlatforms", false));
var BUILD_ALL_PLATFORMS = Argument ("buildall", Argument ("BuildAllPlatforms", false));
var PRINT_ALL_ENV_VARS = Argument ("printAllEnvVars", false);
@ -42,7 +43,6 @@ var PLATFORM_SUPPORTS_VULKAN_TESTS = (IsRunningOnWindows () || IsRunningOnLinux
var SUPPORT_VULKAN_VAR = Argument ("supportVulkan", EnvironmentVariable ("SUPPORT_VULKAN") ?? PLATFORM_SUPPORTS_VULKAN_TESTS);
var SUPPORT_VULKAN = SUPPORT_VULKAN_VAR == "1" || SUPPORT_VULKAN_VAR.ToLower () == "true";
var NuGetToolPath = Context.Tools.Resolve ("nuget.exe");
var CakeToolPath = Context.Tools.Resolve ("Cake.exe");
var MDocPath = Context.Tools.Resolve ("mdoc.exe");
@ -54,7 +54,7 @@ var BUILD_NUMBER = EnvironmentVariable ("BUILD_NUMBER") ?? "0";
var GIT_SHA = Argument ("gitSha", EnvironmentVariable ("GIT_SHA") ?? "");
var GIT_BRANCH_NAME = Argument ("gitBranch", EnvironmentVariable ("GIT_BRANCH_NAME") ?? "");
var PREVIEW_FEED_URL = "https://nugetized.blob.core.windows.net/skiasharp-eap/flatcontainer/{0}/{1}/{0}.{1}.nupkg"; // 0=id, 1=version
var PREVIEW_FEED_URL = "https://pkgs.dev.azure.com/xamarin/public/_packaging/SkiaSharp/nuget/v3/index.json";
var TRACKED_NUGETS = new Dictionary<string, Version> {
{ "SkiaSharp", new Version (1, 57, 0) },
@ -108,6 +108,7 @@ Task ("externals")
Task ("libs")
.Description ("Build all managed assemblies.")
.WithCriteria(!SKIP_BUILD)
.IsDependentOn ("externals")
.Does (() =>
{
@ -485,6 +486,11 @@ Task ("samples")
////////////////////////////////////////////////////////////////////////////////////////////////////
Task ("nuget")
.Description ("Pack all NuGets.")
.IsDependentOn ("nuget-normal")
.IsDependentOn ("nuget-special");
Task ("nuget-normal")
.Description ("Pack all NuGets (build all required dependencies).")
.IsDependentOn ("libs")
.Does (() =>
@ -641,42 +647,91 @@ Task ("nuget")
Information ("Metadata validation passed for: {0}", nupkgFile.GetFilename ());
}
}
});
// special case for all the native assets
if (PACK_ALL_PLATFORMS)
{
EnsureDirectoryExists ($"{OUTPUT_SPECIAL_NUGETS_PATH}");
DeleteFiles ($"{OUTPUT_SPECIAL_NUGETS_PATH}/*.nupkg");
var specials = new Dictionary<string, string> {
{ "_NativeAssets", "native" },
{ "_NuGets", "nugets" },
};
foreach (var pair in specials) {
DeleteFiles ($"./output/{pair.Value}/*.nuspec");
Task ("nuget-special")
.Description ("Pack all special NuGets.")
.IsDependentOn ("nuget-normal")
.Does (() =>
{
EnsureDirectoryExists ($"{OUTPUT_SPECIAL_NUGETS_PATH}");
DeleteFiles ($"{OUTPUT_SPECIAL_NUGETS_PATH}/*.nupkg");
var nuspec = $"./output/{pair.Value}/{pair.Key}.nuspec";
// get a list of all the version number variants
var versions = new List<string> ();
if (!string.IsNullOrEmpty (PREVIEW_LABEL) && PREVIEW_LABEL.StartsWith ("pr.")) {
var v = $"0.0.0-{PREVIEW_LABEL}";
if (!string.IsNullOrEmpty (BUILD_NUMBER))
v += $".{BUILD_NUMBER}";
versions.Add (v);
} else {
if (!string.IsNullOrEmpty (GIT_SHA)) {
var v = $"0.0.0-commit.{GIT_SHA}";
if (!string.IsNullOrEmpty (BUILD_NUMBER))
v += $".{BUILD_NUMBER}";
versions.Add (v);
}
if (!string.IsNullOrEmpty (GIT_BRANCH_NAME)) {
var v = $"0.0.0-branch.{GIT_BRANCH_NAME.Replace ("/", ".")}";
if (!string.IsNullOrEmpty (BUILD_NUMBER))
v += $".{BUILD_NUMBER}";
versions.Add (v);
}
}
// get a list of all the nuspecs to pack
var specials = new Dictionary<string, string> ();
var nativePlatforms = GetDirectories ("./output/native/*")
.Select (d => d.GetDirectoryName ())
.ToArray ();
if (nativePlatforms.Length > 0) {
specials[$"_NativeAssets"] = $"native";
foreach (var platform in nativePlatforms) {
specials[$"_NativeAssets.{platform}"] = $"native/{platform}";
}
}
if (GetFiles ("./output/nugets/*.nupkg").Count > 0) {
specials[$"_NuGets"] = $"nugets";
}
foreach (var pair in specials) {
var id = pair.Key;
var path = pair.Value;
var nuspec = $"./output/{path}/{id}.nuspec";
DeleteFiles ($"./output/{path}/*.nuspec");
foreach (var packageVersion in versions) {
// update the version
var xdoc = XDocument.Load ($"./nuget/{pair.Key}.nuspec");
var fn = id.StartsWith ("_NativeAssets.") ? "_NativeAssets" : id;
var xdoc = XDocument.Load ($"./nuget/{fn}.nuspec");
var metadata = xdoc.Root.Element ("metadata");
var version = metadata.Element ("version");
metadata.Element ("version").Value = packageVersion;
metadata.Element ("id").Value = id;
if (!string.IsNullOrEmpty (PREVIEW_LABEL) && PREVIEW_LABEL.StartsWith ("pr.")) {
version.Value = "0.0.0-" + PREVIEW_LABEL;
xdoc.Save (nuspec);
PackageNuGet (nuspec, OUTPUT_SPECIAL_NUGETS_PATH, true);
} else {
version.Value = "0.0.0-commit." + GIT_SHA;
xdoc.Save (nuspec);
PackageNuGet (nuspec, OUTPUT_SPECIAL_NUGETS_PATH, true);
version.Value = "0.0.0-branch." + GIT_BRANCH_NAME.Replace ("/", ".");
xdoc.Save (nuspec);
PackageNuGet (nuspec, OUTPUT_SPECIAL_NUGETS_PATH, true);
if (id == "_NativeAssets") {
// handle the root package
var dependencies = metadata.Element ("dependencies");
foreach (var platform in nativePlatforms) {
dependencies.Add (new XElement ("dependency",
new XAttribute ("id", $"_NativeAssets.{platform}"),
new XAttribute ("version", packageVersion)));
}
} else if (id.StartsWith ("_NativeAssets.")) {
// handle the dependencies
var platform = id.Substring (id.IndexOf (".") + 1);
var files = xdoc.Root.Element ("files");
files.Add (new XElement ("file",
new XAttribute ("src", $"*/**"),
new XAttribute ("target", $"tools/{platform}")));
}
DeleteFiles ($"./output/{pair.Value}/*.nuspec");
xdoc.Save (nuspec);
PackageNuGet (nuspec, OUTPUT_SPECIAL_NUGETS_PATH, true);
}
DeleteFiles ($"./output/{path}/*.nuspec");
}
});

Просмотреть файл

@ -38,19 +38,12 @@ void CopyChangelogs (DirectoryPath diffRoot, string id, string version)
}
Task ("docs-download-output")
.Does (() =>
.Does (async () =>
{
EnsureDirectoryExists ("./output");
CleanDirectories ("./output");
EnsureDirectoryExists ("./output/temp");
var url = GetDownloadUrl ("_nugets");
DownloadFile (url, "./output/temp/nugets.nupkg");
Unzip ("./output/temp/nugets.nupkg", "./output/temp");
MoveDirectory ("./output/temp/tools", OUTPUT_NUGETS_PATH);
DeleteDirectory("./output/temp", new DeleteDirectorySettings { Recursive = true, Force = true });
await DownloadPackageAsync ("_nugets", OUTPUT_NUGETS_PATH);
foreach (var id in TRACKED_NUGETS.Keys) {
var version = GetVersion (id);

Просмотреть файл

@ -4,7 +4,7 @@ void PackageNuGet(FilePath nuspecPath, DirectoryPath outputPath, bool allowDefau
var settings = new NuGetPackSettings {
OutputDirectory = MakeAbsolute(outputPath),
BasePath = nuspecPath.GetDirectory(),
ToolPath = NuGetToolPath,
ToolPath = NUGET_EXE,
Properties = new Dictionary<string, string> {
// NU5048: The 'PackageIconUrl'/'iconUrl' element is deprecated. Consider using the 'PackageIcon'/'icon' element instead.
// NU5105: The package version 'xxx' uses SemVer 2.0.0 or components of SemVer 1.0.0 that are not supported on legacy clients.
@ -18,25 +18,6 @@ void PackageNuGet(FilePath nuspecPath, DirectoryPath outputPath, bool allowDefau
NuGetPack(nuspecPath, settings);
}
void RunNuGetRestorePackagesConfig(FilePath sln)
{
var dir = sln.GetDirectory();
var nugetSources = new [] { OUTPUT_NUGETS_PATH.FullPath, "https://api.nuget.org/v3/index.json" };
EnsureDirectoryExists(OUTPUT_NUGETS_PATH);
var settings = new NuGetRestoreSettings {
ToolPath = NuGetToolPath,
Source = nugetSources,
NoCache = true,
PackagesDirectory = dir.Combine("packages"),
};
foreach (var config in GetFiles(dir + "/**/packages.config"))
NuGetRestore(config, settings);
}
void RunTests(FilePath testAssembly, bool is32)
{
var dir = testAssembly.GetDirectory();
@ -104,7 +85,7 @@ void RunNetCorePublish(FilePath testProject, DirectoryPath output)
void RunCodeCoverage(string testResultsGlob, DirectoryPath output)
{
try {
RunProcess ("reportgenerator", new ProcessSettings {
RunProcess("reportgenerator", new ProcessSettings {
Arguments =
$"-reports:{testResultsGlob} " +
$"-targetdir:{output} " +
@ -112,13 +93,13 @@ void RunCodeCoverage(string testResultsGlob, DirectoryPath output)
$"-assemblyfilters:-*.Tests"
});
} catch (Exception ex) {
Error ("Make sure to install the 'dotnet-reportgenerator-globaltool' .NET Core global tool.");
Error (ex);
Error("Make sure to install the 'dotnet-reportgenerator-globaltool' .NET Core global tool.");
Error(ex);
throw;
}
var xml = $"{output}/Cobertura.xml";
var root = FindRegexMatchGroupsInFile (xml, @"<source>(.*)<\/source>", 0)[1].Value;
ReplaceTextInFiles (xml, root, "");
var root = FindRegexMatchGroupsInFile(xml, @"<source>(.*)<\/source>", 0)[1].Value;
ReplaceTextInFiles(xml, root, "");
}
IEnumerable<(string Name, string Value)> CreateTraitsDictionary(string args)
@ -260,17 +241,59 @@ async Task<NuGetDiff> CreateNuGetDiffAsync()
}
}
string GetDownloadUrl(string id)
async Task DownloadPackageAsync(string id, DirectoryPath outputDirectory)
{
var version = "0.0.0-";
if (!string.IsNullOrEmpty (PREVIEW_LABEL) && PREVIEW_LABEL.StartsWith ("pr."))
version += PREVIEW_LABEL.ToLower ();
else if (!string.IsNullOrEmpty (GIT_SHA))
version += "commit." + GIT_SHA.ToLower ();
else if (!string.IsNullOrEmpty (GIT_BRANCH_NAME))
version += "branch." + GIT_BRANCH_NAME.Replace ("/", ".").ToLower ();
if (!string.IsNullOrEmpty(PREVIEW_LABEL) && PREVIEW_LABEL.StartsWith("pr."))
version += PREVIEW_LABEL.ToLower();
else if (!string.IsNullOrEmpty(GIT_SHA))
version += "commit." + GIT_SHA.ToLower();
else if (!string.IsNullOrEmpty(GIT_BRANCH_NAME))
version += "branch." + GIT_BRANCH_NAME.Replace("/", ".").ToLower();
else
version += "branch.main";
version += ".*";
return string.Format (PREVIEW_FEED_URL, id.ToLower(), version);
var filter = new NuGetVersions.Filter {
IncludePrerelease = true,
SourceUrl = PREVIEW_FEED_URL,
VersionRange = VersionRange.Parse(version),
};
var latestVersion = await NuGetVersions.GetLatestAsync(id, filter);
var comparer = new NuGetDiff(PREVIEW_FEED_URL);
comparer.PackageCache = PACKAGE_CACHE_PATH.FullPath;
await Download(id, latestVersion);
async Task Download(string currentId, NuGetVersion currentVersion)
{
currentId = currentId.ToLower();
Information($"Downloading: {currentId}...");
var root = await comparer.ExtractCachedPackageAsync(currentId, currentVersion);
var toolsDir = $"{root}/tools/";
if (DirectoryExists(toolsDir)) {
var allFiles = GetFiles(toolsDir + "**/*");
foreach (var file in allFiles) {
var relative = MakeAbsolute(Directory(toolsDir)).GetRelativePath(file);
var dir = $"{outputDirectory}/{relative.GetDirectory()}";
EnsureDirectoryExists(dir);
CopyFileToDirectory(file, dir);
}
}
var nuspec = $"{root}/{currentId}.nuspec";
var xdoc = XDocument.Load(nuspec);
var xmlns = xdoc.Root.Name.Namespace;
var dependencies = xdoc.Root.Descendants(xmlns + "dependency").ToArray();
foreach (var dep in dependencies) {
var depId = dep.Attribute("id").Value;
var depVersion = dep.Attribute("version").Value;
await Download(depId, NuGetVersion.Parse(depVersion));
}
}
}

Просмотреть файл

@ -12,6 +12,7 @@ foreach (var cake in GetFiles("native/*/build.cake"))
var task = Task($"externals-{native}")
.WithCriteria(should)
.WithCriteria(!SKIP_BUILD)
.Does(() => RunCake(localCake, "Default"));
externalsTask.IsDependentOn(task);
@ -25,19 +26,12 @@ Task("externals-osx")
////////////////////////////////////////////////////////////////////////////////////////////////////
Task("externals-download")
.Does(() =>
.Does(async () =>
{
EnsureDirectoryExists ("./output");
CleanDirectories ("./output");
EnsureDirectoryExists ("./output/temp");
var url = GetDownloadUrl ("_nativeassets");
DownloadFile (url, "./output/temp/nativeassets.nupkg");
Unzip ("./output/temp/nativeassets.nupkg", "./output/temp");
MoveDirectory ("./output/temp/tools", "./output/native");
DeleteDirectory("./output/temp", new DeleteDirectorySettings { Recursive = true, Force = true });
await DownloadPackageAsync("_nativeassets", "./output/native");
});
////////////////////////////////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -2,6 +2,29 @@ DirectoryPath PACKAGE_CACHE_PATH = MakeAbsolute(ROOT_PATH.Combine("externals/pac
DirectoryPath OUTPUT_NUGETS_PATH = MakeAbsolute(ROOT_PATH.Combine("output/nugets"));
DirectoryPath OUTPUT_SPECIAL_NUGETS_PATH = MakeAbsolute(ROOT_PATH.Combine("output/special-nugets"));
var NUGETS_SOURCES = new [] {
OUTPUT_NUGETS_PATH.FullPath,
"https://api.nuget.org/v3/index.json",
"https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json"
};
void RunNuGetRestorePackagesConfig(FilePath sln)
{
var dir = sln.GetDirectory();
EnsureDirectoryExists(OUTPUT_NUGETS_PATH);
var settings = new NuGetRestoreSettings {
ToolPath = NUGET_EXE,
Source = NUGETS_SOURCES,
NoCache = true,
PackagesDirectory = dir.Combine("packages"),
};
foreach (var config in GetFiles(dir + "/**/packages.config"))
NuGetRestore(config, settings);
}
void RunMSBuild(
FilePath solution,
string platform = "Any CPU",
@ -12,12 +35,6 @@ void RunMSBuild(
string configuration = null,
Dictionary<string, string> properties = null)
{
var nugetSources = new [] {
OUTPUT_NUGETS_PATH.FullPath,
"https://api.nuget.org/v3/index.json",
"https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json"
};
EnsureDirectoryExists(OUTPUT_NUGETS_PATH);
MSBuild(solution, c => {
@ -68,8 +85,8 @@ void RunMSBuild(
c.Properties [prop.Key] = new [] { prop.Value };
}
}
// c.Properties ["RestoreSources"] = nugetSources;
// c.Properties ["RestoreSources"] = NUGETS_SOURCES;
var sep = IsRunningOnWindows() ? ";" : "%3B";
c.ArgumentCustomization = args => args.Append($"/p:RestoreSources=\"{string.Join(sep, nugetSources)}\"");
c.ArgumentCustomization = args => args.Append($"/p:RestoreSources=\"{string.Join(sep, NUGETS_SOURCES)}\"");
});
}

Просмотреть файл

@ -7,6 +7,7 @@ var CONFIGURATION = Argument("c", Argument("configuration", "Release"));
var VS_INSTALL = Argument("vsinstall", EnvironmentVariable("VS_INSTALL"));
var MSBUILD_EXE = Argument("msbuild", EnvironmentVariable("MSBUILD_EXE"));
var NUGET_EXE = Argument("nuget", EnvironmentVariable("NUGET_EXE") ?? Context.Tools.Resolve ("nuget.exe"));
var CAKE_ARGUMENTS = (IReadOnlyDictionary<string, string>)Context.Arguments
.GetType()

2
externals/skia поставляемый

@ -1 +1 @@
Subproject commit cecf0b0ccf451b67e67695ec2c5031eb3ea52028
Subproject commit 457fddd486d12d91e63d490d28707e3bb9e9f991

Просмотреть файл

@ -5,14 +5,18 @@
<id>_NativeAssets</id>
<title>Build Native Assets</title>
<version>1.0.0</version>
<description>All the native assets from the build</description>
<summary>All the native assets from the build</summary>
<description>All the native assets from the build.</description>
<summary>All the native assets from the build.</summary>
<authors>Microsoft</authors>
<dependencies>
<!-- <dependency id="_NativeAssets.windows" version="1.0.0" /> -->
</dependencies>
</metadata>
<files>
<file src="*/**" target="tools/" />
<!-- <file src="*/**" target="tools/" /> -->
</files>
</package>

Просмотреть файл

@ -5,8 +5,8 @@
<id>_NuGets</id>
<title>Build NuGets</title>
<version>1.0.0</version>
<description>All the NuGet packages from the build</description>
<summary>All the NuGet packages from the build</summary>
<description>All the stable NuGet packages from the build.</description>
<summary>All the stable NuGet packages from the build.</summary>
<authors>Microsoft</authors>
</metadata>

Просмотреть файл

@ -311,7 +311,7 @@ stages:
displayName: Managed (Windows)
vmImage: $(VM_IMAGE_WINDOWS)
target: libs
additionalArgs: --exclusive
additionalArgs: --skipExternals="all"
requiredArtifacts:
- native_android_x86_windows
- native_android_x64_windows
@ -337,7 +337,7 @@ stages:
displayName: Managed (macOS)
vmImage: $(VM_IMAGE_MAC)
target: libs
additionalArgs: --exclusive
additionalArgs: --skipExternals="all"
requiredArtifacts:
- native_android_x86_macos
- native_android_x64_macos
@ -357,7 +357,7 @@ stages:
vmImage: $(VM_IMAGE_LINUX)
packages: $(MANAGED_LINUX_PACKAGES)
target: libs
additionalArgs: --exclusive
additionalArgs: --skipExternals="all"
requiredArtifacts:
- native_linux_x64_linux
- native_linux_arm_linux
@ -381,7 +381,7 @@ stages:
displayName: Package NuGets
vmImage: $(VM_IMAGE_WINDOWS)
target: nuget
additionalArgs: --packall=true --exclusive
additionalArgs: --packall=true --skipbuild=true
installWindowsSdk: false
shouldPublish: true
requiredArtifacts:
@ -567,7 +567,10 @@ stages:
--add-source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json `
--version "1.0.0-prerelease*"
displayName: Install the xharness .NET Core tool
- bash: sh -c "echo \"y\" | $ANDROID_HOME/tools/bin/sdkmanager \"system-images;android-30;google_apis_playstore;x86\""
- bash: |
sh -c "echo \"y\" | $ANDROID_HOME/tools/bin/sdkmanager \"emulator\" \"system-images;android-30;google_apis_playstore;x86\""
echo "##vso[task.prependpath]$ANDROID_HOME/tools/bin"
echo "##vso[task.prependpath]$ANDROID_HOME/emulator"
displayName: Install the Android emulator
postBuildSteps:
- task: PublishTestResults@2

Просмотреть файл

@ -139,9 +139,9 @@ namespace SkiaSharp.Views.Android
}
}
public static Bitmap ToBitmap(this SKPixmap skiaPixmap)
public static Bitmap ToBitmap(this SKImage skiaImage)
{
var info = skiaPixmap.Info;
var info = skiaImage.Info;
// destination values
var config = Bitmap.Config.Argb8888;
@ -172,7 +172,7 @@ namespace SkiaSharp.Views.Android
var ptr = bmp.LockPixels();
// copy
var success = skiaPixmap.ReadPixels(dstInfo, ptr, dstInfo.RowBytes);
var success = skiaImage.ReadPixels(dstInfo, ptr, dstInfo.RowBytes);
// confirm
bmp.UnlockPixels();
@ -183,15 +183,15 @@ namespace SkiaSharp.Views.Android
bmp = null;
}
GC.KeepAlive(skiaImage);
return bmp;
}
public static Bitmap ToBitmap(this SKImage skiaImage)
public static Bitmap ToBitmap(this SKPixmap skiaPixamp)
{
using (var pixmap = skiaImage.PeekPixels())
using (var image = SKImage.FromPixels(skiaPixamp))
{
var bmp = pixmap.ToBitmap();
GC.KeepAlive(skiaImage);
var bmp = image.ToBitmap();
return bmp;
}
}

Просмотреть файл

@ -15,6 +15,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp.Views.Android", "
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp.Views.Forms.Android", "..\source\SkiaSharp.Views.Forms\SkiaSharp.Views.Forms.Android\SkiaSharp.Views.Forms.Android.csproj", "{F962E49D-DC1F-4E93-9F6B-335E2746BCF1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HarfBuzzSharp", "..\binding\HarfBuzzSharp\HarfBuzzSharp.csproj", "{814F4C3B-0767-4A6C-B274-71EAD305D2BF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp", "..\binding\SkiaSharp\SkiaSharp.csproj", "{B9C1E6E5-D56B-4B10-946C-6493AE1C57FA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -47,6 +51,14 @@ Global
{F962E49D-DC1F-4E93-9F6B-335E2746BCF1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F962E49D-DC1F-4E93-9F6B-335E2746BCF1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F962E49D-DC1F-4E93-9F6B-335E2746BCF1}.Release|Any CPU.Build.0 = Release|Any CPU
{814F4C3B-0767-4A6C-B274-71EAD305D2BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{814F4C3B-0767-4A6C-B274-71EAD305D2BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{814F4C3B-0767-4A6C-B274-71EAD305D2BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{814F4C3B-0767-4A6C-B274-71EAD305D2BF}.Release|Any CPU.Build.0 = Release|Any CPU
{B9C1E6E5-D56B-4B10-946C-6493AE1C57FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B9C1E6E5-D56B-4B10-946C-6493AE1C57FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B9C1E6E5-D56B-4B10-946C-6493AE1C57FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B9C1E6E5-D56B-4B10-946C-6493AE1C57FA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

Просмотреть файл

@ -0,0 +1,75 @@
using Xunit;
namespace SkiaSharp.Views.Android.Tests
{
public class AndroidExtensionsTests : AndroidTests
{
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public void PixelBackedImageToBitmap(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
using var image = SKImage.FromBitmap(bitmap);
using var androidBitmap = image.ToBitmap();
ValidateTestBitmap(androidBitmap, alpha);
androidBitmap.Recycle();
}
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public void BitmapToBitmap(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
using var androidBitmap = bitmap.ToBitmap();
ValidateTestBitmap(androidBitmap, alpha);
androidBitmap.Recycle();
}
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public void PixmapToBitmap(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
using var pixmap = bitmap.PeekPixels();
using var androidBitmap = pixmap.ToBitmap();
ValidateTestBitmap(androidBitmap, alpha);
androidBitmap.Recycle();
}
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public void EncodedDataBackedImageToBitmap(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
using var data = bitmap.Encode(SKEncodedImageFormat.Png, 100);
using var image = SKImage.FromEncodedData(data);
using var androidBitmap = image.ToBitmap();
ValidateTestBitmap(androidBitmap, alpha);
androidBitmap.Recycle();
}
}
}

Просмотреть файл

@ -0,0 +1,26 @@
using Android.Graphics;
using SkiaSharp.Tests;
using Xunit;
namespace SkiaSharp.Views.Android.Tests
{
public abstract class AndroidTests : SKTest
{
protected static void ValidateTestBitmap(Bitmap bmp, byte alpha = 255)
{
Assert.NotNull(bmp);
Assert.Equal(40, bmp.Width);
Assert.Equal(40, bmp.Height);
Assert.Equal(Get(SKColors.Red), (uint)bmp.GetPixel(10, 10));
Assert.Equal(Get(SKColors.Green), (uint)bmp.GetPixel(30, 10));
Assert.Equal(Get(SKColors.Blue), (uint)bmp.GetPixel(10, 30));
Assert.Equal(Get(SKColors.Yellow), (uint)bmp.GetPixel(30, 30));
SKColor Get(SKColor color) =>
alpha == 0
? SKColor.Empty
: color.WithAlpha(alpha);
}
}
}

Просмотреть файл

@ -0,0 +1,93 @@
using System.Threading.Tasks;
using Android.App;
using SkiaSharp.Views.Android.Tests;
using Xunit;
namespace SkiaSharp.Views.Forms.Tests
{
public class SKImageSourceHandlerTests : AndroidTests
{
private readonly SKImageSourceHandler handler;
public SKImageSourceHandlerTests()
{
handler = new SKImageSourceHandler();
}
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public async Task PixelBackedImageToBitmap(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
using var image = SKImage.FromBitmap(bitmap);
var source = (SKImageImageSource)image;
using var androidBitmap = await handler.LoadImageAsync(source, Application.Context);
ValidateTestBitmap(androidBitmap, alpha);
androidBitmap.Recycle();
}
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public async Task BitmapToBitmap(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
var source = (SKBitmapImageSource)bitmap;
using var androidBitmap = await handler.LoadImageAsync(source, Application.Context);
ValidateTestBitmap(androidBitmap, alpha);
androidBitmap.Recycle();
}
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public async Task PixmapToBitmap(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
using var pixmap = bitmap.PeekPixels();
var source = (SKPixmapImageSource)pixmap;
using var androidBitmap = await handler.LoadImageAsync(source, Application.Context);
ValidateTestBitmap(androidBitmap, alpha);
androidBitmap.Recycle();
}
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public async Task EncodedDataBackedImageToBitmap(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
using var data = bitmap.Encode(SKEncodedImageFormat.Png, 100);
using var image = SKImage.FromEncodedData(data);
var source = (SKImageImageSource)image;
using var androidBitmap = await handler.LoadImageAsync(source, Application.Context);
ValidateTestBitmap(androidBitmap, alpha);
androidBitmap.Recycle();
}
}
}

Просмотреть файл

@ -94,6 +94,9 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Compile Include="AndroidExtensionsTests.cs" />
<Compile Include="AndroidTests.cs" />
<Compile Include="FormsExtensionsTests.cs" />
<Compile Include="MainActivity.cs" />
<Compile Include="TestInstrumentation.cs" />
</ItemGroup>

Просмотреть файл

@ -3,100 +3,128 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.808.5
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkiaSharp.iOS", "..\binding\SkiaSharp.iOS\SkiaSharp.iOS.csproj", "{A4146A87-DB60-4A17-A179-0E2E4255A08E}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp.iOS", "..\binding\SkiaSharp.iOS\SkiaSharp.iOS.csproj", "{A4146A87-DB60-4A17-A179-0E2E4255A08E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HarfBuzzSharp.iOS", "..\binding\HarfBuzzSharp.iOS\HarfBuzzSharp.iOS.csproj", "{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HarfBuzzSharp.iOS", "..\binding\HarfBuzzSharp.iOS\HarfBuzzSharp.iOS.csproj", "{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkiaSharp.HarfBuzz", "..\source\SkiaSharp.HarfBuzz\SkiaSharp.HarfBuzz\SkiaSharp.HarfBuzz.csproj", "{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp.HarfBuzz", "..\source\SkiaSharp.HarfBuzz\SkiaSharp.HarfBuzz\SkiaSharp.HarfBuzz.csproj", "{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkiaSharp.Views.iOS", "..\source\SkiaSharp.Views\SkiaSharp.Views.iOS\SkiaSharp.Views.iOS.csproj", "{549F8E22-A756-4E99-A84A-C4E74832DA95}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp.Views.iOS", "..\source\SkiaSharp.Views\SkiaSharp.Views.iOS\SkiaSharp.Views.iOS.csproj", "{549F8E22-A756-4E99-A84A-C4E74832DA95}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkiaSharp.Views.Forms.iOS", "..\source\SkiaSharp.Views.Forms\SkiaSharp.Views.Forms.iOS\SkiaSharp.Views.Forms.iOS.csproj", "{0254162B-6B4A-459E-BD96-3A42A104C144}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp.Views.Forms.iOS", "..\source\SkiaSharp.Views.Forms\SkiaSharp.Views.Forms.iOS\SkiaSharp.Views.Forms.iOS.csproj", "{0254162B-6B4A-459E-BD96-3A42A104C144}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkiaSharp.iOS.Tests", "SkiaSharp.iOS.Tests\SkiaSharp.iOS.Tests.csproj", "{B73EB308-70BE-49FD-91A7-1D1495663D6D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HarfBuzzSharp", "..\binding\HarfBuzzSharp\HarfBuzzSharp.csproj", "{5D79739D-98C6-48A4-965E-064DB4C59955}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp", "..\binding\SkiaSharp\SkiaSharp.csproj", "{A694283C-FE40-4049-88AB-2CAE678FC087}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
Debug|iPhoneSimulator = Debug|iPhoneSimulator
Release|iPhoneSimulator = Release|iPhoneSimulator
Debug|iPhone = Debug|iPhone
Debug|iPhoneSimulator = Debug|iPhoneSimulator
Release|Any CPU = Release|Any CPU
Release|iPhone = Release|iPhone
Release|iPhoneSimulator = Release|iPhoneSimulator
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Release|Any CPU.Build.0 = Release|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Debug|iPhone.Build.0 = Debug|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Release|Any CPU.Build.0 = Release|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Release|iPhone.ActiveCfg = Release|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Release|iPhone.Build.0 = Release|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Release|Any CPU.Build.0 = Release|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Debug|iPhone.Build.0 = Debug|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Release|Any CPU.Build.0 = Release|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Release|iPhone.ActiveCfg = Release|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Release|iPhone.Build.0 = Release|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Release|Any CPU.Build.0 = Release|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Debug|iPhone.Build.0 = Debug|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Release|Any CPU.Build.0 = Release|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Release|iPhone.ActiveCfg = Release|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Release|iPhone.Build.0 = Release|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Debug|Any CPU.Build.0 = Debug|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Release|Any CPU.ActiveCfg = Release|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Release|Any CPU.Build.0 = Release|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Debug|iPhone.Build.0 = Debug|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Release|Any CPU.ActiveCfg = Release|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Release|Any CPU.Build.0 = Release|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Release|iPhone.ActiveCfg = Release|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Release|iPhone.Build.0 = Release|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Release|Any CPU.Build.0 = Release|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Debug|iPhone.Build.0 = Debug|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Release|Any CPU.Build.0 = Release|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Release|iPhone.ActiveCfg = Release|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Release|iPhone.Build.0 = Release|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Release|Any CPU.ActiveCfg = Release|iPhoneSimulator
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Release|Any CPU.Build.0 = Release|iPhoneSimulator
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Debug|iPhone.ActiveCfg = Debug|iPhone
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Debug|iPhone.Build.0 = Debug|iPhone
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Release|Any CPU.ActiveCfg = Release|iPhoneSimulator
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Release|Any CPU.Build.0 = Release|iPhoneSimulator
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Release|iPhone.ActiveCfg = Release|iPhone
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Release|iPhone.Build.0 = Release|iPhone
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
{5D79739D-98C6-48A4-965E-064DB4C59955}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5D79739D-98C6-48A4-965E-064DB4C59955}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5D79739D-98C6-48A4-965E-064DB4C59955}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{5D79739D-98C6-48A4-965E-064DB4C59955}.Debug|iPhone.Build.0 = Debug|Any CPU
{5D79739D-98C6-48A4-965E-064DB4C59955}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{5D79739D-98C6-48A4-965E-064DB4C59955}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{5D79739D-98C6-48A4-965E-064DB4C59955}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5D79739D-98C6-48A4-965E-064DB4C59955}.Release|Any CPU.Build.0 = Release|Any CPU
{5D79739D-98C6-48A4-965E-064DB4C59955}.Release|iPhone.ActiveCfg = Release|Any CPU
{5D79739D-98C6-48A4-965E-064DB4C59955}.Release|iPhone.Build.0 = Release|Any CPU
{5D79739D-98C6-48A4-965E-064DB4C59955}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{5D79739D-98C6-48A4-965E-064DB4C59955}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{A694283C-FE40-4049-88AB-2CAE678FC087}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A694283C-FE40-4049-88AB-2CAE678FC087}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A694283C-FE40-4049-88AB-2CAE678FC087}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{A694283C-FE40-4049-88AB-2CAE678FC087}.Debug|iPhone.Build.0 = Debug|Any CPU
{A694283C-FE40-4049-88AB-2CAE678FC087}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{A694283C-FE40-4049-88AB-2CAE678FC087}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{A694283C-FE40-4049-88AB-2CAE678FC087}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A694283C-FE40-4049-88AB-2CAE678FC087}.Release|Any CPU.Build.0 = Release|Any CPU
{A694283C-FE40-4049-88AB-2CAE678FC087}.Release|iPhone.ActiveCfg = Release|Any CPU
{A694283C-FE40-4049-88AB-2CAE678FC087}.Release|iPhone.Build.0 = Release|Any CPU
{A694283C-FE40-4049-88AB-2CAE678FC087}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{A694283C-FE40-4049-88AB-2CAE678FC087}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

Просмотреть файл

@ -0,0 +1,84 @@
using System.Threading.Tasks;
using SkiaSharp.Views.iOS.Tests;
using Xunit;
namespace SkiaSharp.Views.Forms.Tests
{
public class SKImageSourceHandlerTests : iOSTests
{
private readonly SKImageSourceHandler handler;
public SKImageSourceHandlerTests()
{
handler = new SKImageSourceHandler();
}
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public async Task PixelBackedImageToBitmap(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
using var image = SKImage.FromBitmap(bitmap);
var source = (SKImageImageSource)image;
using var uiImage = await handler.LoadImageAsync(source);
ValidateTestBitmap(uiImage, alpha);
}
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public async Task BitmapToBitmap(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
var source = (SKBitmapImageSource)bitmap;
using var uiImage = await handler.LoadImageAsync(source);
ValidateTestBitmap(uiImage, alpha);
}
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public async Task PixmapToBitmap(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
using var pixmap = bitmap.PeekPixels();
var source = (SKPixmapImageSource)pixmap;
using var uiImage = await handler.LoadImageAsync(source);
ValidateTestBitmap(uiImage, alpha);
}
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public async Task EncodedDataBackedImageToBitmap(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
using var data = bitmap.Encode(SKEncodedImageFormat.Png, 100);
using var image = SKImage.FromEncodedData(data);
var source = (SKImageImageSource)image;
using var uiImage = await handler.LoadImageAsync(source);
ValidateTestBitmap(uiImage, alpha);
}
}
}

Просмотреть файл

@ -94,9 +94,13 @@
<PackageReference Include="System.Buffers" Version="4.5.1" ExcludeAssets="all" />
</ItemGroup>
<ItemGroup>
<Compile Include="FormsExtensionsTests.cs" />
<Compile Include="iOSExtensionsTests.cs" />
<Compile Include="iOSTests.cs" />
<Compile Include="Main.cs" />
<Compile Include="AppDelegate.cs" />
<Compile Include="TestApplicationDelegate.cs" />
<Compile Include="TestExtensions.cs" />
<None Include="Entitlements.plist" />
<None Include="Info.plist" />
</ItemGroup>

Просмотреть файл

@ -0,0 +1,26 @@
using CoreGraphics;
namespace SkiaSharp.Views.iOS.Tests
{
public static class TestExtensions
{
public static SKColor GetPixel(this CGImage cgImage, int x, int y)
{
var data = cgImage.DataProvider.CopyData();
var bytesPerPixel = cgImage.BitsPerPixel / cgImage.BitsPerComponent;
var offset = (y * cgImage.BytesPerRow) + (x * bytesPerPixel);
var a = data[offset + 3];
var r = data[offset + 0];
var g = data[offset + 1];
var b = data[offset + 2];
if (a == 0)
return SKColor.Empty;
return (SKColor)new SKColorF((float)r / a, (float)g / a, (float)b / a, a / 255f);
}
}
}

Просмотреть файл

@ -0,0 +1,67 @@
using Xunit;
namespace SkiaSharp.Views.iOS.Tests
{
public class iOSExtensionsTests : iOSTests
{
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public void PixelBackedImageToUIImage(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
using var image = SKImage.FromBitmap(bitmap);
using var iosBitmap = image.ToUIImage();
ValidateTestBitmap(iosBitmap, alpha);
}
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public void BitmapToUIImage(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
using var uiImage = bitmap.ToUIImage();
ValidateTestBitmap(uiImage, alpha);
}
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public void PixmapToUIImage(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
using var pixmap = bitmap.PeekPixels();
using var uiImage = pixmap.ToUIImage();
ValidateTestBitmap(uiImage, alpha);
}
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public void EncodedDataBackedImageToUIImage(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
using var data = bitmap.Encode(SKEncodedImageFormat.Png, 100);
using var image = SKImage.FromEncodedData(data);
using var uiImage = image.ToUIImage();
ValidateTestBitmap(uiImage, alpha);
}
}
}

Просмотреть файл

@ -0,0 +1,34 @@
using CoreGraphics;
using SkiaSharp.Tests;
using UIKit;
using Xunit;
namespace SkiaSharp.Views.iOS.Tests
{
public abstract class iOSTests : SKTest
{
protected static void ValidateTestBitmap(UIImage uiImage, byte alpha = 255)
{
var cgImage = uiImage.CGImage;
ValidateTestBitmap(cgImage, alpha);
}
protected static void ValidateTestBitmap(CGImage cgImage, byte alpha = 255)
{
Assert.NotNull(cgImage);
Assert.Equal(40, cgImage.Width);
Assert.Equal(40, cgImage.Height);
Assert.Equal(Get(SKColors.Red), cgImage.GetPixel(10, 10));
Assert.Equal(Get(SKColors.Green), cgImage.GetPixel(30, 10));
Assert.Equal(Get(SKColors.Blue), cgImage.GetPixel(10, 30));
Assert.Equal(Get(SKColors.Yellow), cgImage.GetPixel(30, 30));
SKColor Get(SKColor color) =>
alpha == 0
? SKColor.Empty
: color.WithAlpha(alpha);
}
}
}

Просмотреть файл

@ -19,6 +19,23 @@ namespace SkiaSharp.Tests
}
}
[Trait(CategoryKey, GpuCategory)]
[SkippableFact]
public void AbandonContextIsAbandoned()
{
using (var ctx = CreateGlContext()) {
ctx.MakeCurrent();
var grContext = GRContext.CreateGl();
Assert.False(grContext.IsAbandoned);
grContext.AbandonContext();
Assert.True(grContext.IsAbandoned);
}
}
[Trait(CategoryKey, GpuCategory)]
[SkippableFact]
public void CreateDefaultContextWithOptionsIsValid()