2016-05-05 03:14:32 +03:00
/ /
// Test the generated API for all CoreImage filters
/ /
// Authors:
// Sebastien Pouliot <sebastien@xamarin.com>
/ /
// Copyright 2013, 2015 Xamarin Inc.
/ /
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
/ /
// http://www.apache.org/licenses/LICENSE-2.0
/ /
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/ /
#if ! __WATCHOS__
using System ;
using System.Collections.Generic ;
using System.IO ;
using System.Reflection ;
using NUnit.Framework ;
#if XAMCORE_2_0
using CoreImage ;
using Foundation ;
using ObjCRuntime ;
#if ! MONOMAC
using UIKit ;
#endif
#elif MONOMAC
using MonoMac.CoreImage ;
using MonoMac.Foundation ;
#else
using MonoTouch.CoreImage ;
using MonoTouch.Foundation ;
using MonoTouch.ObjCRuntime ;
using MonoTouch.UIKit ;
#endif
namespace Introspection {
[TestFixture]
// we want the tests to be available because we use the linker
[Preserve (AllMembers = true)]
public abstract class ApiCoreImageFiltersTest : ApiBaseTest {
static Type CIFilterType = typeof ( CIFilter ) ;
protected virtual bool Skip ( Type type )
{
return Skip ( type . Name ) | | SkipDueToAttribute ( type ) ;
}
protected virtual bool Skip ( string nativeName )
{
switch ( nativeName ) {
// Both reported in radar #21548819
// NSUnknownKeyException [<CIDepthOfField 0x158586970> valueForUndefinedKey:]: this class is not key value coding-compliant for the key inputPoint2.
case "CIDepthOfField" :
// NSUnknownKeyException [<CISunbeamsGenerator 0x1586d0810> valueForUndefinedKey:]: this class is not key value coding-compliant for the key inputCropAmount.
case "CISunbeamsGenerator" :
2017-09-14 19:33:31 +03:00
case "CIAreaMinMaxRed" : // https://bugzilla.xamarin.com/show_bug.cgi?id=57350
case "CIAttributedTextImageGenerator" : // https://bugzilla.xamarin.com/show_bug.cgi?id=57350
case "CIBarcodeGenerator" : // https://bugzilla.xamarin.com/show_bug.cgi?id=57350
case "CIBicubicScaleTransform" : // https://bugzilla.xamarin.com/show_bug.cgi?id=57350
case "CIBlendWithBlueMask" : // https://bugzilla.xamarin.com/show_bug.cgi?id=57350
case "CIBlendWithRedMask" : // https://bugzilla.xamarin.com/show_bug.cgi?id=57350
case "CIBokehBlur" : // https://bugzilla.xamarin.com/show_bug.cgi?id=57350
case "CIColorCubesMixedWithMask" : // https://bugzilla.xamarin.com/show_bug.cgi?id=57350
case "CIColorCurves" : // https://bugzilla.xamarin.com/show_bug.cgi?id=57350
case "CIDepthBlurEffect" : // https://bugzilla.xamarin.com/show_bug.cgi?id=57350
case "CIDepthToDisparity" : // https://bugzilla.xamarin.com/show_bug.cgi?id=57350
case "CIDisparityToDepth" : // https://bugzilla.xamarin.com/show_bug.cgi?id=57350
case "CIEdgePreserveUpsampleFilter" : // https://bugzilla.xamarin.com/show_bug.cgi?id=57350
case "CILabDeltaE" : // https://bugzilla.xamarin.com/show_bug.cgi?id=57350
case "CIMorphologyGradient" : // https://bugzilla.xamarin.com/show_bug.cgi?id=57350
case "CIMorphologyMaximum" : // https://bugzilla.xamarin.com/show_bug.cgi?id=57350
case "CIMorphologyMinimum" : // https://bugzilla.xamarin.com/show_bug.cgi?id=57350
case "CITextImageGenerator" : // https://bugzilla.xamarin.com/show_bug.cgi?id=57350
2016-05-05 03:14:32 +03:00
return true ;
// FIXME: Remove if fixed. Doesn't appear to exist in El Capitan. Reported in radar #22099780
// case "CIMaskedVariableBlur":
// cd .. return true;
default :
return false ;
}
}
[Test]
// this test checks that all native filters have a managed peer, i.e. against missing filters
public void CheckNativeFilters ( )
{
List < string > filters = new List < string > ( ) ;
int n = 0 ;
string qname = CIFilterType . AssemblyQualifiedName ;
// that will give us only the list of filters supported by the executing version of iOS
foreach ( var filter_name in CIFilter . FilterNamesInCategories ( null ) ) {
if ( Skip ( filter_name ) )
continue ;
string type_name = qname . Replace ( "CIFilter" , filter_name ) ;
if ( Type . GetType ( type_name , false , true ) = = null ) {
filters . Add ( filter_name ) ;
// uncomment to generate bindings for any new native filter
// GenerateBinding (CIFilter.FromName (filter_name), Console.Out);
}
n + + ;
}
Assert . That ( filters . Count , Is . EqualTo ( 0 ) , "{0} native filters missing: {1}" , filters . Count , String . Join ( ", " , filters ) ) ;
}
[Test]
// this test checks that all managed filters have a native peer, i.e. against extra filters
public void CheckManagedFilters ( )
{
List < string > filters = new List < string > ( CIFilter . FilterNamesInCategories ( null ) ) ;
var nspace = CIFilterType . Namespace ;
var types = CIFilterType . Assembly . GetTypes ( ) ;
foreach ( Type t in types ) {
if ( t . Namespace ! = nspace )
continue ;
if ( t . IsAbstract | | ! CIFilterType . IsAssignableFrom ( t ) )
continue ;
// we need to skip the filters that are not supported by the executing version of iOS
if ( Skip ( t ) )
continue ;
var ctor = t . GetConstructor ( Type . EmptyTypes ) ;
if ( ( ctor = = null ) | | ctor . IsAbstract )
continue ;
NSObject obj = ctor . Invoke ( null ) as NSObject ;
Assert . That ( obj . Handle , Is . Not . EqualTo ( IntPtr . Zero ) , t . Name + ".Handle" ) ;
#if false
// check base type - we might have our own base type or different names, so it's debug only (not failure)
var super = new Class ( obj . Class . SuperClass ) . Name ;
var bt = t . BaseType . Name ;
if ( ( super ! = bt ) & & ( bt = = "CIFilter" ) ) // check if we should (like Apple) use a non-default base type for filters
Console . WriteLine ( "[WARN] {0}.SuperClass == {1} (native) and {2} managed" , t . Name , super , bt ) ;
#endif
int result = filters . RemoveAll ( s = > StringComparer . OrdinalIgnoreCase . Compare ( t . Name , s ) = = 0 ) ;
Assert . That ( result , Is . GreaterThan ( 0 ) , t . Name ) ;
}
// in case it's a buggy filter we need to try to remove it from the list too
for ( int i = filters . Count - 1 ; i > = 0 ; i - - ) {
if ( Skip ( filters [ i ] ) )
filters . RemoveAt ( i ) ;
}
Assert . That ( filters . Count , Is . EqualTo ( 0 ) , "Managed filters not found for {0}" , String . Join ( ", " , filters ) ) ;
}
static void GenerateBinding ( NSObject filter , TextWriter writer )
{
NSObject value ;
var attributes = ( filter as CIFilter ) . Attributes ;
writer . WriteLine ( "[CoreImageFilter]" ) ;
if ( ! attributes . TryGetValue ( ( NSString ) "CIAttributeFilterAvailable_iOS" , out value ) ) {
writer . WriteLine ( "[NoiOS]" ) ;
} else {
var v = value . ToString ( ) ;
// in the (quite common) case we get "5" for iOS 5.0
if ( v . IndexOf ( '.' ) = = - 1 )
v + = ".0" ;
var ios = Version . Parse ( v ) ;
// we only document availability for iOS 6+
if ( ios . Major > 5 )
writer . WriteLine ( "[iOS ({0},{1})]" , ios . Major , ios . Minor ) ;
}
if ( ! attributes . TryGetValue ( ( NSString ) "CIAttributeFilterAvailable_Mac" , out value ) ) {
writer . WriteLine ( "[NoMac]" ) ;
} else {
try {
var mac = Version . Parse ( value . ToString ( ) ) ;
// we only document availability for 10.7+
if ( mac . Minor > 6 )
writer . WriteLine ( "[Mac ({0},{1})]" , mac . Major , mac . Minor ) ;
}
catch ( FormatException ) {
// 10.? is not a valid version - we'll assume it was added a long time ago (in a galaxy far away)
writer . WriteLine ( "// incorrect version string for OSX: '{0}' Double-check documentation" , value ) ;
}
}
writer . WriteLine ( "[BaseType (typeof (CIFilter))]" ) ;
var fname = attributes [ ( NSString ) "CIAttributeFilterName" ] . ToString ( ) ;
writer . WriteLine ( "interface {0} {{" , fname ) ;
foreach ( var k in attributes . Keys ) {
var key = k . ToString ( ) ;
if ( key . StartsWith ( "CIAttribute" , StringComparison . Ordinal ) )
continue ;
// CIFilter defines it for all filters
if ( key = = "inputImage" )
continue ;
writer . WriteLine ( ) ;
var dict = attributes [ k ] as NSDictionary ;
var type = dict [ ( NSString ) "CIAttributeClass" ] ;
writer . WriteLine ( "\t[CoreImageProperty (\"{0}\")]" , key ) ;
// by default we drop the "input" prefix, but keep the "output" prefix to avoid confusion
if ( key . StartsWith ( "input" , StringComparison . Ordinal ) )
key = Char . ToUpperInvariant ( key [ 5 ] ) + key . Substring ( 6 ) ;
var ptype = type . ToString ( ) ;
// Too many things ends up in NSNumber but we do a better job in our bindings
if ( ptype = = "NSNumber" ) {
ptype = "float" ;
writer . WriteLine ( "\t// TODO: this was an NSNumber transformed to float, but maybe an int or bool is more appropriate" ) ;
}
writer . WriteLine ( "\t{0} {1} {{ get; set; }}" , ptype , key ) ;
}
writer . WriteLine ( "}" ) ;
writer . WriteLine ( ) ;
}
}
}
#endif // !__WATCHOS__