Work in progress, making the clipboard & drag/drop work again. SvgContainer seems to work, added MetaFileFormatHandler & MetafileContainer for the EMF/WMF file formats.

This commit is contained in:
Robin Krom 2022-02-09 22:00:17 +01:00
commit eb9bbb8937
No known key found for this signature in database
GPG key ID: BCC01364F1371490
22 changed files with 611 additions and 326 deletions

View file

@ -34,6 +34,7 @@ using Greenshot.Base.Core.Enums;
using Greenshot.Base.Core.FileFormatHandlers;
using Greenshot.Base.IniFile;
using Greenshot.Base.Interfaces;
using Greenshot.Base.Interfaces.Drawing;
using Greenshot.Base.Interfaces.Plugin;
using Greenshot.Base.UnmanagedHelpers;
using log4net;
@ -300,13 +301,14 @@ EndSelection:<<<<<<<4
return true;
}
var supportedExtensions = FileFormatHandlerRegistry.ExtensionsFor(FileFormatHandlerActions.LoadDrawableFromStream).ToList();
foreach (var fileData in IterateClipboardContent(dataObject))
{
try
{
using (ImageHelper.FromStream(fileData))
var extension = Path.GetExtension(fileData.filename)?.ToLowerInvariant();
if (supportedExtensions.Contains(extension))
{
// If we get here, there is an image
return true;
}
}
@ -316,7 +318,7 @@ EndSelection:<<<<<<<4
}
finally
{
fileData?.Dispose();
fileData.stream?.Dispose();
}
}
@ -328,6 +330,7 @@ EndSelection:<<<<<<<4
var imageStream = clipboardContent as MemoryStream;
if (IsValidStream(imageStream))
{
// TODO: How to check if we support "just a stream"?
using (ImageHelper.FromStream(imageStream))
{
// If we get here, there is an image
@ -374,8 +377,8 @@ EndSelection:<<<<<<<4
/// Iterate the clipboard content
/// </summary>
/// <param name="dataObject">IDataObject</param>
/// <returns>IEnumerable{MemoryStream}</returns>
private static IEnumerable<MemoryStream> IterateClipboardContent(IDataObject dataObject)
/// <returns>IEnumerable{(MemoryStream,string)}</returns>
private static IEnumerable<(MemoryStream stream,string filename)> IterateClipboardContent(IDataObject dataObject)
{
var fileDescriptors = AvailableFileDescriptors(dataObject);
if (fileDescriptors == null) yield break;
@ -414,8 +417,8 @@ EndSelection:<<<<<<<4
/// </summary>
/// <param name="fileDescriptors">IEnumerable{FileDescriptor}</param>
/// <param name="dataObject">IDataObject</param>
/// <returns>IEnumerable{MemoryStream}</returns>
private static IEnumerable<MemoryStream> IterateFileDescriptors(IEnumerable<FileDescriptor> fileDescriptors, IDataObject dataObject)
/// <returns>IEnumerable{(MemoryStream stream, string filename)}</returns>
private static IEnumerable<(MemoryStream stream, string filename)> IterateFileDescriptors(IEnumerable<FileDescriptor> fileDescriptors, IDataObject dataObject)
{
if (fileDescriptors == null)
{
@ -446,7 +449,7 @@ EndSelection:<<<<<<<4
if (fileData?.Length > 0)
{
fileData.Position = 0;
yield return fileData;
yield return (fileData, fileDescriptor.FileName);
}
fileIndex++;
@ -505,56 +508,75 @@ EndSelection:<<<<<<<4
/// </summary>
/// <param name="dataObject"></param>
/// <returns>IEnumerable of Image</returns>
public static IEnumerable<Image> GetImages(IDataObject dataObject)
public static IEnumerable<IDrawableContainer> GetImages(IDataObject dataObject)
{
// Get single image, this takes the "best" match
Image singleImage = GetImage(dataObject);
IDrawableContainer singleImage = GetImage(dataObject);
if (singleImage != null)
{
Log.InfoFormat("Got image from clipboard with size {0} and format {1}", singleImage.Size, singleImage.PixelFormat);
Log.InfoFormat($"Got {singleImage.GetType()} from clipboard with size {singleImage.Size}");
yield return singleImage;
yield break;
}
else
var supportedExtensions = FileFormatHandlerRegistry.ExtensionsFor(FileFormatHandlerActions.LoadDrawableFromStream).ToList();
foreach (var fileData in IterateClipboardContent(dataObject))
{
foreach (var fileData in IterateClipboardContent(dataObject))
var extension = Path.GetExtension(fileData.filename)?.ToLowerInvariant();
if (!supportedExtensions.Contains(extension))
{
Image image;
try
continue;
}
IDrawableContainer drawableContainer = null;
try
{
if (!FileFormatHandlerRegistry.TryLoadDrawableFromStream(fileData.stream, extension, out drawableContainer))
{
image = ImageHelper.FromStream(fileData);
}
catch (Exception ex)
{
Log.Error("Couldn't read file contents", ex);
continue;
}
finally
{
fileData?.Dispose();
}
// If we get here, there is an image
yield return image;
}
// check if files are supplied
foreach (string imageFile in GetImageFilenames(dataObject))
}
catch (Exception ex)
{
Image returnImage = null;
try
{
returnImage = ImageHelper.LoadImage(imageFile);
}
catch (Exception streamImageEx)
{
Log.Error("Problem retrieving Image from clipboard.", streamImageEx);
}
Log.Error("Couldn't read file contents", ex);
continue;
}
finally
{
fileData.stream?.Dispose();
}
// If we get here, there is an image
yield return drawableContainer;
}
if (returnImage != null)
// check if files are supplied
foreach (string imageFile in GetImageFilenames(dataObject))
{
var extension = Path.GetExtension(imageFile)?.ToLowerInvariant();
if (!supportedExtensions.Contains(extension))
{
continue;
}
IDrawableContainer drawableContainer = null;
using FileStream fileStream = new FileStream(imageFile, FileMode.Open, FileAccess.Read, FileShare.Read);
try
{
if (!FileFormatHandlerRegistry.TryLoadDrawableFromStream(fileStream, extension, out drawableContainer))
{
Log.InfoFormat("Got image from clipboard with size {0} and format {1}", returnImage.Size, returnImage.PixelFormat);
yield return returnImage;
continue;
}
}
catch (Exception ex)
{
Log.Error("Couldn't read file contents", ex);
continue;
}
// If we get here, there is an image
yield return drawableContainer;
}
}
@ -563,51 +585,50 @@ EndSelection:<<<<<<<4
/// </summary>
/// <param name="dataObject"></param>
/// <returns>Image or null</returns>
private static Image GetImage(IDataObject dataObject)
private static IDrawableContainer GetImage(IDataObject dataObject)
{
Image returnImage = null;
if (dataObject != null)
{
IList<string> formats = GetFormats(dataObject);
string[] retrieveFormats;
if (dataObject == null) return null;
// Found a weird bug, where PNG's from Outlook 2010 are clipped
// So I build some special logic to get the best format:
if (formats != null && formats.Contains(FORMAT_PNG_OFFICEART) && formats.Contains(DataFormats.Dib))
IDrawableContainer returnImage = null;
IList<string> formats = GetFormats(dataObject);
string[] retrieveFormats;
// Found a weird bug, where PNG's from Outlook 2010 are clipped
// So I build some special logic to get the best format:
if (formats != null && formats.Contains(FORMAT_PNG_OFFICEART) && formats.Contains(DataFormats.Dib))
{
// Outlook ??
Log.Info("Most likely the current clipboard contents come from Outlook, as this has a problem with PNG and others we place the DIB format to the front...");
retrieveFormats = new[]
{
// Outlook ??
Log.Info("Most likely the current clipboard contents come from Outlook, as this has a problem with PNG and others we place the DIB format to the front...");
retrieveFormats = new[]
{
DataFormats.Dib, FORMAT_BITMAP, FORMAT_FILECONTENTS, FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JPEG, FORMAT_JFIF,
DataFormats.Tiff, FORMAT_GIF, FORMAT_HTML
};
DataFormats.Dib, FORMAT_BITMAP, FORMAT_FILECONTENTS, FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JPEG, FORMAT_JFIF,
DataFormats.Tiff, FORMAT_GIF, FORMAT_HTML
};
}
else
{
retrieveFormats = new[]
{
FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_17, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JPEG, FORMAT_JFIF, DataFormats.Tiff, DataFormats.Dib, FORMAT_BITMAP,
FORMAT_FILECONTENTS, FORMAT_GIF, FORMAT_HTML
};
}
foreach (string currentFormat in retrieveFormats)
{
if (formats != null && formats.Contains(currentFormat))
{
Log.InfoFormat("Found {0}, trying to retrieve.", currentFormat);
returnImage = GetImageForFormat(currentFormat, dataObject);
}
else
{
retrieveFormats = new[]
{
FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_17, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JPEG, FORMAT_JFIF, DataFormats.Tiff, DataFormats.Dib, FORMAT_BITMAP,
FORMAT_FILECONTENTS, FORMAT_GIF, FORMAT_HTML
};
Log.DebugFormat("Couldn't find format {0}.", currentFormat);
}
foreach (string currentFormat in retrieveFormats)
if (returnImage != null)
{
if (formats != null && formats.Contains(currentFormat))
{
Log.InfoFormat("Found {0}, trying to retrieve.", currentFormat);
returnImage = GetImageForFormat(currentFormat, dataObject);
}
else
{
Log.DebugFormat("Couldn't find format {0}.", currentFormat);
}
if (returnImage != null)
{
return returnImage;
}
return returnImage;
}
}
@ -615,15 +636,17 @@ EndSelection:<<<<<<<4
}
/// <summary>
/// Helper method to try to get an image in the specified format from the dataObject
/// Helper method to try to get an IDrawableContainer in the specified format from the dataObject
/// the DIB reader should solve some issues
/// It also supports Format17/DibV5, by using the following information: https://stackoverflow.com/a/14335591
/// </summary>
/// <param name="format">string with the format</param>
/// <param name="dataObject">IDataObject</param>
/// <returns>Image or null</returns>
private static Image GetImageForFormat(string format, IDataObject dataObject)
/// <returns>IDrawableContainer or null</returns>
private static IDrawableContainer GetImageForFormat(string format, IDataObject dataObject)
{
IDrawableContainer drawableContainer = null;
if (format == FORMAT_HTML)
{
var textObject = ContentAsString(dataObject, FORMAT_HTML, Encoding.UTF8);
@ -639,10 +662,10 @@ EndSelection:<<<<<<<4
var srcAttribute = imgNode.Attributes["src"];
var imageUrl = srcAttribute.Value;
Log.Debug(imageUrl);
var image = NetworkHelper.DownloadImage(imageUrl);
if (image != null)
drawableContainer = NetworkHelper.DownloadImageAsDrawableContainer(imageUrl);
if (drawableContainer != null)
{
return image;
return drawableContainer;
}
}
}
@ -653,110 +676,29 @@ EndSelection:<<<<<<<4
var imageStream = clipboardObject as MemoryStream;
if (!IsValidStream(imageStream))
{
// TODO: add "HTML Format" support here...
// TODO: add text based, like "HTML Format" support here...
// TODO: solve the issue that we do not have a factory for the ImageContainer
/*var image = clipboardObject as Image;
if (image != null)
{
return new ImageContainer(this)
{
Image = image,
Left = x,
Top = y
};
}
return clipboardObject as Image;
*/
return null;
}
if (CoreConfig.EnableSpecialDIBClipboardReader)
// From here, imageStream is a valid stream
if (!FileFormatHandlerRegistry.TryLoadDrawableFromStream(imageStream, format, out drawableContainer))
{
if (format == FORMAT_17 || format == DataFormats.Dib)
{
Log.Info("Found DIB stream, trying to process it.");
try
{
if (imageStream != null)
{
byte[] dibBuffer = new byte[imageStream.Length];
_ = imageStream.Read(dibBuffer, 0, dibBuffer.Length);
var infoHeader = BinaryStructHelper.FromByteArray<BITMAPINFOHEADERV5>(dibBuffer);
if (!infoHeader.IsDibV5)
{
Log.InfoFormat("Using special DIB <v5 format reader with biCompression {0}", infoHeader.biCompression);
int fileHeaderSize = Marshal.SizeOf(typeof(BITMAPFILEHEADER));
uint infoHeaderSize = infoHeader.biSize;
int fileSize = (int) (fileHeaderSize + infoHeader.biSize + infoHeader.biSizeImage);
var fileHeader = new BITMAPFILEHEADER
{
bfType = BITMAPFILEHEADER.BM,
bfSize = fileSize,
bfReserved1 = 0,
bfReserved2 = 0,
bfOffBits = (int) (fileHeaderSize + infoHeaderSize + infoHeader.biClrUsed * 4)
};
byte[] fileHeaderBytes = BinaryStructHelper.ToByteArray(fileHeader);
using var bitmapStream = new MemoryStream();
bitmapStream.Write(fileHeaderBytes, 0, fileHeaderSize);
bitmapStream.Write(dibBuffer, 0, dibBuffer.Length);
bitmapStream.Seek(0, SeekOrigin.Begin);
var image = ImageHelper.FromStream(bitmapStream);
if (image != null)
{
return image;
}
}
else
{
Log.Info("Using special DIBV5 / Format17 format reader");
// CF_DIBV5
IntPtr gcHandle = IntPtr.Zero;
try
{
GCHandle handle = GCHandle.Alloc(dibBuffer, GCHandleType.Pinned);
gcHandle = GCHandle.ToIntPtr(handle);
return
new Bitmap(infoHeader.biWidth, infoHeader.biHeight,
-(int) (infoHeader.biSizeImage / infoHeader.biHeight),
infoHeader.biBitCount == 32 ? PixelFormat.Format32bppArgb : PixelFormat.Format24bppRgb,
new IntPtr(handle.AddrOfPinnedObject().ToInt32() + infoHeader.OffsetToPixels +
(infoHeader.biHeight - 1) * (int) (infoHeader.biSizeImage / infoHeader.biHeight))
);
}
catch (Exception ex)
{
Log.Error("Problem retrieving Format17 from clipboard.", ex);
}
finally
{
if (gcHandle == IntPtr.Zero)
{
GCHandle.FromIntPtr(gcHandle).Free();
}
}
}
}
}
catch (Exception dibEx)
{
Log.Error("Problem retrieving DIB from clipboard.", dibEx);
}
}
return drawableContainer;
}
else
{
Log.Info("Skipping special DIB format reader as it's disabled in the configuration.");
}
try
{
if (imageStream != null)
{
imageStream.Seek(0, SeekOrigin.Begin);
var tmpImage = ImageHelper.FromStream(imageStream);
if (tmpImage != null)
{
Log.InfoFormat("Got image with clipboard format {0} from the clipboard.", format);
return tmpImage;
}
}
}
catch (Exception streamImageEx)
{
Log.Error($"Problem retrieving {format} from clipboard.", streamImageEx);
}
return null;
}
@ -1132,16 +1074,14 @@ EndSelection:<<<<<<<4
public static IEnumerable<string> GetImageFilenames(IDataObject dataObject)
{
string[] dropFileNames = (string[])dataObject.GetData(DataFormats.FileDrop);
if (dropFileNames != null && dropFileNames.Length > 0)
{
var supportedExtensions = FileFormatHandlerRegistry.ExtensionsFor(FileFormatHandlerActions.LoadFromStream).ToList();
return dropFileNames
.Where(filename => !string.IsNullOrEmpty(filename))
.Where(Path.HasExtension)
.Where(filename => supportedExtensions.Contains(Path.GetExtension(filename).ToLowerInvariant().Substring(1)));
}
if (dropFileNames is not { Length: > 0 }) return Enumerable.Empty<string>();
var supportedExtensions = FileFormatHandlerRegistry.ExtensionsFor(FileFormatHandlerActions.LoadFromStream).ToList();
return dropFileNames
.Where(filename => !string.IsNullOrEmpty(filename))
.Where(Path.HasExtension)
.Where(filename => supportedExtensions.Contains(Path.GetExtension(filename)));
return Enumerable.Empty<string>();
}
/// <summary>

View file

@ -0,0 +1,27 @@
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using Greenshot.Base.Interfaces;
using Greenshot.Base.Interfaces.Drawing;
namespace Greenshot.Base.Core.FileFormatHandlers
{
public abstract class AbstractFileFormatHandler
{
/// <summary>
/// Make sure we handle the input extension always the same, by "normalizing" it
/// </summary>
/// <param name="extension">string</param>
/// <returns>string</returns>
protected string NormalizeExtension(string extension)
{
if (string.IsNullOrEmpty(extension))
{
return null;
}
extension = extension.ToLowerInvariant();
return !extension.StartsWith(".") ? $".{extension}" : extension;
}
}
}

View file

@ -24,6 +24,7 @@ using System.Drawing;
using System.IO;
using System.Linq;
using Greenshot.Base.Interfaces;
using Greenshot.Base.Interfaces.Drawing;
namespace Greenshot.Base.Core.FileFormatHandlers
{
@ -31,13 +32,6 @@ namespace Greenshot.Base.Core.FileFormatHandlers
{
public static IList<IFileFormatHandler> FileFormatHandlers { get; } = new List<IFileFormatHandler>();
static FileFormatHandlerRegistry()
{
FileFormatHandlers.Add(new IconFileFormatHandler());
FileFormatHandlers.Add(new GreenshotFileFormatHandler());
FileFormatHandlers.Add(new DefaultFileFormatHandler());
}
public static IEnumerable<string> ExtensionsFor(FileFormatHandlerActions fileFormatHandlerAction)
{
return FileFormatHandlers.SelectMany(ffh => ffh.SupportedExtensions(fileFormatHandlerAction)).Distinct();
@ -66,5 +60,29 @@ namespace Greenshot.Base.Core.FileFormatHandlers
return fileFormatHandler.TrySaveToStream(bitmap, destination, extension);
}
/// <summary>
/// Try to load a drawable container from the stream
/// </summary>
/// <param name="stream">Stream</param>
/// <param name="extension">string</param>
/// <param name="drawableContainer">IDrawableContainer out</param>
/// <param name="parentSurface">ISurface</param>
/// <returns>bool true if it was successful</returns>
public static bool TryLoadDrawableFromStream(Stream stream, string extension, out IDrawableContainer drawableContainer, ISurface parentSurface = null)
{
var fileFormatHandler = FileFormatHandlers
.Where(ffh => ffh.Supports(FileFormatHandlerActions.LoadDrawableFromStream, extension))
.OrderBy(ffh => ffh.PriorityFor(FileFormatHandlerActions.LoadDrawableFromStream, extension))
.FirstOrDefault();
if (fileFormatHandler == null)
{
drawableContainer = null;
return false;
}
return fileFormatHandler.TryLoadDrawableFromStream(stream, extension, out drawableContainer, parentSurface);
}
}
}

View file

@ -1320,7 +1320,7 @@ namespace Greenshot.Base.Core
}
// If no pixelformat is supplied
if (PixelFormat.DontCare == targetFormat || PixelFormat.Undefined == targetFormat)
if (targetFormat is PixelFormat.DontCare or PixelFormat.Undefined)
{
if (SupportsPixelFormat(sourceImage.PixelFormat))
{

View file

@ -31,6 +31,7 @@ using System.Text.RegularExpressions;
using Greenshot.Base.Core.FileFormatHandlers;
using Greenshot.Base.IniFile;
using Greenshot.Base.Interfaces;
using Greenshot.Base.Interfaces.Drawing;
using Greenshot.Base.Interfaces.Plugin;
using log4net;
@ -89,25 +90,13 @@ namespace Greenshot.Base.Core
}
/// <summary>
/// Download the uri to Bitmap
/// Download the uri to build an IDrawableContainer
/// </summary>
/// <param name="url">Of an image</param>
/// <returns>Bitmap</returns>
public static Image DownloadImage(string url)
/// <returns>IDrawableContainer</returns>
public static IDrawableContainer DownloadImageAsDrawableContainer(string url)
{
var extensions = new StringBuilder();
var supportedExtensions = FileFormatHandlerRegistry.ExtensionsFor(FileFormatHandlerActions.LoadFromStream).ToList();
foreach (var extension in supportedExtensions)
{
if (string.IsNullOrEmpty(extension))
{
continue;
}
extensions.AppendFormat(@"\.{0}|", extension);
}
extensions.Length--;
var extensions = string.Join("|", FileFormatHandlerRegistry.ExtensionsFor(FileFormatHandlerActions.LoadFromStream));
var imageUrlRegex = new Regex($@"(http|https)://.*(?<extension>{extensions})");
var match = imageUrlRegex.Match(url);
@ -116,7 +105,10 @@ namespace Greenshot.Base.Core
using var memoryStream = GetAsMemoryStream(url);
try
{
return ImageHelper.FromStream(memoryStream, match.Success ? match.Groups["extension"]?.Value : null);
if (FileFormatHandlerRegistry.TryLoadDrawableFromStream(memoryStream, match.Success ? match.Groups["extension"]?.Value : null, out var drawableContainer))
{
return drawableContainer;
}
}
catch (Exception)
{
@ -139,7 +131,10 @@ namespace Greenshot.Base.Core
}
using var memoryStream2 = GetAsMemoryStream(match.Value);
return ImageHelper.FromStream(memoryStream2, match.Groups["extension"]?.Value);
if (FileFormatHandlerRegistry.TryLoadDrawableFromStream(memoryStream2, match.Success ? match.Groups["extension"]?.Value : null, out var drawableContainer))
{
return drawableContainer;
}
}
}
catch (Exception e)

View file

@ -30,7 +30,14 @@ namespace Greenshot.Base.Interfaces.Drawing
{
public interface IDrawableContainer : INotifyPropertyChanged, IDisposable
{
/// <summary>
/// The parent surface where this IDrawableContainer is on
/// </summary>
ISurface Parent { get; set; }
/// <summary>
/// Is this IDrawableContainer selected on the surface
/// </summary>
bool Selected { get; set; }
int Left { get; set; }
@ -54,15 +61,25 @@ namespace Greenshot.Base.Interfaces.Drawing
bool HasFilters { get; }
EditStatus Status { get; set; }
void Invalidate();
bool ClickableAt(int x, int y);
void MoveBy(int x, int y);
void Transform(Matrix matrix);
bool HandleMouseDown(int x, int y);
void HandleMouseUp(int x, int y);
bool HandleMouseMove(int x, int y);
bool InitContent();
void MakeBoundsChangeUndoable(bool allowMerge);
EditStatus DefaultEditMode { get; }
/// <summary>

View file

@ -89,8 +89,8 @@ namespace Greenshot.Base.Interfaces
/// <param name="stream">Stream</param>
/// <param name="extension">string</param>
/// <param name="drawableContainer">IDrawableContainer out</param>
/// <param name="parent">ISurface</param>
/// <param name="parentSurface">ISurface</param>
/// <returns>bool true if it was successful</returns>
public bool TryLoadDrawableFromStream(Stream stream, string extension, out IDrawableContainer drawableContainer, ISurface parent);
public bool TryLoadDrawableFromStream(Stream stream, string extension, out IDrawableContainer drawableContainer, ISurface parentSurface = null);
}
}

View file

@ -61,6 +61,11 @@ namespace Greenshot.Editor.Drawing
Load(filename);
}
public IconContainer(ISurface parent, Stream stream) : base(parent)
{
Load(stream);
}
public Icon Icon
{
set
@ -100,6 +105,18 @@ namespace Greenshot.Editor.Drawing
Log.Debug("Loaded file: " + filename + " with resolution: " + Height + "," + Width);
}
public void Load(Stream iconStream)
{
if (iconStream == null)
{
return;
}
using Icon fileIcon = new Icon(iconStream);
Icon = fileIcon;
Log.Debug("Loaded stream: with resolution: " + Height + "," + Width);
}
public override void Draw(Graphics graphics, RenderMode rm)
{
if (icon == null)

View file

@ -0,0 +1,71 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: https://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using Greenshot.Base.Core;
using Greenshot.Base.Interfaces;
using Svg;
namespace Greenshot.Editor.Drawing
{
/// <summary>
/// This provides a resizable SVG container, redrawing the SVG in the size the container takes.
/// </summary>
[Serializable]
public class MetafileContainer : VectorGraphicsContainer
{
private readonly Metafile _metafile;
public MetafileContainer(Metafile metafile, ISurface parent) : base(parent)
{
_metafile = metafile;
Size = new Size(metafile.Width/4, metafile.Height/4);
}
protected override Image ComputeBitmap()
{
var image = ImageHelper.CreateEmpty(Width, Height, PixelFormat.Format32bppArgb, Color.Transparent);
var dstRect = new Rectangle(0, 0, Width, Height);
using (Graphics graphics = Graphics.FromImage(image))
{
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphics.DrawImage(_metafile, dstRect);
}
if (RotationAngle == 0) return image;
var newImage = image.Rotate(RotationAngle);
image.Dispose();
return newImage;
}
public override bool HasDefaultSize => true;
public override Size DefaultSize => new Size(_metafile.Width, _metafile.Height);
}
}

View file

@ -49,7 +49,6 @@ namespace Greenshot.Editor.Drawing
public sealed class Surface : Control, ISurface, INotifyPropertyChanged
{
private static readonly ILog LOG = LogManager.GetLogger(typeof(Surface));
public static int Count;
private static readonly CoreConfiguration conf = IniConfig.GetIniSection<CoreConfiguration>();
// Property to identify the Surface ID
@ -207,7 +206,7 @@ namespace Greenshot.Editor.Drawing
[NonSerialized] private IDrawableContainer _undrawnElement;
/// <summary>
/// the cropcontainer, when cropping this is set, do not serialize
/// the crop container, when cropping this is set, do not serialize
/// </summary>
[NonSerialized] private IDrawableContainer _cropContainer;
@ -467,7 +466,6 @@ namespace Greenshot.Editor.Drawing
public Surface()
{
_fieldAggregator = new FieldAggregator(this);
Count++;
_elements = new DrawableContainerList(_uniqueId);
selectedElements = new DrawableContainerList(_uniqueId);
LOG.Debug("Creating surface!");
@ -550,7 +548,6 @@ namespace Greenshot.Editor.Drawing
{
if (disposing)
{
Count--;
LOG.Debug("Disposing surface!");
if (_buffer != null)
{
@ -927,20 +924,23 @@ namespace Greenshot.Editor.Drawing
// Test if it's an url and try to download the image so we have it in the original form
if (possibleUrl != null && possibleUrl.StartsWith("http"))
{
using Image image = NetworkHelper.DownloadImage(possibleUrl);
if (image != null)
var drawableContainer = NetworkHelper.DownloadImageAsDrawableContainer(possibleUrl);
if (drawableContainer != null)
{
AddImageContainer(image, mouse.X, mouse.Y);
drawableContainer.Left = Location.X;
drawableContainer.Top = Location.Y;
AddElement(drawableContainer);
return;
}
}
}
foreach (Image image in ClipboardHelper.GetImages(e.Data))
foreach (var drawableContainer in ClipboardHelper.GetImages(e.Data))
{
AddImageContainer(image, mouse.X, mouse.Y);
drawableContainer.Left = mouse.X;
drawableContainer.Top = mouse.Y;
AddElement(drawableContainer);
mouse.Offset(10, 10);
image.Dispose();
}
}
@ -2057,17 +2057,15 @@ namespace Greenshot.Editor.Drawing
{
Point pasteLocation = GetPasteLocation(0.1f, 0.1f);
foreach (Image clipboardImage in ClipboardHelper.GetImages(clipboard))
foreach (var drawableContainer in ClipboardHelper.GetImages(clipboard))
{
if (clipboardImage != null)
{
DeselectAllElements();
IImageContainer container = AddImageContainer(clipboardImage as Bitmap, pasteLocation.X, pasteLocation.Y);
SelectElement(container);
clipboardImage.Dispose();
pasteLocation.X += 10;
pasteLocation.Y += 10;
}
if (drawableContainer == null) continue;
DeselectAllElements();
drawableContainer.Left = pasteLocation.X;
drawableContainer.Top = pasteLocation.Y;
SelectElement(drawableContainer);
pasteLocation.X += 10;
pasteLocation.Y += 10;
}
}
else if (ClipboardHelper.ContainsText(clipboard))

View file

@ -21,7 +21,6 @@
using System;
using System.Drawing;
using System.Drawing.Imaging;
using Greenshot.Base.Core;
using Greenshot.Base.Interfaces;
using Svg;
@ -44,14 +43,19 @@ namespace Greenshot.Editor.Drawing
protected override Image ComputeBitmap()
{
var image = ImageHelper.CreateEmpty(Width, Height, PixelFormat.Format32bppRgb, Color.Transparent);
//var image = ImageHelper.CreateEmpty(Width, Height, PixelFormat.Format32bppArgb, Color.Transparent);
_svgDocument.Draw(image);
var image = _svgDocument.Draw(Width, Height);
if (RotationAngle == 0) return image;
var newImage = image.Rotate(RotationAngle);
image.Dispose();
return newImage;
}
public override bool HasDefaultSize => true;
public override Size DefaultSize => new Size((int)_svgDocument.Width, (int)_svgDocument.Height);
}
}

View file

@ -22,9 +22,7 @@
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Runtime.Serialization;
using Greenshot.Base.Core;
using Greenshot.Base.Interfaces;
using Greenshot.Base.Interfaces.Drawing;
@ -78,6 +76,7 @@ namespace Greenshot.Editor.Drawing
base.Dispose(disposing);
}
/// <inheritdoc cref="IDrawableContainer"/>
public override void Transform(Matrix matrix)
{
RotationAngle += CalculateAngle(matrix);
@ -88,34 +87,26 @@ namespace Greenshot.Editor.Drawing
base.Transform(matrix);
}
/// <inheritdoc cref="IDrawableContainer"/>
public override void Draw(Graphics graphics, RenderMode rm)
{
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
if (_cachedImage != null && _cachedImage.Size != Bounds.Size)
{
ResetCachedBitmap();
}
_cachedImage ??= ComputeBitmap();
_cachedImage ??= ComputeBitmap();
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphics.DrawImage(_cachedImage, Bounds);
}
protected virtual Image ComputeBitmap()
{
var image = ImageHelper.CreateEmpty(Width, Height, PixelFormat.Format32bppRgb, Color.Transparent);
if (RotationAngle == 0) return image;
var newImage = image.Rotate(RotationAngle);
image.Dispose();
return newImage;
}
protected abstract Image ComputeBitmap();
private void ResetCachedBitmap()
{

View file

@ -29,6 +29,11 @@ namespace Greenshot.Editor
public static void Initialize()
{
FileFormatHandlerRegistry.FileFormatHandlers.Add(new SvgFileFormatHandler());
FileFormatHandlerRegistry.FileFormatHandlers.Add(new DefaultFileFormatHandler());
FileFormatHandlerRegistry.FileFormatHandlers.Add(new DibFileFormatHandler());
FileFormatHandlerRegistry.FileFormatHandlers.Add(new GreenshotFileFormatHandler());
FileFormatHandlerRegistry.FileFormatHandlers.Add(new IconFileFormatHandler());
FileFormatHandlerRegistry.FileFormatHandlers.Add(new MetaFileFormatHandler());
}
}
}

View file

@ -19,44 +19,36 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using Greenshot.Base.Core;
using Greenshot.Base.Core.FileFormatHandlers;
using Greenshot.Base.Interfaces;
using Greenshot.Base.Interfaces.Drawing;
using Greenshot.Editor.Drawing;
namespace Greenshot.Base.Core.FileFormatHandlers
namespace Greenshot.Editor.FileFormatHandlers
{
/// <summary>
/// This is the default .NET bitmap file format handler
/// </summary>
public class DefaultFileFormatHandler : IFileFormatHandler
public class DefaultFileFormatHandler : AbstractFileFormatHandler, IFileFormatHandler
{
private static readonly string [] OurExtensions = { "png", "bmp", "gif", "jpg", "jpeg", "tiff", "tif" };
private static readonly string [] OurExtensions = { ".png", ".bmp", ".gif", ".jpg", ".jpeg", ".tiff", ".tif" };
/// <inheritdoc />
public IEnumerable<string> SupportedExtensions(FileFormatHandlerActions fileFormatHandlerAction)
{
if (fileFormatHandlerAction == FileFormatHandlerActions.LoadDrawableFromStream)
{
return Enumerable.Empty<string>();
}
return OurExtensions;
}
/// <inheritdoc />
public bool Supports(FileFormatHandlerActions fileFormatHandlerAction, string extension)
{
if (fileFormatHandlerAction == FileFormatHandlerActions.LoadDrawableFromStream)
{
return false;
}
return OurExtensions.Contains(extension?.ToLowerInvariant());
return OurExtensions.Contains(NormalizeExtension(extension));
}
/// <inheritdoc />
@ -68,15 +60,15 @@ namespace Greenshot.Base.Core.FileFormatHandlers
/// <inheritdoc />
public bool TrySaveToStream(Bitmap bitmap, Stream destination, string extension)
{
ImageFormat imageFormat = extension?.ToLowerInvariant() switch
ImageFormat imageFormat = NormalizeExtension(extension) switch
{
"png" => ImageFormat.Png,
"bmp" => ImageFormat.Bmp,
"gif" => ImageFormat.Gif,
"jpg" => ImageFormat.Jpeg,
"jpeg" => ImageFormat.Jpeg,
"tiff" => ImageFormat.Tiff,
"tif" => ImageFormat.Tiff,
".png" => ImageFormat.Png,
".bmp" => ImageFormat.Bmp,
".gif" => ImageFormat.Gif,
".jpg" => ImageFormat.Jpeg,
".jpeg" => ImageFormat.Jpeg,
".tiff" => ImageFormat.Tiff,
".tif" => ImageFormat.Tiff,
_ => null
};
@ -97,9 +89,20 @@ namespace Greenshot.Base.Core.FileFormatHandlers
}
/// <inheritdoc />
public bool TryLoadDrawableFromStream(Stream stream, string extension, out IDrawableContainer drawableContainer, ISurface surface)
public bool TryLoadDrawableFromStream(Stream stream, string extension, out IDrawableContainer drawableContainer, ISurface surface = null)
{
throw new NotImplementedException();
if (TryLoadFromStream(stream, extension, out var bitmap))
{
var imageContainer = new ImageContainer(surface)
{
Image = bitmap
};
drawableContainer = imageContainer;
return true;
}
drawableContainer = null;
return true;
}
}
}

View file

@ -26,40 +26,36 @@ using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using Greenshot.Base.Core;
using Greenshot.Base.Core.FileFormatHandlers;
using Greenshot.Base.Interfaces;
using Greenshot.Base.Interfaces.Drawing;
using Greenshot.Base.UnmanagedHelpers;
using Greenshot.Editor.Drawing;
using log4net;
namespace Greenshot.Base.Core.FileFormatHandlers
namespace Greenshot.Editor.FileFormatHandlers
{
/// <summary>
/// This handles creating a DIB (Device Independent Bitmap) on the clipboard
/// </summary>
public class DibFileFormatHandler : IFileFormatHandler
public class DibFileFormatHandler : AbstractFileFormatHandler, IFileFormatHandler
{
private const double DpiToPelsPerMeter = 39.3701;
private static readonly string [] OurExtensions = { "dib" };
private static readonly ILog Log = LogManager.GetLogger(typeof(DibFileFormatHandler));
private static readonly string [] OurExtensions = { ".dib", ".format17" };
/// <inheritdoc />
public IEnumerable<string> SupportedExtensions(FileFormatHandlerActions fileFormatHandlerAction)
{
if (fileFormatHandlerAction == FileFormatHandlerActions.LoadDrawableFromStream)
{
return Enumerable.Empty<string>();
}
return OurExtensions;
}
/// <inheritdoc />
public bool Supports(FileFormatHandlerActions fileFormatHandlerAction, string extension)
{
if (string.IsNullOrEmpty(extension) || fileFormatHandlerAction != FileFormatHandlerActions.SaveToStream)
{
return false;
}
return OurExtensions.Contains(extension.ToLowerInvariant());
extension = NormalizeExtension(extension);
return OurExtensions.Contains(extension);
}
/// <inheritdoc />
@ -79,13 +75,79 @@ namespace Greenshot.Base.Core.FileFormatHandlers
/// <inheritdoc />
public bool TryLoadFromStream(Stream stream, string extension, out Bitmap bitmap)
{
throw new NotImplementedException();
byte[] dibBuffer = new byte[stream.Length];
_ = stream.Read(dibBuffer, 0, dibBuffer.Length);
var infoHeader = BinaryStructHelper.FromByteArray<BITMAPINFOHEADERV5>(dibBuffer);
if (!infoHeader.IsDibV5)
{
Log.InfoFormat("Using special DIB <v5 format reader with biCompression {0}", infoHeader.biCompression);
int fileHeaderSize = Marshal.SizeOf(typeof(BITMAPFILEHEADER));
uint infoHeaderSize = infoHeader.biSize;
int fileSize = (int)(fileHeaderSize + infoHeader.biSize + infoHeader.biSizeImage);
var fileHeader = new BITMAPFILEHEADER
{
bfType = BITMAPFILEHEADER.BM,
bfSize = fileSize,
bfReserved1 = 0,
bfReserved2 = 0,
bfOffBits = (int)(fileHeaderSize + infoHeaderSize + infoHeader.biClrUsed * 4)
};
byte[] fileHeaderBytes = BinaryStructHelper.ToByteArray(fileHeader);
using var bitmapStream = new MemoryStream();
bitmapStream.Write(fileHeaderBytes, 0, fileHeaderSize);
bitmapStream.Write(dibBuffer, 0, dibBuffer.Length);
bitmapStream.Seek(0, SeekOrigin.Begin);
bitmap = ImageHelper.FromStream(bitmapStream) as Bitmap;
return true;
}
Log.Info("Using special DIBV5 / Format17 format reader");
// CF_DIBV5
IntPtr gcHandle = IntPtr.Zero;
try
{
GCHandle handle = GCHandle.Alloc(dibBuffer, GCHandleType.Pinned);
gcHandle = GCHandle.ToIntPtr(handle);
bitmap = new Bitmap(infoHeader.biWidth, infoHeader.biHeight,
-(int)(infoHeader.biSizeImage / infoHeader.biHeight),
infoHeader.biBitCount == 32 ? PixelFormat.Format32bppArgb : PixelFormat.Format24bppRgb,
new IntPtr(handle.AddrOfPinnedObject().ToInt32() + infoHeader.OffsetToPixels +
(infoHeader.biHeight - 1) * (int)(infoHeader.biSizeImage / infoHeader.biHeight))
);
}
catch (Exception ex)
{
Log.Error("Problem retrieving Format17 from clipboard.", ex);
bitmap = null;
}
finally
{
if (gcHandle == IntPtr.Zero)
{
GCHandle.FromIntPtr(gcHandle).Free();
}
}
return true;
}
/// <inheritdoc />
public bool TryLoadDrawableFromStream(Stream stream, string extension, out IDrawableContainer drawableContainer, ISurface surface)
public bool TryLoadDrawableFromStream(Stream stream, string extension, out IDrawableContainer drawableContainer, ISurface surface = null)
{
throw new NotImplementedException();
if (TryLoadFromStream(stream, extension, out var bitmap))
{
var imageContainer = new ImageContainer(surface)
{
Image = bitmap
};
drawableContainer = imageContainer;
return true;
}
drawableContainer = null;
return true;
}

View file

@ -24,14 +24,16 @@ using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using Greenshot.Base.Core;
using Greenshot.Base.Core.FileFormatHandlers;
using Greenshot.Base.Interfaces;
using Greenshot.Base.Interfaces.Drawing;
namespace Greenshot.Base.Core.FileFormatHandlers
namespace Greenshot.Editor.FileFormatHandlers
{
public class GreenshotFileFormatHandler : IFileFormatHandler
public class GreenshotFileFormatHandler : AbstractFileFormatHandler, IFileFormatHandler
{
private static readonly string[] OurExtensions = { "greenshot" };
private static readonly string[] OurExtensions = { ".greenshot" };
/// <inheritdoc />
public IEnumerable<string> SupportedExtensions(FileFormatHandlerActions fileFormatHandlerAction)
@ -51,8 +53,12 @@ namespace Greenshot.Base.Core.FileFormatHandlers
{
return false;
}
if (fileFormatHandlerAction == FileFormatHandlerActions.SaveToStream)
{
return false;
}
return OurExtensions.Contains(extension?.ToLowerInvariant());
return OurExtensions.Contains(NormalizeExtension(extension));
}
@ -75,7 +81,7 @@ namespace Greenshot.Base.Core.FileFormatHandlers
return true;
}
public bool TryLoadDrawableFromStream(Stream stream, string extension, out IDrawableContainer drawableContainer, ISurface parent)
public bool TryLoadDrawableFromStream(Stream stream, string extension, out IDrawableContainer drawableContainer, ISurface parent = null)
{
throw new NotImplementedException();
}

View file

@ -25,25 +25,28 @@ using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using Greenshot.Base.Core;
using Greenshot.Base.Core.FileFormatHandlers;
using Greenshot.Base.Interfaces;
using Greenshot.Base.Interfaces.Drawing;
using Greenshot.Editor.Drawing;
using log4net;
namespace Greenshot.Base.Core.FileFormatHandlers
namespace Greenshot.Editor.FileFormatHandlers
{
/// <summary>
/// THis is the default .NET bitmap file format handler
/// </summary>
public class IconFileFormatHandler : IFileFormatHandler
public class IconFileFormatHandler : AbstractFileFormatHandler, IFileFormatHandler
{
private static readonly ILog Log = LogManager.GetLogger(typeof(ImageHelper));
private static readonly string[] OurExtensions = { "ico" };
private static readonly string[] OurExtensions = { ".ico" };
/// <inheritdoc />
public IEnumerable<string> SupportedExtensions(FileFormatHandlerActions fileFormatHandlerAction)
{
if (fileFormatHandlerAction == FileFormatHandlerActions.LoadDrawableFromStream)
if (fileFormatHandlerAction == FileFormatHandlerActions.SaveToStream)
{
return Enumerable.Empty<string>();
}
@ -54,12 +57,12 @@ namespace Greenshot.Base.Core.FileFormatHandlers
/// <inheritdoc />
public bool Supports(FileFormatHandlerActions fileFormatHandlerAction, string extension)
{
if (fileFormatHandlerAction == FileFormatHandlerActions.LoadDrawableFromStream)
if (fileFormatHandlerAction == FileFormatHandlerActions.SaveToStream)
{
return false;
}
return OurExtensions.Contains(extension?.ToLowerInvariant());
return OurExtensions.Contains(NormalizeExtension(extension));
}
/// <inheritdoc />
@ -76,7 +79,7 @@ namespace Greenshot.Base.Core.FileFormatHandlers
public bool TryLoadFromStream(Stream stream, string extension, out Bitmap bitmap)
{
var startingPosition = stream.Seek(0, SeekOrigin.Current);
_ = stream.Seek(0, SeekOrigin.Current);
// Icon logic, try to get the Vista icon, else the biggest possible
try
@ -113,10 +116,20 @@ namespace Greenshot.Base.Core.FileFormatHandlers
}
public bool TryLoadDrawableFromStream(Stream stream, string extension, out IDrawableContainer drawableContainer, ISurface parent)
public bool TryLoadDrawableFromStream(Stream stream, string extension, out IDrawableContainer drawableContainer, ISurface surface = null)
{
// TODO: Implement this
throw new NotImplementedException();
if (TryLoadFromStream(stream, extension, out var bitmap))
{
var imageContainer = new ImageContainer(surface)
{
Image = bitmap
};
drawableContainer = imageContainer;
return true;
}
drawableContainer = null;
return true;
}
/// <summary>

View file

@ -0,0 +1,108 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: https://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using Greenshot.Base.Core;
using Greenshot.Base.Core.FileFormatHandlers;
using Greenshot.Base.Interfaces;
using Greenshot.Base.Interfaces.Drawing;
using Greenshot.Editor.Drawing;
namespace Greenshot.Editor.FileFormatHandlers
{
/// <summary>
/// This handles the Windows metafile files
/// </summary>
public class MetaFileFormatHandler : AbstractFileFormatHandler, IFileFormatHandler
{
private static readonly string [] OurExtensions = { ".wmf", ".emf" };
/// <inheritdoc />
public IEnumerable<string> SupportedExtensions(FileFormatHandlerActions fileFormatHandlerAction)
{
if (fileFormatHandlerAction == FileFormatHandlerActions.SaveToStream)
{
return Enumerable.Empty<string>();
}
return OurExtensions;
}
/// <inheritdoc />
public bool Supports(FileFormatHandlerActions fileFormatHandlerAction, string extension)
{
if (fileFormatHandlerAction == FileFormatHandlerActions.SaveToStream)
{
return false;
}
return OurExtensions.Contains(NormalizeExtension(extension));
}
/// <inheritdoc />
public int PriorityFor(FileFormatHandlerActions fileFormatHandlerAction, string extension)
{
return int.MaxValue;
}
/// <inheritdoc />
public bool TrySaveToStream(Bitmap bitmap, Stream destination, string extension)
{
return false;
}
/// <inheritdoc />
public bool TryLoadFromStream(Stream stream, string extension, out Bitmap bitmap)
{
try
{
if (Image.FromStream(stream, true, true) is Metafile metaFile)
{
bitmap = ImageHelper.Clone(metaFile, PixelFormat.Format32bppArgb);
return true;
}
}
catch
{
// Ignore
}
bitmap = null;
return false;
}
/// <inheritdoc />
public bool TryLoadDrawableFromStream(Stream stream, string extension, out IDrawableContainer drawableContainer, ISurface surface = null)
{
if (Image.FromStream(stream, true, true) is Metafile metaFile)
{
drawableContainer = new MetafileContainer(metaFile, surface);
return true;
}
drawableContainer = null;
return false;
}
}
}

View file

@ -27,7 +27,7 @@ using System.Linq;
using Greenshot.Base.Interfaces;
using Greenshot.Base.Interfaces.Drawing;
namespace Greenshot.Base.Core.FileFormatHandlers
namespace Greenshot.Editor.FileFormatHandlers
{
/// <summary>
/// This can be an ImageSharp implementation

View file

@ -26,6 +26,7 @@ using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using Greenshot.Base.Core;
using Greenshot.Base.Core.FileFormatHandlers;
using Greenshot.Base.Interfaces;
using Greenshot.Base.Interfaces.Drawing;
using Greenshot.Editor.Drawing;
@ -37,15 +38,15 @@ namespace Greenshot.Editor.FileFormatHandlers
/// <summary>
/// This handled the loading of SVG images to the editor
/// </summary>
public class SvgFileFormatHandler : IFileFormatHandler
public class SvgFileFormatHandler : AbstractFileFormatHandler, IFileFormatHandler
{
private static readonly ILog Log = LogManager.GetLogger(typeof(ImageHelper));
private static readonly string[] OurExtensions = { "svg" };
private static readonly ILog Log = LogManager.GetLogger(typeof(SvgFileFormatHandler));
private static readonly string[] OurExtensions = { ".svg" };
/// <inheritdoc />
public IEnumerable<string> SupportedExtensions(FileFormatHandlerActions fileFormatHandlerAction)
{
if (fileFormatHandlerAction == FileFormatHandlerActions.LoadDrawableFromStream)
if (fileFormatHandlerAction == FileFormatHandlerActions.SaveToStream)
{
return Enumerable.Empty<string>();
}
@ -56,12 +57,12 @@ namespace Greenshot.Editor.FileFormatHandlers
/// <inheritdoc />
public bool Supports(FileFormatHandlerActions fileFormatHandlerAction, string extension)
{
if (fileFormatHandlerAction == FileFormatHandlerActions.LoadDrawableFromStream)
if (fileFormatHandlerAction == FileFormatHandlerActions.SaveToStream)
{
return false;
}
return OurExtensions.Contains(extension);
return OurExtensions.Contains(NormalizeExtension(extension));
}
/// <inheritdoc />
public int PriorityFor(FileFormatHandlerActions fileFormatHandlerAction, string extension)
@ -96,9 +97,14 @@ namespace Greenshot.Editor.FileFormatHandlers
return false;
}
public bool TryLoadDrawableFromStream(Stream stream, string extension, out IDrawableContainer drawableContainer, ISurface parent)
public bool TryLoadDrawableFromStream(Stream stream, string extension, out IDrawableContainer drawableContainer, ISurface parent = null)
{
var svgDocument = SvgDocument.Open<SvgDocument>(stream);
if (svgDocument == null)
{
drawableContainer = null;
return false;
}
drawableContainer = new SvgContainer(svgDocument, parent);
return true;
}

View file

@ -1,4 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<None Include="Languages\language*.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>

View file

@ -389,6 +389,7 @@ namespace Greenshot.Helpers
HandleCapture();
break;
case CaptureMode.Clipboard:
// TODO: Fix getting image vs. drawablecontainer
Image clipboardImage = ClipboardHelper.GetImage();
if (clipboardImage != null)
{