Skip to content

Commit

Permalink
Add PropertyItem tests (#46794)
Browse files Browse the repository at this point in the history
* Refactor PropertyItem image code

* Refactor PropertyItemInternal

* Use Windows implementation of PropertyItem in Unix

* PR feedback

* Use ArrayPool
  • Loading branch information
hughbe committed Mar 26, 2021
1 parent 62170c1 commit ec2fedc
Show file tree
Hide file tree
Showing 14 changed files with 717 additions and 559 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,6 @@
<Compile Include="System\Drawing\GdiPlusStreamHelper.Unix.cs" />
<Compile Include="System\Drawing\LibX11Functions.cs" />
<Compile Include="System\Drawing\MarshallingHelpers.cs" />
<Compile Include="System\Drawing\NativeStructs.Unix.cs" />
<Compile Include="System\Drawing\ImageAnimator.Unix.cs" />
<Compile Include="System\Drawing\Image.Unix.cs" />
<Compile Include="System\Drawing\Pen.Unix.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,30 +121,9 @@ private static void PlatformInitialize()
[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipSetImagePalette(IntPtr image, IntPtr palette);

[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipGetPropertyCount(IntPtr image, out uint propNumbers);

[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipGetPropertyIdList(IntPtr image, uint propNumbers, [Out] int[] list);

[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipGetPropertySize(IntPtr image, out int bufferSize, out int propNumbers);

[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipGetAllPropertyItems(IntPtr image, int bufferSize, int propNumbers, IntPtr items);

[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipGetImageBounds(IntPtr image, out RectangleF source, ref GraphicsUnit unit);

[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipGetPropertyItemSize(IntPtr image, int propertyID, out int propertySize);

[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipGetPropertyItem(IntPtr image, int propertyID, int propertySize, IntPtr buffer);

[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipSetPropertyItem(IntPtr image, GdipPropertyItem* propertyItem);

[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipGetImageThumbnail(IntPtr image, uint width, uint height, out IntPtr thumbImage, IntPtr callback, IntPtr callBackData);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,27 +248,6 @@ private static void PlatformInitialize()
[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipGetImagePaletteSize(HandleRef image, out int size);

[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipGetPropertyCount(HandleRef image, out int count);

[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipGetPropertyIdList(HandleRef image, int count, int[] list);

[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipGetPropertyItemSize(HandleRef image, int propid, out int size);

[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipGetPropertyItem(HandleRef image, int propid, int size, IntPtr buffer);

[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipGetPropertySize(HandleRef image, out int totalSize, ref int count);

[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipGetAllPropertyItems(HandleRef image, int totalSize, int count, IntPtr buffer);

[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipSetPropertyItem(HandleRef image, PropertyItemInternal propitem);

[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipImageForceValidation(IntPtr image);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1060,9 +1060,30 @@ internal static unsafe partial class Gdip
[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipImageRotateFlip(HandleRef image, int rotateFlipType);

[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipGetAllPropertyItems(HandleRef image, uint totalBufferSize, uint numProperties, PropertyItemInternal* allItems);

[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipGetPropertyCount(HandleRef image, out uint numOfProperty);

[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipGetPropertyIdList(HandleRef image, uint numOfProperty, int* list);

[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipGetPropertyItem(HandleRef image, int propid, uint propSize, PropertyItemInternal* buffer);

[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipGetPropertyItemSize(HandleRef image, int propid, out uint size);

[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipGetPropertySize(HandleRef image, out uint totalBufferSize, out uint numProperties);

[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipRemovePropertyItem(HandleRef image, int propid);

[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipSetPropertyItem(HandleRef image, PropertyItemInternal* item);

[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipGetImageType(HandleRef image, out int type);

Expand Down
126 changes: 0 additions & 126 deletions src/libraries/System.Drawing.Common/src/System/Drawing/Image.Unix.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,35 +98,6 @@ public RectangleF GetBounds(ref GraphicsUnit pageUnit)
return source;
}

public PropertyItem GetPropertyItem(int propid)
{
int propSize;
IntPtr property;
PropertyItem item = new PropertyItem();
GdipPropertyItem gdipProperty = default;
int status;

status = Gdip.GdipGetPropertyItemSize(nativeImage, propid,
out propSize);
Gdip.CheckStatus(status);

/* Get PropertyItem */
property = Marshal.AllocHGlobal(propSize);
try
{
status = Gdip.GdipGetPropertyItem(nativeImage, propid, propSize, property);
Gdip.CheckStatus(status);
gdipProperty = (GdipPropertyItem)Marshal.PtrToStructure(property,
typeof(GdipPropertyItem))!;
GdipPropertyItem.MarshalTo(gdipProperty, item);
}
finally
{
Marshal.FreeHGlobal(property);
}
return item;
}

public Image GetThumbnailImage(int thumbWidth, int thumbHeight, Image.GetThumbnailImageAbort? callback, IntPtr callbackData)
{
if ((thumbWidth <= 0) || (thumbHeight <= 0))
Expand Down Expand Up @@ -285,37 +256,6 @@ public void SaveAdd(Image image, EncoderParameters encoderParams)
Gdip.CheckStatus(st);
}

public void SetPropertyItem(PropertyItem propitem)
{
if (propitem == null)
throw new ArgumentNullException(nameof(propitem));

int nItemSize = Marshal.SizeOf(propitem.Value![0]);
int size = nItemSize * propitem.Value.Length;
IntPtr dest = Marshal.AllocHGlobal(size);
try
{
GdipPropertyItem pi = default;
pi.id = propitem.Id;
pi.len = propitem.Len;
pi.type = propitem.Type;

Marshal.Copy(propitem.Value, 0, dest, size);
pi.value = dest;

unsafe
{
int status = Gdip.GdipSetPropertyItem(nativeImage, &pi);

Gdip.CheckStatus(status);
}
}
finally
{
Marshal.FreeHGlobal(dest);
}
}

[Browsable(false)]
public ColorPalette Palette
{
Expand Down Expand Up @@ -375,72 +315,6 @@ internal void storeGDIPalette(ColorPalette palette)
}
}

[Browsable(false)]
public int[] PropertyIdList
{
get
{
uint propNumbers;

int status = Gdip.GdipGetPropertyCount(nativeImage,
out propNumbers);
Gdip.CheckStatus(status);

int[] idList = new int[propNumbers];
status = Gdip.GdipGetPropertyIdList(nativeImage,
propNumbers, idList);
Gdip.CheckStatus(status);

return idList;
}
}

[Browsable(false)]
public PropertyItem[] PropertyItems
{
get
{
int propNums, propsSize, propSize;
IntPtr properties, propPtr;
PropertyItem[] items;
GdipPropertyItem gdipProperty = default;
int status;

status = Gdip.GdipGetPropertySize(nativeImage, out propsSize, out propNums);
Gdip.CheckStatus(status);

items = new PropertyItem[propNums];

if (propNums == 0)
return items;

/* Get PropertyItem list*/
properties = Marshal.AllocHGlobal(propsSize * propNums);
try
{
status = Gdip.GdipGetAllPropertyItems(nativeImage, propsSize,
propNums, properties);
Gdip.CheckStatus(status);

propSize = Marshal.SizeOf(gdipProperty);
propPtr = properties;

for (int i = 0; i < propNums; i++, propPtr = new IntPtr(propPtr.ToInt64() + propSize))
{
gdipProperty = (GdipPropertyItem)Marshal.PtrToStructure
(propPtr, typeof(GdipPropertyItem))!;
items[i] = new PropertyItem();
GdipPropertyItem.MarshalTo(gdipProperty, items[i]);
}
}
finally
{
Marshal.FreeHGlobal(properties);
}
return items;
}
}

protected virtual void Dispose(bool disposing)
{
if (nativeImage != IntPtr.Zero)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -390,91 +390,6 @@ public Image GetThumbnailImage(int thumbWidth, int thumbHeight, GetThumbnailImag
return CreateImageObject(thumbImage);
}

/// <summary>
/// Gets an array of the property IDs stored in this <see cref='Image'/>.
/// </summary>
[Browsable(false)]
public int[] PropertyIdList
{
get
{
Gdip.CheckStatus(Gdip.GdipGetPropertyCount(new HandleRef(this, nativeImage), out int count));

int[] propid = new int[count];

//if we have a 0 count, just return our empty array
if (count == 0)
return propid;

Gdip.CheckStatus(Gdip.GdipGetPropertyIdList(new HandleRef(this, nativeImage), count, propid));

return propid;
}
}

/// <summary>
/// Gets the specified property item from this <see cref='Image'/>.
/// </summary>
public PropertyItem? GetPropertyItem(int propid)
{
Gdip.CheckStatus(Gdip.GdipGetPropertyItemSize(new HandleRef(this, nativeImage), propid, out int size));

if (size == 0)
return null;

IntPtr propdata = Marshal.AllocHGlobal(size);

try
{
Gdip.CheckStatus(Gdip.GdipGetPropertyItem(new HandleRef(this, nativeImage), propid, size, propdata));
return PropertyItemInternal.ConvertFromMemory(propdata, 1)[0];
}
finally
{
Marshal.FreeHGlobal(propdata);
}
}

/// <summary>
/// Sets the specified property item to the specified value.
/// </summary>
public void SetPropertyItem(PropertyItem propitem)
{
PropertyItemInternal propItemInternal = PropertyItemInternal.ConvertFromPropertyItem(propitem);

using (propItemInternal)
{
Gdip.CheckStatus(Gdip.GdipSetPropertyItem(new HandleRef(this, nativeImage), propItemInternal));
}
}

/// <summary>
/// Gets an array of <see cref='PropertyItem'/> objects that describe this <see cref='Image'/>.
/// </summary>
[Browsable(false)]
public PropertyItem[] PropertyItems
{
get
{
Gdip.CheckStatus(Gdip.GdipGetPropertyCount(new HandleRef(this, nativeImage), out int count));
Gdip.CheckStatus(Gdip.GdipGetPropertySize(new HandleRef(this, nativeImage), out int size, ref count));

if (size == 0 || count == 0)
return Array.Empty<PropertyItem>();

IntPtr propdata = Marshal.AllocHGlobal(size);
try
{
Gdip.CheckStatus(Gdip.GdipGetAllPropertyItems(new HandleRef(this, nativeImage), size, count, propdata));
return PropertyItemInternal.ConvertFromMemory(propdata, count);
}
finally
{
Marshal.FreeHGlobal(propdata);
}
}
}

internal static void ValidateImage(IntPtr image)
{
try
Expand Down
Loading

0 comments on commit ec2fedc

Please sign in to comment.