Merge pull request #5 from soukoku/v4-dev

First attempt on TW_CAPABILITY generator
This commit is contained in:
Eugene Wang 2018-11-25 07:36:01 -05:00 committed by GitHub
commit 2fca2272f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 567 additions and 151 deletions

225
src/NTwain/CapWriter.cs Normal file
View File

@ -0,0 +1,225 @@
using NTwain.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace NTwain
{
/// <summary>
/// CLass that can generate <see cref="TW_CAPABILITY"/> for use in capability negotiation.
/// </summary>
public class CapWriter
{
private readonly TwainConfig config;
/// <summary>
/// Creates a new <see cref="CapWriter"/>.
/// </summary>
/// <param name="config"></param>
internal CapWriter(TwainConfig config)
{
this.config = config;
}
/// <summary>
/// Generates a <see cref="TW_CAPABILITY"/> using single value (aka TW_ONEVALUE).
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="cap"></param>
/// <param name="type"></param>
/// <param name="value"></param>
/// <returns></returns>
public TW_CAPABILITY Generate<T>(CapabilityId cap, ItemType type, T value)
{
// size of data + uint16 item type
var valueSz = type.GetSize();
if (valueSz < 4) valueSz = 4; // onevalue container value minimum is 32bit
var memSz = valueSz + 2; // + item type field
var twCap = new TW_CAPABILITY
{
Capability = cap,
ContainerType = ContainerType.OneValue,
hContainer = config.MemoryManager.Allocate((uint)memSz)
};
if (twCap.hContainer != IntPtr.Zero)
{
IntPtr baseAddr = config.MemoryManager.Lock(twCap.hContainer);
try
{
int offset = 0;
// TODO: type size may be different on mac
baseAddr.WriteValue(ref offset, ItemType.UInt16, value);
// ONEVALUE is special in value can be uint32 or string
// if less than uint32 put it in lower word
// (string value seems undocumented but internet says put it as-is and not a pointer)
if (valueSz < 4)
{
Marshal.WriteInt16(baseAddr, offset, 0);
offset += 2;
}
baseAddr.WriteValue(ref offset, type, value);
}
finally
{
config.MemoryManager.Unlock(twCap.hContainer);
}
}
return twCap;
}
/// <summary>
/// Generates a <see cref="TW_CAPABILITY"/> for use in capability negotiation
/// using TWAIN's array value.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="cap"></param>
/// <param name="value"></param>
/// <returns></returns>
public TW_CAPABILITY Generate<T>(CapabilityId cap, ArrayValue<T> value)
{
var twCap = new TW_CAPABILITY
{
Capability = cap,
ContainerType = ContainerType.Array,
hContainer = config.MemoryManager.Allocate((uint)Marshal.SizeOf(typeof(TW_ARRAY)))
};
if (twCap.hContainer != IntPtr.Zero)
{
var listSz = value.Type.GetSize() * value.ItemList.Length;
TW_ARRAY container = new TW_ARRAY
{
ItemType = (ushort)value.Type,
NumItems = (uint)value.ItemList.Length,
ItemList = config.MemoryManager.Allocate((uint)listSz)
};
if (container.ItemList != IntPtr.Zero)
{
IntPtr baseAddr = config.MemoryManager.Lock(container.ItemList);
try
{
int offset = 0;
foreach (var it in value.ItemList)
{
baseAddr.WriteValue(ref offset, value.Type, it);
}
}
finally
{
config.MemoryManager.Unlock(container.ItemList);
}
try
{
baseAddr = config.MemoryManager.Lock(twCap.hContainer);
Marshal.StructureToPtr(container, baseAddr, false);
}
finally
{
config.MemoryManager.Unlock(twCap.hContainer);
}
}
else
{
config.MemoryManager.Free(twCap.hContainer);
}
}
return twCap;
}
/// <summary>
/// Generates a <see cref="TW_CAPABILITY"/> for use in capability negotiation
/// using TWAIN's enum value.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="cap"></param>
/// <param name="value"></param>
/// <returns></returns>
public TW_CAPABILITY Generate<T>(CapabilityId cap, EnumValue<T> value)
{
var twCap = new TW_CAPABILITY
{
Capability = cap,
ContainerType = ContainerType.Enum,
hContainer = config.MemoryManager.Allocate((uint)Marshal.SizeOf(typeof(TW_ENUMERATION)))
};
if (twCap.hContainer != IntPtr.Zero)
{
var listSz = value.Type.GetSize() * value.ItemList.Length;
TW_ENUMERATION container = new TW_ENUMERATION
{
ItemType = (ushort)value.Type,
NumItems = (uint)value.ItemList.Length,
CurrentIndex = (uint)value.CurrentIndex,
DefaultIndex = (uint)value.DefaultIndex,
ItemList = config.MemoryManager.Allocate((uint)listSz)
};
if (container.ItemList != IntPtr.Zero)
{
IntPtr baseAddr = config.MemoryManager.Lock(container.ItemList);
try
{
int offset = 0;
foreach (var it in value.ItemList)
{
baseAddr.WriteValue(ref offset, value.Type, it);
}
}
finally
{
config.MemoryManager.Unlock(container.ItemList);
}
try
{
baseAddr = config.MemoryManager.Lock(twCap.hContainer);
Marshal.StructureToPtr(container, baseAddr, false);
}
finally
{
config.MemoryManager.Unlock(twCap.hContainer);
}
}
else
{
config.MemoryManager.Free(twCap.hContainer);
}
}
return twCap;
}
/// <summary>
/// Generates a <see cref="TW_CAPABILITY"/> for use in capability negotiation
/// using TWAIN's range value.
/// </summary>
/// <param name="cap"></param>
/// <param name="value"></param>
/// <returns></returns>
public TW_CAPABILITY Generate(CapabilityId cap, TW_RANGE value)
{
var twCap = new TW_CAPABILITY
{
Capability = cap,
ContainerType = ContainerType.Range,
hContainer = config.MemoryManager.Allocate((uint)Marshal.SizeOf(typeof(TW_RANGE)))
};
if (twCap.hContainer != IntPtr.Zero)
{
try
{
IntPtr baseAddr = config.MemoryManager.Lock(twCap.hContainer);
Marshal.StructureToPtr(value, baseAddr, false);
}
finally
{
config.MemoryManager.Unlock(twCap.hContainer);
}
}
return twCap;
}
}
}

View File

@ -9,22 +9,22 @@ namespace NTwain.Data
// use custom containers for twain container types to not have to worry about memory mgmt
// after giving it to consumers
/// <summary>
/// Container for one value.
/// </summary>
/// <typeparam name="T"></typeparam>
public struct OneValue<T>
{
/// <summary>
/// The type of the item.
/// </summary>
public ItemType Type;
///// <summary>
///// Container for one value.
///// </summary>
///// <typeparam name="T"></typeparam>
//public struct OneValue<T>
//{
// /// <summary>
// /// The type of the item.
// /// </summary>
// public ItemType Type;
/// <summary>
/// The value.
/// </summary>
public T Value;
}
// /// <summary>
// /// The value.
// /// </summary>
// public T Value;
//}
/// <summary>
/// Stores a group of associated individual values for a capability.
@ -50,11 +50,6 @@ namespace NTwain.Data
/// </summary>
public struct EnumValue<T>
{
/// <summary>
/// Gets the byte offset of the item list from a Ptr to the first item.
/// </summary>
internal const int ValuesOffset = 14;
/// <summary>
/// The type of items in the enumerated list.
/// </summary>
@ -79,44 +74,5 @@ namespace NTwain.Data
/// </summary>
public T[] ItemList;
}
/// <summary>
/// Container for a range of values.
/// </summary>
public struct RangeValue
{
/// <summary>
/// The type of items in the container.
/// </summary>
public ItemType Type;
/// <summary>
/// The least positive/most negative value of the range.
/// </summary>
public int Min;
/// <summary>
/// The most positive/least negative value of the range.
/// </summary>
public int Max;
/// <summary>
/// The delta between two adjacent values of the range.
/// e.g. Item2 - Item1 = StepSize;
/// </summary>
public int StepSize;
/// <summary>
/// The devices "power-on" value for the capability. If the application is
/// performing a MSG_SET operation and isnt sure what the default
/// value is, set this field to <see cref="TwainConst.DontCare32"/>.
/// </summary>
public int DefaultValue;
/// <summary>
/// The value to which the device (or its user interface) is currently set to
/// for the capability.
/// </summary>
public int CurrentValue;
}
}

View File

@ -35,17 +35,17 @@ namespace NTwain.Data
[StructLayout(LayoutKind.Sequential, Pack = 2)]
partial struct TW_FIX32
{
TW_INT16 _whole;
TW_UINT16 _frac;
internal TW_INT16 Whole;
internal TW_UINT16 Fraction;
}
[StructLayout(LayoutKind.Sequential, Pack = 2)]
partial struct TW_FRAME
{
TW_FIX32 _left;
TW_FIX32 _top;
TW_FIX32 _right;
TW_FIX32 _bottom;
internal TW_FIX32 _left;
internal TW_FIX32 _top;
internal TW_FIX32 _right;
internal TW_FIX32 _bottom;
}
[StructLayout(LayoutKind.Sequential, Pack = 2)]
@ -111,7 +111,7 @@ namespace NTwain.Data
{
TW_UINT16 _cap;
TW_UINT16 _conType;
TW_HANDLE _hContainer;
internal TW_HANDLE hContainer;
}
[StructLayout(LayoutKind.Sequential, Pack = 2)]
@ -427,13 +427,13 @@ namespace NTwain.Data
TW_UINT32 _sheetCount;
}
[StructLayout(LayoutKind.Sequential, Pack = 2)]
partial class TW_ONEVALUE
{
// TODO: mac is different?
public TW_UINT16 ItemType;
public TW_UINT32 Item;
}
//[StructLayout(LayoutKind.Sequential, Pack = 2)]
//partial class TW_ONEVALUE
//{
// // TODO: mac is different?
// public TW_UINT16 ItemType;
// public TW_UINT32 Item;
//}
[StructLayout(LayoutKind.Sequential, Pack = 2)]
partial struct TW_PALETTE8
@ -465,15 +465,15 @@ namespace NTwain.Data
}
[StructLayout(LayoutKind.Sequential, Pack = 2)]
partial class TW_RANGE
partial struct TW_RANGE
{
// TODO: mac & linux are different?
public TW_UINT16 ItemType;
public TW_UINT32 MinValue;
public TW_UINT32 MaxValue;
public TW_UINT32 StepSize;
public TW_UINT32 DefaultValue;
public TW_UINT32 CurrentValue;
TW_UINT16 _itemType;
TW_UINT32 _minValue;
TW_UINT32 _maxValue;
TW_UINT32 _stepSize;
TW_UINT32 _defaultValue;
TW_UINT32 _currentValue;
}
//[StructLayout(LayoutKind.Sequential, Pack = 2)]

View File

@ -32,22 +32,39 @@ namespace NTwain.Data
float ToFloat()
{
return (float)_whole + _frac / 65536f;
return (float)Whole + Fraction / 65536f;
}
TW_FIX32(float value)
{
//int temp = (int)(value * 65536.0 + 0.5);
//_whole = (short)(temp >> 16);
//_frac = (ushort)(temp & 0x0000ffff);
//Whole = (short)(temp >> 16);
//Fraction = (ushort)(temp & 0x0000ffff);
// different version from twain faq
bool sign = value < 0;
int temp = (int)(value * 65536.0 + (sign ? (-0.5) : 0.5));
_whole = (short)(temp >> 16);
_frac = (ushort)(temp & 0x0000ffff);
Whole = (short)(temp >> 16);
Fraction = (ushort)(temp & 0x0000ffff);
}
/// <summary>
/// Converts this value to a value for communicating with twain data source.
/// </summary>
/// <returns></returns>
public uint ToTransferValue()
{
// probably has a faster way but can't think now
byte[] array = new byte[4];
var part = BitConverter.GetBytes(Whole);
Buffer.BlockCopy(part, 0, array, 0, 2);
part = BitConverter.GetBytes(Fraction);
Buffer.BlockCopy(part, 0, array, 2, 2);
return BitConverter.ToUInt32(array, 0);
}
/// <summary>
/// Returns a <see cref="System.String"/> that represents this instance.
/// </summary>
@ -59,33 +76,6 @@ namespace NTwain.Data
return ToFloat().ToString(CultureInfo.InvariantCulture);
}
///// <summary>
///// Converts this to <see cref="TW_ONEVALUE"/> for capability set methods.
///// </summary>
///// <returns></returns>
//public TW_ONEVALUE ToOneValue()
//{
// // copy struct parts as-is.
// // probably has a faster way but can't think now
// byte[] array = new byte[4];
// var part = BitConverter.GetBytes(Whole);
// Buffer.BlockCopy(part, 0, array, 0, 2);
// part = BitConverter.GetBytes(Fraction);
// Buffer.BlockCopy(part, 0, array, 2, 2);
// var converted = BitConverter.ToUInt32(array, 0);
// return new TW_ONEVALUE
// {
// ItemType = ItemType.Fix32,
// Item = converted
// // old wrong conversion
// // (uint)this,// ((uint)dpi) << 16;
// };
//}
#region equals
/// <summary>
@ -109,7 +99,7 @@ namespace NTwain.Data
/// <returns></returns>
public bool Equals(TW_FIX32 other)
{
return _whole == other._whole && _frac == other._frac;
return Whole == other.Whole && Fraction == other.Fraction;
}
/// <summary>
/// Returns a hash code for this instance.
@ -119,7 +109,7 @@ namespace NTwain.Data
/// </returns>
public override int GetHashCode()
{
return _whole ^ _frac;
return Whole ^ Fraction;
}
#endregion
@ -621,16 +611,14 @@ namespace NTwain.Data
// #region properties
// /// <summary>
// /// Id of capability to set or get.
// /// </summary>
// public CapabilityId Capability { get { return (CapabilityId)_cap; } set { _cap = (ushort)value; } }
// /// <summary>
// /// The type of the container structure referenced by the pointer internally. The container
// /// will be one of four types: <see cref="TW_ARRAY"/>, <see cref="TW_ENUMERATION"/>,
// /// <see cref="TW_ONEVALUE"/>, or <see cref="TW_RANGE"/>.
// /// </summary>
// public ContainerType ContainerType { get { return (ContainerType)_conType; } set { _conType = (ushort)value; } }
/// <summary>
/// Id of capability to set or get.
/// </summary>
public CapabilityId Capability { get { return (CapabilityId)_cap; } internal set { _cap = (ushort)value; } }
/// <summary>
/// The type of the container structure referenced by the pointer internally.
/// </summary>
public ContainerType ContainerType { get { return (ContainerType)_conType; } internal set { _conType = (ushort)value; } }
// internal IntPtr Container { get { return _hContainer; } }
@ -1957,7 +1945,42 @@ namespace NTwain.Data
/// </summary>
public EndXferJob EndOfJob { get { return (EndXferJob)_eOJ; } }
}
/// <summary>
/// Container for a range of values.
/// </summary>
public partial struct TW_RANGE
{
/// <summary>
/// The type of items in the list.
/// </summary>
public ItemType ItemType { get { return (ItemType)_itemType; } set { _itemType = (ushort)value; } }
/// <summary>
/// The least positive/most negative value of the range.
/// </summary>
public uint MinValue { get { return _minValue; } set { _minValue = value; } }
/// <summary>
/// The most positive/least negative value of the range.
/// </summary>
public uint MaxValue { get { return _maxValue; } set { _maxValue = value; } }
/// <summary>
/// The delta between two adjacent values of the range.
/// e.g. Item2 - Item1 = StepSize;
/// </summary>
public uint StepSize { get { return _stepSize; } set { _stepSize = value; } }
/// <summary>
/// The devices "power-on" value for the capability. If the application is
/// performing a MSG_SET operation and isnt sure what the default
/// value is, set this field to <see cref="TwainConst.DontCare32"/>.
/// </summary>
public uint DefaultValue { get { return _defaultValue; } set { _defaultValue = value; } }
/// <summary>
/// The value to which the device (or its user interface) is currently set to
/// for the capability.
/// </summary>
public uint CurrentValue { get { return _currentValue; } set { _currentValue = value; } }
}
// ///// <summary>
// ///// This structure is used by the application to specify a set of mapping values to be applied to RGB

View File

@ -84,19 +84,19 @@ namespace NTwain.Data
/// </summary>
Invalid = 0,
/// <summary>
/// The container is <see cref="TW_ARRAY"/>.
/// The container is TW_ARRAY.
/// </summary>
Array = 3,
/// <summary>
/// The container is <see cref="TW_ENUMERATION"/>.
/// The container is TW_ENUMERATION.
/// </summary>
Enum = 4,
/// <summary>
/// The container is <see cref="TW_ONEVALUE"/>.
/// The container is TW_ONEVALUE.
/// </summary>
OneValue = 5,
/// <summary>
/// The container is <see cref="TW_RANGE"/>.
/// The container is TW_RANGE.
/// </summary>
Range = 6,
/// <summary>

View File

@ -0,0 +1,190 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace NTwain.Data
{
/// <summary>
/// Contains extension methods for reading/writing primitive
/// TWAIN data types.
/// </summary>
static class TypeExtensions
{
static readonly Dictionary<ItemType, int> _sizes = new Dictionary<ItemType, int>
{
{ ItemType.Int8, 1 },
{ ItemType.UInt8, 1 },
{ ItemType.Int16, 2 },
{ ItemType.UInt16, 2 },
{ ItemType.Int32, 4 },
{ ItemType.UInt32, 4 },
{ ItemType.Bool, 2 },
{ ItemType.Fix32, Marshal.SizeOf(typeof(TW_FIX32)) },
{ ItemType.Frame, Marshal.SizeOf(typeof(TW_FRAME)) },
{ ItemType.String128, TwainConst.String128 },
{ ItemType.String255, TwainConst.String255 },
{ ItemType.String32, TwainConst.String32 },
{ ItemType.String64, TwainConst.String64 },
// TODO: find out if it should be fixed 4 bytes or intptr size
{ ItemType.Handle, IntPtr.Size },
};
public static int GetSize(this ItemType type)
{
if(_sizes.TryGetValue(type, out int size)) return size;
throw new NotSupportedException($"Unsupported item type {type}.");
}
#region writes
/// <summary>
/// Writes a TWAIN value.
/// </summary>
/// <param name="baseAddr">The base addr.</param>
/// <param name="offset">The offset.</param>
/// <param name="type">The TWAIN type.</param>
/// <param name="value">The value.</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "1#"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
public static void WriteValue(this IntPtr baseAddr, ref int offset, ItemType type, object value)
{
switch (type)
{
case ItemType.Int8:
case ItemType.UInt8:
Marshal.WriteByte(baseAddr, offset, Convert.ToByte(value, CultureInfo.InvariantCulture));// (byte)value);
break;
case ItemType.Bool:
case ItemType.Int16:
case ItemType.UInt16:
Marshal.WriteInt16(baseAddr, offset, Convert.ToInt16(value, CultureInfo.InvariantCulture));//(short)value);
break;
case ItemType.UInt32:
case ItemType.Int32:
Marshal.WriteInt32(baseAddr, offset, Convert.ToInt32(value, CultureInfo.InvariantCulture));//(int)value);
break;
case ItemType.Fix32:
TW_FIX32 f32 = (TW_FIX32)value;
WriteFix32(baseAddr, ref offset, f32);
return; // no need to update offset for this
case ItemType.Frame:
TW_FRAME frame = (TW_FRAME)value;
WriteFix32(baseAddr, ref offset, frame._left);
WriteFix32(baseAddr, ref offset, frame._top);
WriteFix32(baseAddr, ref offset, frame._right);
WriteFix32(baseAddr, ref offset, frame._bottom);
return; // no need to update offset for this
//case ItemType.String1024:
// WriteString(baseAddr, offset, value as string, 1024);
// break;
case ItemType.String128:
WriteString(baseAddr, offset, (string)value, 128);
break;
case ItemType.String255:
WriteString(baseAddr, offset, (string)value, 255);
break;
case ItemType.String32:
WriteString(baseAddr, offset, (string)value, 32);
break;
case ItemType.String64:
WriteString(baseAddr, offset, (string)value, 64);
break;
//case ItemType.Unicode512:
// WriteUString(baseAddr, offset, value as string, 512);
// break;
}
offset += type.GetSize();
}
private static void WriteFix32(IntPtr baseAddr, ref int offset, TW_FIX32 f32)
{
Marshal.WriteInt16(baseAddr, offset, f32.Whole);
if (f32.Fraction > Int16.MaxValue)
{
Marshal.WriteInt16(baseAddr, offset + 2, (Int16)(f32.Fraction - 32768));
}
else
{
Marshal.WriteInt16(baseAddr, offset + 2, (Int16)f32.Fraction);
}
offset += _sizes[ItemType.Fix32];
}
/// <summary>
/// Writes string value. THIS MAY BE WRONG.
/// </summary>
/// <param name="baseAddr"></param>
/// <param name="offset"></param>
/// <param name="value"></param>
/// <param name="maxLength"></param>
static void WriteString(IntPtr baseAddr, int offset, string value, int maxLength)
{
if (string.IsNullOrEmpty(value))
{
// write zero
Marshal.WriteByte(baseAddr, offset, 0);
}
else
{
for (int i = 0; i < maxLength; i++)
{
if (i == value.Length)
{
// string end reached, so write \0 and quit
Marshal.WriteByte(baseAddr, offset, 0);
return;
}
else
{
Marshal.WriteByte(baseAddr, offset, (byte)value[i]);
offset++;
}
}
// when ended normally also write \0
Marshal.WriteByte(baseAddr, offset, 0);
}
}
///// <summary>
///// Writes unicode string value.
///// </summary>
///// <param name="baseAddr"></param>
///// <param name="offset"></param>
///// <param name="item"></param>
///// <param name="maxLength"></param>
//[EnvironmentPermissionAttribute(SecurityAction.LinkDemand)]
//private void WriteUString(IntPtr baseAddr, int offset, string item, int maxLength)
//{
// if (string.IsNullOrEmpty(item))
// {
// // write zero
// Marshal.WriteInt16(baseAddr, offset, (char)0);
// }
// else
// {
// // use 2 bytes per char
// for (int i = 0; i < maxLength; i++)
// {
// if (i == item.Length)
// {
// // string end reached, so write \0 and quit
// Marshal.WriteInt16(baseAddr, offset, (char)0);
// return;
// }
// else
// {
// Marshal.WriteInt16(baseAddr, offset, item[i]);
// offset += 2;
// }
// }
// // when ended normally also write \0
// Marshal.WriteByte(baseAddr, offset, 0);
// }
//}
#endregion
}
}

View File

@ -8,7 +8,7 @@ namespace NTwain.Internals
{
// probably wrong
class LinuxMemoryManager : IMemoryManager
class MarshalMemoryManager : IMemoryManager
{
public IntPtr Allocate(uint size)
{
@ -22,6 +22,7 @@ namespace NTwain.Internals
public IntPtr Lock(IntPtr handle)
{
// no op
return handle;
}

View File

@ -41,7 +41,7 @@ namespace NTwain.Threading
{
action();
}
catch (Exception ex)
catch
{
// TODO: do something
}

View File

@ -99,7 +99,7 @@ namespace NTwain.Triplets.Control
}
/// <summary>
/// Return all of the labels for a capability of type <see cref="TW_ARRAY"/> or <see cref="TW_ENUMERATION"/>, for example
/// Return all of the labels for a capability of type TW_ARRAY or TW_ENUMERATION, for example
/// "US Letter" for ICapSupportedSizes TWSS_USLETTER.
/// </summary>
/// <param name="capability">The capability.</param>
@ -145,8 +145,8 @@ namespace NTwain.Triplets.Control
/// Changes the Current Value(s) and Available Values of the specified capability to those specified
/// by the application. As of TWAIN 2.2 this only modifies the Current Value of the specified capability, constraints cannot be
/// changed with this.
/// Current Values are set when the container is a <see cref="TW_ONEVALUE"/> or <see cref="TW_ARRAY"/>. Available and
/// Current Values are set when the container is a <see cref="TW_ENUMERATION"/> or <see cref="TW_RANGE"/>.
/// Current Values are set when the container is a TW_ONEVALUE or TW_ARRAY. Available and
/// Current Values are set when the container is a TW_ENUMERATION or TW_RANGE.
/// </summary>
/// <param name="capability">The capability.</param>
/// <returns></returns>
@ -159,8 +159,8 @@ namespace NTwain.Triplets.Control
/// Changes the Current Value(s) and Available Value(s) of the specified capability to those specified
/// by the application.
/// </summary>
/// Current Values are set when the container is a <see cref="TW_ONEVALUE"/> or <see cref="TW_ARRAY"/>. Available and
/// Current Values are set when the container is a <see cref="TW_ENUMERATION"/> or <see cref="TW_RANGE"/>.
/// Current Values are set when the container is a TW_ONEVALUE or TW_ARRAY. Available and
/// Current Values are set when the container is a TW_ENUMERATION or TW_RANGE.
/// <param name="capability">The capability.</param>
/// <returns></returns>
public ReturnCode SetConstraint(ref TW_CAPABILITY capability)

View File

@ -14,17 +14,34 @@ namespace NTwain
/// </summary>
public class TwainConfig
{
internal TwainConfig() { }
internal TwainConfig(PlatformID platform, bool is32Bit)
{
Platform = platform;
Is32Bit = is32Bit;
// initial default until twain entry is available
switch (platform)
{
case PlatformID.Win32NT:
_defaultMemoryManager = new WinMemoryManager();
break;
default:
_defaultMemoryManager = new MarshalMemoryManager();
break;
}
}
readonly IMemoryManager _defaultMemoryManager;
/// <summary>
/// Gets whether the app is running in 32bit.
/// </summary>
public bool Is32Bit { get; internal set; }
public bool Is32Bit { get; private set; }
/// <summary>
/// Gets the platform the app is running on.
/// </summary>
public PlatformID Platform { get; internal set; }
public PlatformID Platform { get; private set; }
//public bool PreferLegacyDsm { get; internal set; }
@ -43,11 +60,9 @@ namespace NTwain
{
get
{
return _memMgr ?? DefaultMemoryManager;
return _memMgr ?? _defaultMemoryManager;
}
internal set { _memMgr = value; }
}
internal IMemoryManager DefaultMemoryManager { get; set; }
}
}

View File

@ -18,8 +18,8 @@ namespace NTwain
private string _companyName;
private Language _lang;
private DataGroups _dg = DataGroups.Image;
private bool _32bit;
private PlatformID _platform;
readonly bool _32bit;
readonly PlatformID _platform;
private Country _country;
/// <summary>
@ -106,17 +106,12 @@ namespace NTwain
/// <returns></returns>
public TwainConfig Build()
{
var config = new TwainConfig
{
Platform = _platform,
Is32Bit = _32bit
};
var config = new TwainConfig(_platform, _32bit);
// todo: change id based on platform
switch (_platform)
{
case PlatformID.Win32NT:
config.DefaultMemoryManager = new WinMemoryManager(); // initial default
config.App32 = new TW_IDENTITY
{
DataFlags = DataFlags.App2,

View File

@ -43,6 +43,15 @@ namespace NTwain
/// </summary>
internal DGAudio DGAudio => dgAudio ?? (dgAudio = new DGAudio(this));
//public CapReader CapReader { get; }
/// <summary>
/// Gets the <see cref="TW_CAPABILITY"/> generator.
/// </summary>
public CapWriter CapWriter { get; }
/// <summary>
/// Occurs when an enabled source has been disabled (back to state 4).
/// </summary>

View File

@ -51,6 +51,8 @@ namespace NTwain
_callback32Delegate = new Callback32(Handle32BitCallback);
break;
}
//CapReader = new CapReader(this);
CapWriter = new CapWriter(config);
}
/// <summary>