xamarin-macios/msbuild/Xamarin.iOS.Tasks.Core/Tasks/CollectITunesArtworkTaskBas...

182 строки
4.9 KiB
C#

using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Xamarin.MacDev.Tasks;
using Xamarin.Localization.MSBuild;
namespace Xamarin.iOS.Tasks
{
public abstract class CollectITunesArtworkTaskBase : XamarinTask
{
#region Inputs
public ITaskItem[] ITunesArtwork { get; set; }
#endregion
#region Outputs
[Output]
public ITaskItem[] ITunesArtworkWithLogicalNames { get; set; }
#endregion
static int ReadInt (BinaryReader reader)
{
int result = 0;
result += (int) reader.ReadByte () << 24;
result += (int) reader.ReadByte () << 16;
result += (int) reader.ReadByte () << 8;
result += (int) reader.ReadByte ();
return result;
}
static bool GetPngImageSize (string path, out int width, out int height)
{
// PNG file format specification can be found at: http://www.w3.org/TR/PNG
BinaryReader reader = null;
width = height = -1;
try {
reader = new BinaryReader (File.OpenRead (path));
var pngHeader = reader.ReadBytes (8);
// Check for valid PNG header.
if (pngHeader[0] != 137 ||
pngHeader[1] != 80 || pngHeader[2] != 78 || pngHeader [3] != 71 ||
pngHeader [4] != 13 || pngHeader [5] != 10 || pngHeader [6] != 26 || pngHeader [7] != 10)
return false;
// First chunk is always the IHDR header chunk
reader.ReadBytes (4); // skip chunk size
var ihdrID = reader.ReadBytes (4);
if (ihdrID[0] != 73 || ihdrID[1] != 72 || ihdrID[2] != 68 || ihdrID[3] != 82)
return false;
width = ReadInt (reader);
height = ReadInt (reader);
return true;
} catch {
return false;
} finally {
if (reader != null)
reader.Close ();
}
}
const string CoreGraphicsLibrary = "/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics";
[DllImport (CoreGraphicsLibrary)]
extern static /* CGDataProviderRef */ IntPtr CGDataProviderCreateWithFilename (/* const char* */ string filename);
[DllImport (CoreGraphicsLibrary)]
extern static void CGDataProviderRelease (/* CGDataProviderRef */ IntPtr provider);
[DllImport (CoreGraphicsLibrary)]
extern static IntPtr CGImageGetWidth (/* CGImageRef */ IntPtr image);
[DllImport (CoreGraphicsLibrary)]
extern static IntPtr CGImageGetHeight (/* CGImageRef */ IntPtr image);
[DllImport (CoreGraphicsLibrary)]
extern static /* CGImageRef */ IntPtr CGImageCreateWithJPEGDataProvider (/* CGDataProviderRef */ IntPtr source, /* CGFloat[] */ IntPtr decode, bool shouldInterpolate, CGColorRenderingIntent intent);
[DllImport (CoreGraphicsLibrary)]
extern static void CGImageRelease (/* CGImageRef */ IntPtr image);
// untyped enum -> CGColorSpace.h
enum CGColorRenderingIntent
{
Default,
AbsoluteColorimetric,
RelativeColorimetric,
Perceptual,
Saturation,
};
static bool GetJpgImageSize (string path, out int width, out int height)
{
width = height = -1;
try {
var provider = CGDataProviderCreateWithFilename (path);
if (provider == IntPtr.Zero)
return false;
try {
var img = CGImageCreateWithJPEGDataProvider (provider, IntPtr.Zero, false, CGColorRenderingIntent.Default);
if (img == IntPtr.Zero)
return false;
try {
width = (int) CGImageGetWidth (img);
height = (int) CGImageGetHeight (img);
} finally {
CGImageRelease (img);
}
} finally {
CGDataProviderRelease (provider);
}
} catch {
return false;
}
return true;
}
public override bool Execute ()
{
var artworkWithLogicalNames = new List<ITaskItem> ();
var artwork = new HashSet<string> ();
if (ITunesArtwork != null) {
foreach (var item in ITunesArtwork) {
// We need a physical path here, ignore the Link element
var path = item.GetMetadata ("FullPath");
string logicalName;
int width, height;
if (!File.Exists (path)) {
Log.LogError (MSBStrings.E0006, path);
continue;
}
if (!GetPngImageSize (path, out width, out height) && !GetJpgImageSize (path, out width, out height)) {
Log.LogError (null, null, null, path, 0, 0, 0, 0, MSBStrings.E0007, path);
return false;
}
if (width != height || (width != 512 && width != 1024)) {
Log.LogError (null, null, null, path, 0, 0, 0, 0, MSBStrings.E0008, width, height, path);
return false;
}
logicalName = width == 1024 ? "iTunesArtwork@2x" : "iTunesArtwork";
if (!artwork.Add (logicalName)) {
Log.LogError (null, null, null, path, 0, 0, 0, 0, MSBStrings.E0009, width, height, path);
return false;
}
var bundleResource = new TaskItem (item);
bundleResource.SetMetadata ("LogicalName", logicalName);
bundleResource.SetMetadata ("Optimize", "false");
artworkWithLogicalNames.Add (bundleResource);
}
}
ITunesArtworkWithLogicalNames = artworkWithLogicalNames.ToArray ();
return !Log.HasLoggedErrors;
}
}
}