diff --git a/Greenshot.ImageEditor/Configuration/CoreConfiguration.cs b/Greenshot.ImageEditor/Configuration/CoreConfiguration.cs deleted file mode 100644 index 1ee896ea4..000000000 --- a/Greenshot.ImageEditor/Configuration/CoreConfiguration.cs +++ /dev/null @@ -1,597 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.IniFile; -using Greenshot.Plugin; -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Drawing; -using System.IO; -using System.Reflection; -using System.Windows.Forms; - -namespace GreenshotPlugin.Core -{ - public enum ClipboardFormat - { - PNG, DIB, HTML, HTMLDATAURL, BITMAP, DIBV5 - } - public enum OutputFormat - { - bmp, gif, jpg, png, tiff, greenshot - } - public enum WindowCaptureMode - { - Screen, GDI, Aero, AeroTransparent, Auto - } - - public enum BuildStates - { - UNSTABLE, - RELEASE_CANDIDATE, - RELEASE - } - - public enum ClickActions - { - DO_NOTHING, - OPEN_LAST_IN_EXPLORER, - OPEN_LAST_IN_EDITOR, - OPEN_SETTINGS, - SHOW_CONTEXT_MENU - } - - /// - /// Description of CoreConfiguration. - /// - [IniSection("Core", Description = "Greenshot core configuration")] - public class CoreConfiguration : IniSection, INotifyPropertyChanged - { - public event PropertyChangedEventHandler PropertyChanged; - - [IniProperty("Language", Description = "The language in IETF format (e.g. en-US)")] - public string Language; - - [IniProperty("RegionHotkey", Description = "Hotkey for starting the region capture", DefaultValue = "PrintScreen")] - public string RegionHotkey; - [IniProperty("WindowHotkey", Description = "Hotkey for starting the window capture", DefaultValue = "Alt + PrintScreen")] - public string WindowHotkey; - [IniProperty("FullscreenHotkey", Description = "Hotkey for starting the fullscreen capture", DefaultValue = "Ctrl + PrintScreen")] - public string FullscreenHotkey; - [IniProperty("LastregionHotkey", Description = "Hotkey for starting the last region capture", DefaultValue = "Shift + PrintScreen")] - public string LastregionHotkey; - [IniProperty("IEHotkey", Description = "Hotkey for starting the IE capture", DefaultValue = "Shift + Ctrl + PrintScreen")] - public string IEHotkey; - - [IniProperty("IsFirstLaunch", Description = "Is this the first time launch?", DefaultValue = "true")] - public bool IsFirstLaunch; - [IniProperty("Destinations", Separator = ",", Description = "Which destinations? Possible options (more might be added by plugins) are: Editor, FileDefault, FileWithDialog, Clipboard, Printer, EMail, Picker", DefaultValue = "Picker")] - public List OutputDestinations = new List(); - [IniProperty("ClipboardFormats", Separator = ",", Description = "Specify which formats we copy on the clipboard? Options are: PNG, HTML, HTMLDATAURL and DIB", DefaultValue = "PNG,DIB")] - public List ClipboardFormats = new List(); - - [IniProperty("CaptureMousepointer", Description = "Should the mouse be captured?", DefaultValue = "true")] - public bool CaptureMousepointer; - [IniProperty("CaptureWindowsInteractive", Description = "Use interactive window selection to capture? (false=Capture active window)", DefaultValue = "false")] - public bool CaptureWindowsInteractive; - [IniProperty("CaptureDelay", Description = "Capture delay in millseconds.", DefaultValue = "100")] - public int CaptureDelay; - [IniProperty("ScreenCaptureMode", Description = "The capture mode used to capture a screen. (Auto, FullScreen, Fixed)", DefaultValue = "Auto")] - public ScreenCaptureMode ScreenCaptureMode; - [IniProperty("ScreenToCapture", Description = "The screen number to capture when using ScreenCaptureMode Fixed.", DefaultValue = "1")] - public int ScreenToCapture; - [IniProperty("WindowCaptureMode", Description = "The capture mode used to capture a Window (Screen, GDI, Aero, AeroTransparent, Auto).", DefaultValue = "Auto")] - public WindowCaptureMode WindowCaptureMode; - [IniProperty("WindowCaptureAllChildLocations", Description = "Enable/disable capture all children, very slow but will make it possible to use this information in the editor.", DefaultValue = "False")] - public bool WindowCaptureAllChildLocations; - - [IniProperty("DWMBackgroundColor", Description = "The background color for a DWM window capture.")] - public Color DWMBackgroundColor; - - [IniProperty("PlayCameraSound", LanguageKey = "settings_playsound", Description = "Play a camera sound after taking a capture.", DefaultValue = "false")] - public bool PlayCameraSound = false; - [IniProperty("ShowTrayNotification", LanguageKey = "settings_shownotify", Description = "Show a notification from the systray when a capture is taken.", DefaultValue = "true")] - public bool ShowTrayNotification = true; - - [IniProperty("OutputFilePath", Description = "Output file path.")] - public string OutputFilePath; - [IniProperty("OutputFileAllowOverwrite", Description = "If the target file already exists True will make Greenshot always overwrite and False will display a 'Save-As' dialog.", DefaultValue = "true")] - public bool OutputFileAllowOverwrite; - [IniProperty("OutputFileFilenamePattern", Description = "Filename pattern for screenshot.", DefaultValue = "${capturetime:d\"yyyy-MM-dd HH_mm_ss\"}-${title}")] - public string OutputFileFilenamePattern; - [IniProperty("OutputFileFormat", Description = "Default file type for writing screenshots. (bmp, gif, jpg, png, tiff)", DefaultValue = "png")] - public OutputFormat OutputFileFormat = OutputFormat.png; - [IniProperty("OutputFileReduceColors", Description = "If set to true, than the colors of the output file are reduced to 256 (8-bit) colors", DefaultValue = "false")] - public bool OutputFileReduceColors; - [IniProperty("OutputFileAutoReduceColors", Description = "If set to true the amount of colors is counted and if smaller than 256 the color reduction is automatically used.", DefaultValue = "false")] - public bool OutputFileAutoReduceColors; - [IniProperty("OutputFileReduceColorsTo", Description = "Amount of colors to reduce to, when reducing", DefaultValue = "256")] - public int OutputFileReduceColorsTo; - - [IniProperty("OutputFileCopyPathToClipboard", Description = "When saving a screenshot, copy the path to the clipboard?", DefaultValue = "true")] - public bool OutputFileCopyPathToClipboard; - [IniProperty("OutputFileAsFullpath", Description = "SaveAs Full path?")] - public string OutputFileAsFullpath; - - [IniProperty("OutputFileJpegQuality", Description = "JPEG file save quality in %.", DefaultValue = "80")] - public int OutputFileJpegQuality; - [IniProperty("OutputFilePromptQuality", Description = "Ask for the quality before saving?", DefaultValue = "false")] - public bool OutputFilePromptQuality; - [IniProperty("OutputFileIncrementingNumber", Description = "The number for the ${NUM} in the filename pattern, is increased automatically after each save.", DefaultValue = "1")] - public uint OutputFileIncrementingNumber; - - [IniProperty("OutputPrintPromptOptions", LanguageKey = "settings_alwaysshowprintoptionsdialog", Description = "Ask for print options when printing?", DefaultValue = "true")] - public bool OutputPrintPromptOptions; - [IniProperty("OutputPrintAllowRotate", LanguageKey = "printoptions_allowrotate", Description = "Allow rotating the picture for fitting on paper?", DefaultValue = "false")] - public bool OutputPrintAllowRotate; - [IniProperty("OutputPrintAllowEnlarge", LanguageKey = "printoptions_allowenlarge", Description = "Allow growing the picture for fitting on paper?", DefaultValue = "false")] - public bool OutputPrintAllowEnlarge; - [IniProperty("OutputPrintAllowShrink", LanguageKey = "printoptions_allowshrink", Description = "Allow shrinking the picture for fitting on paper?", DefaultValue = "true")] - public bool OutputPrintAllowShrink; - [IniProperty("OutputPrintCenter", LanguageKey = "printoptions_allowcenter", Description = "Center image when printing?", DefaultValue = "true")] - public bool OutputPrintCenter; - [IniProperty("OutputPrintInverted", LanguageKey = "printoptions_inverted", Description = "Print image inverted (use e.g. for console captures)", DefaultValue = "false")] - public bool OutputPrintInverted; - [IniProperty("OutputPrintGrayscale", LanguageKey = "printoptions_printgrayscale", Description = "Force grayscale printing", DefaultValue = "false")] - public bool OutputPrintGrayscale; - [IniProperty("OutputPrintMonochrome", LanguageKey = "printoptions_printmonochrome", Description = "Force monorchrome printing", DefaultValue = "false")] - public bool OutputPrintMonochrome; - [IniProperty("OutputPrintMonochromeThreshold", Description = "Threshold for monochrome filter (0 - 255), lower value means less black", DefaultValue = "127")] - public byte OutputPrintMonochromeThreshold; - [IniProperty("OutputPrintFooter", LanguageKey = "printoptions_timestamp", Description = "Print footer on print?", DefaultValue = "true")] - public bool OutputPrintFooter; - [IniProperty("OutputPrintFooterPattern", Description = "Footer pattern", DefaultValue = "${capturetime:d\"D\"} ${capturetime:d\"T\"} - ${title}")] - public string OutputPrintFooterPattern; - [IniProperty("NotificationSound", Description = "The wav-file to play when a capture is taken, loaded only once at the Greenshot startup", DefaultValue = "default")] - public string NotificationSound; - [IniProperty("UseProxy", Description = "Use your global proxy?", DefaultValue = "True")] - public bool UseProxy; - [IniProperty("IECapture", Description = "Enable/disable IE capture", DefaultValue = "True")] - public bool IECapture; - [IniProperty("IEFieldCapture", Description = "Enable/disable IE field capture, very slow but will make it possible to annotate the fields of a capture in the editor.", DefaultValue = "False")] - public bool IEFieldCapture; - [IniProperty("WindowClassesToCheckForIE", Description = "Comma separated list of Window-Classes which need to be checked for a IE instance!", DefaultValue = "AfxFrameOrView70,IMWindowClass")] - public List WindowClassesToCheckForIE; - [IniProperty("AutoCropDifference", Description = "Sets how to compare the colors for the autocrop detection, the higher the more is 'selected'. Possible values are from 0 to 255, where everything above ~150 doesn't make much sense!", DefaultValue = "10")] - public int AutoCropDifference; - - [IniProperty("IncludePlugins", Description = "Comma separated list of Plugins which are allowed. If something in the list, than every plugin not in the list will not be loaded!")] - public List IncludePlugins; - [IniProperty("ExcludePlugins", Description = "Comma separated list of Plugins which are NOT allowed.")] - public List ExcludePlugins; - [IniProperty("ExcludeDestinations", Description = "Comma separated list of destinations which should be disabled.")] - public List ExcludeDestinations; - - [IniProperty("UpdateCheckInterval", Description = "How many days between every update check? (0=no checks)", DefaultValue = "1")] - public int UpdateCheckInterval; - [IniProperty("LastUpdateCheck", Description = "Last update check")] - public DateTime LastUpdateCheck; - - [IniProperty("DisableSettings", Description = "Enable/disable the access to the settings, can only be changed manually in this .ini", DefaultValue = "False")] - public bool DisableSettings; - [IniProperty("DisableQuickSettings", Description = "Enable/disable the access to the quick settings, can only be changed manually in this .ini", DefaultValue = "False")] - public bool DisableQuickSettings; - [IniProperty("DisableTrayicon", Description = "Disable the trayicon, can only be changed manually in this .ini", DefaultValue = "False")] - public bool HideTrayicon; - [IniProperty("HideExpertSettings", Description = "Hide expert tab in the settings, can only be changed manually in this .ini", DefaultValue = "False")] - public bool HideExpertSettings; - - [IniProperty("ThumnailPreview", Description = "Enable/disable thumbnail previews", DefaultValue = "True")] - public bool ThumnailPreview; - - [IniProperty("NoGDICaptureForProduct", Description = "List of productnames for which GDI capturing is skipped (using fallback).", DefaultValue = "IntelliJ IDEA")] - public List NoGDICaptureForProduct; - [IniProperty("NoDWMCaptureForProduct", Description = "List of productnames for which DWM capturing is skipped (using fallback).", DefaultValue = "Citrix ICA Client")] - public List NoDWMCaptureForProduct; - - [IniProperty("OptimizeForRDP", Description = "Make some optimizations for usage with remote desktop", DefaultValue = "False")] - public bool OptimizeForRDP; - [IniProperty("DisableRDPOptimizing", Description = "Disable all optimizations for usage with remote desktop", DefaultValue = "False")] - public bool DisableRDPOptimizing; - - [IniProperty("MinimizeWorkingSetSize", Description = "Optimize memory footprint, but with a performance penalty!", DefaultValue = "False")] - public bool MinimizeWorkingSetSize; - - [IniProperty("WindowCaptureRemoveCorners", Description = "Remove the corners from a window capture", DefaultValue = "True")] - public bool WindowCaptureRemoveCorners; - - [IniProperty("CheckForUnstable", Description = "Also check for unstable version updates", DefaultValue = "False")] - public bool CheckForUnstable; - - [IniProperty("ActiveTitleFixes", Description = "The fixes that are active.")] - public List ActiveTitleFixes; - - [IniProperty("TitleFixMatcher", Description = "The regular expressions to match the title with.")] - public Dictionary TitleFixMatcher; - - [IniProperty("TitleFixReplacer", Description = "The replacements for the matchers.")] - public Dictionary TitleFixReplacer; - - [IniProperty("ExperimentalFeatures", Description = "A list of experimental features, this allows us to test certain features before releasing them.", ExcludeIfNull = true)] - public List ExperimentalFeatures; - - [IniProperty("EnableSpecialDIBClipboardReader", Description = "Enable a special DIB clipboard reader", DefaultValue = "True")] - public bool EnableSpecialDIBClipboardReader; - - [IniProperty("WindowCornerCutShape", Description = "The cutshape which is used to remove the window corners, is mirrorred for all corners", DefaultValue = "5,3,2,1,1")] - public List WindowCornerCutShape; - - [IniProperty("LeftClickAction", Description = "Specify what action is made if the tray icon is left clicked, if a double-click action is specified this action is initiated after a delay (configurable via the windows double-click speed)", DefaultValue = "SHOW_CONTEXT_MENU")] - public ClickActions LeftClickAction; - - [IniProperty("DoubleClickAction", Description = "Specify what action is made if the tray icon is double clicked", DefaultValue = "OPEN_LAST_IN_EXPLORER")] - public ClickActions DoubleClickAction; - - [IniProperty("ZoomerEnabled", Description = "Sets if the zoomer is enabled", DefaultValue = "True")] - public bool ZoomerEnabled; - [IniProperty("ZoomerOpacity", Description = "Specify the transparency for the zoomer, from 0-1 (where 1 is no transparency and 0 is complete transparent. An usefull setting would be 0.7)", DefaultValue = "1")] - public float ZoomerOpacity; - - [IniProperty("MaxMenuItemLength", Description = "Maximum length of submenu items in the context menu, making this longer might cause context menu issues on dual screen systems.", DefaultValue = "25")] - public int MaxMenuItemLength; - - [IniProperty("MailApiTo", Description = "The 'to' field for the email destination (settings for Outlook can be found under the Office section)", DefaultValue = "")] - public string MailApiTo; - [IniProperty("MailApiCC", Description = "The 'CC' field for the email destination (settings for Outlook can be found under the Office section)", DefaultValue = "")] - public string MailApiCC; - [IniProperty("MailApiBCC", Description = "The 'BCC' field for the email destination (settings for Outlook can be found under the Office section)", DefaultValue = "")] - public string MailApiBCC; - - [IniProperty("OptimizePNGCommand", Description = "Optional command to execute on a temporary PNG file, the command should overwrite the file and Greenshot will read it back. Note: this command is also executed when uploading PNG's!", DefaultValue = "")] - public string OptimizePNGCommand; - [IniProperty("OptimizePNGCommandArguments", Description = "Arguments for the optional command to execute on a PNG, {0} is replaced by the temp-filename from Greenshot. Note: Temp-file is deleted afterwards by Greenshot.", DefaultValue = "\"{0}\"")] - public string OptimizePNGCommandArguments; - - [IniProperty("LastSaveWithVersion", Description = "Version of Greenshot which created this .ini")] - public string LastSaveWithVersion; - - [IniProperty("ProcessEXIFOrientation", Description = "When reading images from files or clipboard, use the EXIF information to correct the orientation", DefaultValue = "True")] - public bool ProcessEXIFOrientation; - - [IniProperty("LastCapturedRegion", Description = "The last used region, for reuse in the capture last region")] - public Rectangle LastCapturedRegion; - - private Size _iconSize; - [IniProperty("IconSize", Description = "Defines the size of the icons (e.g. for the buttons in the editor), default value 16,16 anything bigger will cause scaling", DefaultValue = "16,16")] - public Size IconSize - { - get - { - return _iconSize; - } - set - { - Size newSize = value; - if (newSize != Size.Empty) - { - if (newSize.Width < 16) - { - newSize.Width = 16; - } - else if (newSize.Width > 256) - { - newSize.Width = 256; - } - newSize.Width = (newSize.Width / 8) * 8; - if (newSize.Height < 16) - { - newSize.Height = 16; - } - else if (IconSize.Height > 256) - { - newSize.Height = 256; - } - newSize.Height = (newSize.Height / 8) * 8; - } - if (_iconSize != newSize) - { - _iconSize = value; - if (PropertyChanged != null) - { - PropertyChanged(this, new PropertyChangedEventArgs("IconSize")); - } - } - } - } - - [IniProperty("WebRequestTimeout", Description = "The connect timeout value for webrequets, these are seconds", DefaultValue = "100")] - public int WebRequestTimeout; - [IniProperty("WebRequestReadWriteTimeout", Description = "The read/write timeout value for webrequets, these are seconds", DefaultValue = "100")] - public int WebRequestReadWriteTimeout; - - /// - /// Specifies what THIS build is - /// - public BuildStates BuildState - { - get - { - string informationalVersion = Application.ProductVersion; - if (informationalVersion != null) - { - if (informationalVersion.ToLowerInvariant().Contains("-rc")) - { - return BuildStates.RELEASE_CANDIDATE; - } - if (informationalVersion.ToLowerInvariant().Contains("-unstable")) - { - return BuildStates.UNSTABLE; - } - } - return BuildStates.RELEASE; - } - } - - public bool UseLargeIcons - { - get - { - return IconSize.Width >= 32 || IconSize.Height >= 32; - } - } - - /// - /// A helper method which returns true if the supplied experimental feature is enabled - /// - /// - /// - public bool isExperimentalFeatureEnabled(string experimentalFeature) - { - return (ExperimentalFeatures != null && ExperimentalFeatures.Contains(experimentalFeature)); - } - - /// - /// Supply values we can't put as defaults - /// - /// The property to return a default for - /// object with the default value for the supplied property - public override object GetDefault(string property) - { - switch (property) - { - case "PluginWhitelist": - case "PluginBacklist": - return new List(); - case "OutputFileAsFullpath": - if (IniConfig.IsPortable) - { - return Path.Combine(Application.StartupPath, @"..\..\Documents\Pictures\Greenshots\dummy.png"); - } - else - { - return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "dummy.png"); - } - case "OutputFilePath": - if (IniConfig.IsPortable) - { - string pafOutputFilePath = Path.Combine(Application.StartupPath, @"..\..\Documents\Pictures\Greenshots"); - if (!Directory.Exists(pafOutputFilePath)) - { - try - { - Directory.CreateDirectory(pafOutputFilePath); - return pafOutputFilePath; - } - catch (Exception ex) - { - LOG.Warn(ex); - // Problem creating directory, fallback to Desktop - } - } - else - { - return pafOutputFilePath; - } - } - return Environment.GetFolderPath(Environment.SpecialFolder.Desktop); - case "DWMBackgroundColor": - return Color.Transparent; - case "ActiveTitleFixes": - List activeDefaults = new List(); - activeDefaults.Add("Firefox"); - activeDefaults.Add("IE"); - activeDefaults.Add("Chrome"); - return activeDefaults; - case "TitleFixMatcher": - Dictionary matcherDefaults = new Dictionary(); - matcherDefaults.Add("Firefox", " - Mozilla Firefox.*"); - matcherDefaults.Add("IE", " - (Microsoft|Windows) Internet Explorer.*"); - matcherDefaults.Add("Chrome", " - Google Chrome.*"); - return matcherDefaults; - case "TitleFixReplacer": - Dictionary replacerDefaults = new Dictionary(); - replacerDefaults.Add("Firefox", ""); - replacerDefaults.Add("IE", ""); - replacerDefaults.Add("Chrome", ""); - return replacerDefaults; - } - return null; - } - - /// - /// This method will be called before converting the property, making to possible to correct a certain value - /// Can be used when migration is needed - /// - /// The name of the property - /// The string value of the property - /// string with the propertyValue, modified or not... - public override string PreCheckValue(string propertyName, string propertyValue) - { - // Changed the separator, now we need to correct this - if ("Destinations".Equals(propertyName)) - { - if (propertyValue != null) - { - return propertyValue.Replace('|', ','); - } - } - if ("OutputFilePath".Equals(propertyName)) - { - if (string.IsNullOrEmpty(propertyValue)) - { - return null; - } - } - return base.PreCheckValue(propertyName, propertyValue); - } - - /// - /// This method will be called before writing the configuration - /// - public override void BeforeSave() - { - try - { - // Store version, this can be used later to fix settings after an update - LastSaveWithVersion = Assembly.GetEntryAssembly().GetName().Version.ToString(); - } - catch - { - } - } - - /// - /// This method will be called after reading the configuration, so eventually some corrections can be made - /// - public override void AfterLoad() - { - // Comment with releases - // CheckForUnstable = true; - - if (string.IsNullOrEmpty(LastSaveWithVersion)) - { - try - { - // Store version, this can be used later to fix settings after an update - LastSaveWithVersion = Assembly.GetEntryAssembly().GetName().Version.ToString(); - } - catch - { - } - // Disable the AutoReduceColors as it causes issues with Mozzila applications and some others - OutputFileAutoReduceColors = false; - } - - // Enable OneNote if upgrading from 1.1 - if (ExcludeDestinations != null && ExcludeDestinations.Contains("OneNote")) - { - if (LastSaveWithVersion != null && LastSaveWithVersion.StartsWith("1.1")) - { - ExcludeDestinations.Remove("OneNote"); - } - else - { - // Remove with the release - ExcludeDestinations.Remove("OneNote"); - } - } - - if (OutputDestinations == null) - { - OutputDestinations = new List(); - } - - // Make sure there is an output! - if (OutputDestinations.Count == 0) - { - OutputDestinations.Add("Editor"); - } - - // Prevent both settings at once, bug #3435056 - if (OutputDestinations.Contains("Clipboard") && OutputFileCopyPathToClipboard) - { - OutputFileCopyPathToClipboard = false; - } - - // Make sure we have clipboard formats, otherwise a paste doesn't make sense! - if (ClipboardFormats == null || ClipboardFormats.Count == 0) - { - ClipboardFormats = new List(); - ClipboardFormats.Add(ClipboardFormat.PNG); - ClipboardFormats.Add(ClipboardFormat.HTML); - ClipboardFormats.Add(ClipboardFormat.DIB); - } - - // Make sure the lists are lowercase, to speedup the check - if (NoGDICaptureForProduct != null) - { - // Fix error in configuration - if (NoGDICaptureForProduct.Count >= 2) - { - if ("intellij".Equals(NoGDICaptureForProduct[0]) && "idea".Equals(NoGDICaptureForProduct[1])) - { - NoGDICaptureForProduct.RemoveRange(0, 2); - NoGDICaptureForProduct.Add("Intellij Idea"); - IsDirty = true; - } - } - for (int i = 0; i < NoGDICaptureForProduct.Count; i++) - { - NoGDICaptureForProduct[i] = NoGDICaptureForProduct[i].ToLower(); - } - } - if (NoDWMCaptureForProduct != null) - { - // Fix error in configuration - if (NoDWMCaptureForProduct.Count >= 3) - { - if ("citrix".Equals(NoDWMCaptureForProduct[0]) && "ica".Equals(NoDWMCaptureForProduct[1]) && "client".Equals(NoDWMCaptureForProduct[2])) - { - NoDWMCaptureForProduct.RemoveRange(0, 3); - NoDWMCaptureForProduct.Add("Citrix ICA Client"); - IsDirty = true; - } - } - for (int i = 0; i < NoDWMCaptureForProduct.Count; i++) - { - NoDWMCaptureForProduct[i] = NoDWMCaptureForProduct[i].ToLower(); - } - } - - if (AutoCropDifference < 0) - { - AutoCropDifference = 0; - } - if (AutoCropDifference > 255) - { - AutoCropDifference = 255; - } - if (OutputFileReduceColorsTo < 2) - { - OutputFileReduceColorsTo = 2; - } - if (OutputFileReduceColorsTo > 256) - { - OutputFileReduceColorsTo = 256; - } - - if (WebRequestTimeout <= 10) - { - WebRequestTimeout = 100; - } - if (WebRequestReadWriteTimeout < 1) - { - WebRequestReadWriteTimeout = 100; - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Configuration/EditorConfiguration.cs b/Greenshot.ImageEditor/Configuration/EditorConfiguration.cs deleted file mode 100644 index 4b7f512d8..000000000 --- a/Greenshot.ImageEditor/Configuration/EditorConfiguration.cs +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Core; -using Greenshot.Drawing.Fields; -using Greenshot.IniFile; -using Greenshot.Plugin; -using GreenshotPlugin.UnmanagedHelpers; -using System; -using System.Collections.Generic; -using System.Drawing; - -namespace Greenshot.Configuration -{ - /// - /// Description of CoreConfiguration. - /// - [IniSection("Editor", Description = "Greenshot editor configuration")] - public class EditorConfiguration : IniSection - { - [IniProperty("RecentColors", Separator = "|", Description = "Last used colors")] - public List RecentColors; - - [IniProperty("DefaultDrawingMode", Separator = "|", Description = "Default drawing mode:None,Rect,Ellipse,Line,Arrow,Path,Text,SpeechBubble,StepLabel,Highlight,Obfuscate,Crop", DefaultValue = "Rect", FixedValue = true)] - public DrawingModes DefaultDrawingMode; - [IniProperty("RememberLastDrawingMode", Description = "Remember last drawing mode used and select it next time", DefaultValue = "False")] - public bool RememberLastDrawingMode; - [IniProperty("LastDrawingMode", Separator = "|", Description = "Last drawing mode used", DefaultValue = "Rect")] - public DrawingModes LastDrawingMode; - - [IniProperty("LastFieldValue", Separator = "|", Description = "Field values, make sure the last used settings are re-used")] - public Dictionary LastUsedFieldValues; - - [IniProperty("MatchSizeToCapture", Description = "Match the editor window size to the capture", DefaultValue = "True")] - public bool MatchSizeToCapture; - [IniProperty("MaximizeWhenLargeImage", Description = "Maximize the editor window when image is larger than the working area", DefaultValue = "False")] - public bool MaximizeWhenLargeImage; - [IniProperty("WindowPlacementFlags", Description = "Placement flags", DefaultValue = "0")] - public WindowPlacementFlags WindowPlacementFlags; - [IniProperty("WindowShowCommand", Description = "Show command", DefaultValue = "Normal")] - public ShowWindowCommand ShowWindowCommand; - [IniProperty("WindowMinPosition", Description = "Position of minimized window", DefaultValue = "-1,-1")] - public Point WindowMinPosition; - [IniProperty("WindowMaxPosition", Description = "Position of maximized window", DefaultValue = "-1,-1")] - public Point WindowMaxPosition; - [IniProperty("WindowNormalPosition", Description = "Position of normal window", DefaultValue = "100,100,400,400")] - public Rectangle WindowNormalPosition; - [IniProperty("ReuseEditor", Description = "Reuse already open editor", DefaultValue = "false")] - public bool ReuseEditor; - [IniProperty("FreehandSensitivity", Description = "The smaller this number, the less smoothing is used. Decrease for detailed drawing, e.g. when using a pen. Increase for smoother lines. e.g. when you want to draw a smooth line.", DefaultValue = "3")] - public int FreehandSensitivity; - [IniProperty("SuppressSaveDialogAtClose", Description = "Suppressed the 'do you want to save' dialog when closing the editor.", DefaultValue = "False")] - public bool SuppressSaveDialogAtClose; - - [IniProperty("DropShadowEffectSettings", Description = "Settings for the drop shadow effect.")] - public DropShadowEffect DropShadowEffectSettings; - - [IniProperty("TornEdgeEffectSettings", Description = "Settings for the torn edge effect.")] - public TornEdgeEffect TornEdgeEffectSettings; - - public override void AfterLoad() - { - base.AfterLoad(); - if (RecentColors == null) - { - RecentColors = new List(); - } - } - - /// Type of the class for which to create the field - /// FieldType of the field to construct - /// FieldType of the field to construct - /// a new Field of the given fieldType, with the scope of it's value being restricted to the Type scope - public Field CreateField(Type requestingType, FieldType fieldType, object preferredDefaultValue) - { - string requestingTypeName = requestingType.Name; - string requestedField = requestingTypeName + "." + fieldType.Name; - object fieldValue = preferredDefaultValue; - - // Check if the configuration exists - if (LastUsedFieldValues == null) - { - LastUsedFieldValues = new Dictionary(); - } - - // Check if settings for the requesting type exist, if not create! - if (LastUsedFieldValues.ContainsKey(requestedField)) - { - // Check if a value is set (not null)! - if (LastUsedFieldValues[requestedField] != null) - { - fieldValue = LastUsedFieldValues[requestedField]; - } - else - { - // Overwrite null value - LastUsedFieldValues[requestedField] = fieldValue; - } - } - else - { - LastUsedFieldValues.Add(requestedField, fieldValue); - } - Field returnField = new Field(fieldType, requestingType); - returnField.Value = fieldValue; - return returnField; - } - - public void UpdateLastFieldValue(Field field) - { - string requestedField = field.Scope + "." + field.FieldType.Name; - // Check if the configuration exists - if (LastUsedFieldValues == null) - { - LastUsedFieldValues = new Dictionary(); - } - // check if settings for the requesting type exist, if not create! - if (LastUsedFieldValues.ContainsKey(requestedField)) - { - LastUsedFieldValues[requestedField] = field.myValue; - } - else - { - LastUsedFieldValues.Add(requestedField, field.myValue); - } - } - - public WindowPlacement GetEditorPlacement() - { - WindowPlacement placement = WindowPlacement.Default; - placement.NormalPosition = new RECT(WindowNormalPosition); - placement.MaxPosition = new POINT(WindowMaxPosition); - placement.MinPosition = new POINT(WindowMinPosition); - placement.ShowCmd = ShowWindowCommand; - placement.Flags = WindowPlacementFlags; - return placement; - } - - public void SetEditorPlacement(WindowPlacement placement) - { - WindowNormalPosition = placement.NormalPosition.ToRectangle(); - WindowMaxPosition = placement.MaxPosition.ToPoint(); - WindowMinPosition = placement.MinPosition.ToPoint(); - ShowWindowCommand = placement.ShowCmd; - WindowPlacementFlags = placement.Flags; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/BackgroundForm.cs b/Greenshot.ImageEditor/Controls/BackgroundForm.cs deleted file mode 100644 index e4bbf9bfa..000000000 --- a/Greenshot.ImageEditor/Controls/BackgroundForm.cs +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using GreenshotPlugin.Core; -using System; -using System.Drawing; -using System.Threading; -using System.Windows.Forms; - -namespace GreenshotPlugin.Controls -{ - /// - /// Description of PleaseWaitForm. - /// - internal partial class BackgroundForm : Form - { - private volatile bool _shouldClose; - - private void BackgroundShowDialog() - { - ShowDialog(); - } - - public static BackgroundForm ShowAndWait(string title, string text) - { - BackgroundForm backgroundForm = new BackgroundForm(title, text); - // Show form in background thread - Thread backgroundTask = new Thread(backgroundForm.BackgroundShowDialog); - backgroundForm.Name = "Background form"; - backgroundTask.IsBackground = true; - backgroundTask.SetApartmentState(ApartmentState.STA); - backgroundTask.Start(); - return backgroundForm; - } - - public BackgroundForm(string title, string text) - { - // - // The InitializeComponent() call is required for Windows Forms designer support. - // - InitializeComponent(); - Icon = GreenshotResources.getGreenshotIcon(); - _shouldClose = false; - Text = title; - label_pleasewait.Text = text; - FormClosing += PreventFormClose; - timer_checkforclose.Start(); - } - - // Can be used instead of ShowDialog - public new void Show() - { - base.Show(); - bool positioned = false; - foreach (Screen screen in Screen.AllScreens) - { - if (screen.Bounds.Contains(Cursor.Position)) - { - positioned = true; - Location = new Point(screen.Bounds.X + (screen.Bounds.Width / 2) - (Width / 2), screen.Bounds.Y + (screen.Bounds.Height / 2) - (Height / 2)); - break; - } - } - if (!positioned) - { - Location = new Point(Cursor.Position.X - Width / 2, Cursor.Position.Y - Height / 2); - } - } - - private void PreventFormClose(object sender, FormClosingEventArgs e) - { - if (!_shouldClose) - { - e.Cancel = true; - } - } - - private void Timer_checkforcloseTick(object sender, EventArgs e) - { - if (_shouldClose) - { - timer_checkforclose.Stop(); - BeginInvoke(new EventHandler(delegate { Close(); })); - } - } - - public void CloseDialog() - { - _shouldClose = true; - Application.DoEvents(); - } - - private void BackgroundFormFormClosing(object sender, FormClosingEventArgs e) - { - timer_checkforclose.Stop(); - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/BackgroundForm.designer.cs b/Greenshot.ImageEditor/Controls/BackgroundForm.designer.cs deleted file mode 100644 index 1d1c30d28..000000000 --- a/Greenshot.ImageEditor/Controls/BackgroundForm.designer.cs +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -namespace GreenshotPlugin.Controls -{ - partial class BackgroundForm - { - /// - /// Designer variable used to keep track of non-visual components. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Disposes resources used by the form. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing) { - if (components != null) { - components.Dispose(); - } - } - base.Dispose(disposing); - } - - /// - /// This method is required for Windows Forms designer support. - /// Do not change the method contents inside the source code editor. The Forms designer might - /// not be able to load this method if it was changed manually. - /// - private void InitializeComponent() - { - this.components = new System.ComponentModel.Container(); - this.label_pleasewait = new System.Windows.Forms.Label(); - this.timer_checkforclose = new System.Windows.Forms.Timer(this.components); - this.SuspendLayout(); - // - // label_pleasewait - // - this.label_pleasewait.AutoSize = true; - this.label_pleasewait.Dock = System.Windows.Forms.DockStyle.Fill; - this.label_pleasewait.Location = new System.Drawing.Point(0, 0); - this.label_pleasewait.Name = "label_pleasewait"; - this.label_pleasewait.Padding = new System.Windows.Forms.Padding(10); - this.label_pleasewait.Size = new System.Drawing.Size(90, 33); - this.label_pleasewait.TabIndex = 0; - this.label_pleasewait.Text = "Please wait..."; - this.label_pleasewait.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.label_pleasewait.UseWaitCursor = true; - // - // timer_checkforclose - // - this.timer_checkforclose.Interval = 200; - this.timer_checkforclose.Tick += new System.EventHandler(this.Timer_checkforcloseTick); - // - // BackgroundForm - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.AutoSize = true; - this.ClientSize = new System.Drawing.Size(169, 52); - this.ControlBox = true; - this.Controls.Add(this.label_pleasewait); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "BackgroundForm"; - this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; - this.Text = "Greenshot"; - this.TopMost = true; - this.UseWaitCursor = true; - this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.BackgroundFormFormClosing); - this.ResumeLayout(false); - this.PerformLayout(); - } - private System.Windows.Forms.Timer timer_checkforclose; - private System.Windows.Forms.Label label_pleasewait; - } -} diff --git a/Greenshot.ImageEditor/Controls/BindableToolStripButton.cs b/Greenshot.ImageEditor/Controls/BindableToolStripButton.cs deleted file mode 100644 index 7b45869a8..000000000 --- a/Greenshot.ImageEditor/Controls/BindableToolStripButton.cs +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using GreenshotPlugin.Controls; -using System; -using System.ComponentModel; -using System.Windows.Forms; - -namespace Greenshot.Controls -{ - /// - /// Description of BindableToolStripButton. - /// - internal class BindableToolStripButton : ToolStripButton, INotifyPropertyChanged, IGreenshotLanguageBindable - { - public event PropertyChangedEventHandler PropertyChanged; - - [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] - public string LanguageKey - { - get; - set; - } - - public BindableToolStripButton() - { - CheckedChanged += BindableToolStripButton_CheckedChanged; - } - - private void BindableToolStripButton_CheckedChanged(object sender, EventArgs e) - { - if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Checked")); - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/BindableToolStripComboBox.cs b/Greenshot.ImageEditor/Controls/BindableToolStripComboBox.cs deleted file mode 100644 index 63e52cf51..000000000 --- a/Greenshot.ImageEditor/Controls/BindableToolStripComboBox.cs +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using GreenshotPlugin.Controls; -using System; -using System.ComponentModel; -using System.Windows.Forms; - -namespace Greenshot.Controls -{ - /// - /// A simple ToolStripComboBox implementing INotifyPropertyChanged for data binding - /// - internal class BindableToolStripComboBox : ToolStripComboBox, INotifyPropertyChanged, IGreenshotLanguageBindable - { - public event PropertyChangedEventHandler PropertyChanged; - - [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] - public string LanguageKey - { - get; - set; - } - - public BindableToolStripComboBox() - { - SelectedIndexChanged += BindableToolStripComboBox_SelectedIndexChanged; - } - - private void BindableToolStripComboBox_SelectedIndexChanged(object sender, EventArgs e) - { - if (PropertyChanged != null) - { - PropertyChanged(this, new PropertyChangedEventArgs("SelectedItem")); - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/BindableToolStripDropDownButton.cs b/Greenshot.ImageEditor/Controls/BindableToolStripDropDownButton.cs deleted file mode 100644 index 1848ac25f..000000000 --- a/Greenshot.ImageEditor/Controls/BindableToolStripDropDownButton.cs +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using GreenshotPlugin.Controls; -using System.ComponentModel; -using System.Windows.Forms; - -namespace Greenshot.Controls -{ - /// - /// A simple ToolStripDropDownButton implementing INotifyPropertyChanged for data binding. - /// Also, when a DropDownItem is selected, the DropDownButton adopts its Tag and Image. - /// The selected tag can be accessed via SelectedTag property. - /// - internal class BindableToolStripDropDownButton : ToolStripDropDownButton, INotifyPropertyChanged, IGreenshotLanguageBindable - { - public event PropertyChangedEventHandler PropertyChanged; - - [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] - public string LanguageKey - { - get; - set; - } - - public object SelectedTag - { - get { if (Tag == null && DropDownItems.Count > 0) Tag = DropDownItems[0].Tag; return Tag; } - set { AdoptFromTag(value); } - } - - protected override void OnDropDownItemClicked(ToolStripItemClickedEventArgs e) - { - ToolStripItem clickedItem = e.ClickedItem; - if (Tag == null || !Tag.Equals(clickedItem.Tag)) - { - Tag = clickedItem.Tag; - Image = clickedItem.Image; - if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("SelectedTag")); - } - base.OnDropDownItemClicked(e); - } - - private void AdoptFromTag(object tag) - { - if (Tag == null || !Tag.Equals(tag)) - { - Tag = tag; - foreach (ToolStripItem item in DropDownItems) - { - if (item.Tag != null && item.Tag.Equals(tag)) - { - Image = item.Image; - break; - } - } - Tag = tag; - if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("SelectedTag")); - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/ColorButton.cs b/Greenshot.ImageEditor/Controls/ColorButton.cs deleted file mode 100644 index 5edd69dc7..000000000 --- a/Greenshot.ImageEditor/Controls/ColorButton.cs +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using GreenshotPlugin.Controls; -using System; -using System.ComponentModel; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Windows.Forms; - -namespace Greenshot.Controls -{ - /// - /// Description of ColorButton. - /// - internal class ColorButton : Button, IGreenshotLanguageBindable - { - public event PropertyChangedEventHandler PropertyChanged; - private Color selectedColor = Color.White; - - [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] - public string LanguageKey - { - get; - set; - } - - public ColorButton() - { - Click += ColorButtonClick; - } - - public Color SelectedColor - { - get - { - return selectedColor; - } - set - { - selectedColor = value; - - Brush brush; - if (value != Color.Transparent) - { - brush = new SolidBrush(value); - } - else - { - brush = new HatchBrush(HatchStyle.Percent50, Color.White, Color.Gray); - } - - if (Image != null) - { - using (Graphics graphics = Graphics.FromImage(Image)) - { - graphics.FillRectangle(brush, new Rectangle(4, 17, 16, 3)); - } - } - - // cleanup GDI Object - brush.Dispose(); - Invalidate(); - } - } - - private void ColorButtonClick(object sender, EventArgs e) - { - ColorDialog colorDialog = ColorDialog.GetInstance(); - colorDialog.Color = SelectedColor; - // Using the parent to make sure the dialog doesn't show on another window - colorDialog.ShowDialog(Parent.Parent); - if (colorDialog.DialogResult != DialogResult.Cancel) - { - if (!colorDialog.Color.Equals(SelectedColor)) - { - SelectedColor = colorDialog.Color; - if (PropertyChanged != null) - { - PropertyChanged(this, new PropertyChangedEventArgs("SelectedColor")); - } - } - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/CustomToolStripProfessionalRenderer.cs b/Greenshot.ImageEditor/Controls/CustomToolStripProfessionalRenderer.cs deleted file mode 100644 index 43111a455..000000000 --- a/Greenshot.ImageEditor/Controls/CustomToolStripProfessionalRenderer.cs +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System.Drawing; -using System.Windows.Forms; - -namespace Greenshot.Controls -{ - /// - /// Prevent having a gradient background in the toolstrip, and the overflow button - /// See: http://stackoverflow.com/a/16926979 - /// - internal class CustomProfessionalColorTable : ProfessionalColorTable - { - public override Color ToolStripGradientBegin - { - get { return SystemColors.Control; } - } - public override Color ToolStripGradientMiddle - { - get { return SystemColors.Control; } - } - public override Color ToolStripGradientEnd - { - get { return SystemColors.Control; } - } - public override Color OverflowButtonGradientBegin - { - get { return SystemColors.Control; } - } - public override Color OverflowButtonGradientMiddle - { - get { return SystemColors.Control; } - } - public override Color OverflowButtonGradientEnd - { - get { return SystemColors.Control; } - } - } - - /// - /// ToolStripProfessionalRenderer without having a visual artifact - /// See: http://stackoverflow.com/a/16926979 and http://stackoverflow.com/a/13418840 - /// - internal class CustomToolStripProfessionalRenderer : ToolStripProfessionalRenderer - { - public CustomToolStripProfessionalRenderer() : base(new CustomProfessionalColorTable()) - { - RoundedEdges = false; - } - - /// - /// By overriding the OnRenderToolStripBorder we can make the ToolStrip without border - /// - /// - protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e) - { - // Don't draw a border - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/FontFamilyComboBox.cs b/Greenshot.ImageEditor/Controls/FontFamilyComboBox.cs deleted file mode 100644 index 7bcf4bef6..000000000 --- a/Greenshot.ImageEditor/Controls/FontFamilyComboBox.cs +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System; -using System.ComponentModel; -using System.Drawing; -using System.Windows.Forms; - -namespace Greenshot.Controls -{ - /// - /// ToolStripComboBox containing installed font families, - /// implementing INotifyPropertyChanged for data binding - /// - internal class FontFamilyComboBox : ToolStripComboBox, INotifyPropertyChanged - { - public event PropertyChangedEventHandler PropertyChanged; - - public FontFamily FontFamily - { - get - { - return (FontFamily)SelectedItem; - } - set - { - if (!SelectedItem.Equals(value)) - { - SelectedItem = value; - } - } - } - - public FontFamilyComboBox() : base() - { - if (ComboBox != null) - { - ComboBox.DataSource = FontFamily.Families; - ComboBox.DisplayMember = "Name"; - SelectedIndexChanged += BindableToolStripComboBox_SelectedIndexChanged; - ComboBox.DrawMode = DrawMode.OwnerDrawFixed; - ComboBox.DrawItem += ComboBox_DrawItem; - } - } - - private void ComboBox_DrawItem(object sender, DrawItemEventArgs e) - { - // DrawBackground handles drawing the background (i.e,. hot-tracked v. not) - // It uses the system colors (Bluish, and and white, by default) - // same as calling e.Graphics.FillRectangle ( SystemBrushes.Highlight, e.Bounds ); - e.DrawBackground(); - - if (e.Index > -1) - { - FontFamily fontFamily = Items[e.Index] as FontFamily; - FontStyle fontStyle = FontStyle.Regular; - if (fontFamily != null && !fontFamily.IsStyleAvailable(FontStyle.Regular)) - { - if (fontFamily.IsStyleAvailable(FontStyle.Bold)) - { - fontStyle = FontStyle.Bold; - } - else if (fontFamily.IsStyleAvailable(FontStyle.Italic)) - { - fontStyle = FontStyle.Italic; - } - else if (fontFamily.IsStyleAvailable(FontStyle.Strikeout)) - { - fontStyle = FontStyle.Strikeout; - } - else if (fontFamily.IsStyleAvailable(FontStyle.Underline)) - { - fontStyle = FontStyle.Underline; - } - } - try - { - if (fontFamily != null) - { - DrawText(e.Graphics, fontFamily, fontStyle, e.Bounds, fontFamily.Name); - } - } - catch - { - if (fontFamily != null) - { - // If the drawing failed, BUG-1770 seems to have a weird case that causes: Font 'Lucida Sans Typewriter' does not support style 'Regular' - DrawText(e.Graphics, FontFamily.GenericSansSerif, FontStyle.Regular, e.Bounds, fontFamily.Name); - } - } - } - // Uncomment this if you actually like the way the focus rectangle looks - //e.DrawFocusRectangle (); - } - - /// - /// Helper method to draw the string - /// - /// - /// - /// - /// - /// - private void DrawText(Graphics graphics, FontFamily fontFamily, FontStyle fontStyle, Rectangle bounds, string text) - { - using (Font font = new Font(fontFamily, Font.Size + 5, fontStyle, GraphicsUnit.Pixel)) - { - // Make sure the text is visible by centering it in the line - using (StringFormat stringFormat = new StringFormat()) - { - stringFormat.LineAlignment = StringAlignment.Center; - graphics.DrawString(text, font, Brushes.Black, bounds, stringFormat); - } - } - } - - private void BindableToolStripComboBox_SelectedIndexChanged(object sender, EventArgs e) - { - if (PropertyChanged != null) - { - PropertyChanged(this, new PropertyChangedEventArgs("Text")); - PropertyChanged(this, new PropertyChangedEventArgs("FontFamily")); - PropertyChanged(this, new PropertyChangedEventArgs("SelectedIndex")); - PropertyChanged(this, new PropertyChangedEventArgs("SelectedItem")); - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/FormWithoutActivation.cs b/Greenshot.ImageEditor/Controls/FormWithoutActivation.cs deleted file mode 100644 index 71950d53d..000000000 --- a/Greenshot.ImageEditor/Controls/FormWithoutActivation.cs +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System.Windows.Forms; - -namespace GreenshotPlugin.Controls -{ - /// - /// FormWithoutActivation is exactly like a normal form, but doesn't activate (steal focus) - /// - internal class FormWithoutActivation : Form - { - protected override bool ShowWithoutActivation - { - get { return true; } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/GreenshotButton.cs b/Greenshot.ImageEditor/Controls/GreenshotButton.cs deleted file mode 100644 index 28f8af8ec..000000000 --- a/Greenshot.ImageEditor/Controls/GreenshotButton.cs +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System.ComponentModel; -using System.Windows.Forms; - -namespace GreenshotPlugin.Controls -{ - internal class GreenshotButton : Button, IGreenshotLanguageBindable - { - [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] - public string LanguageKey - { - get; - set; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/GreenshotCheckBox.cs b/Greenshot.ImageEditor/Controls/GreenshotCheckBox.cs deleted file mode 100644 index cd70b69c7..000000000 --- a/Greenshot.ImageEditor/Controls/GreenshotCheckBox.cs +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System.ComponentModel; -using System.Windows.Forms; - -namespace GreenshotPlugin.Controls -{ - /// - /// Description of GreenshotCheckbox. - /// - internal class GreenshotCheckBox : CheckBox, IGreenshotLanguageBindable, IGreenshotConfigBindable - { - [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] - public string LanguageKey - { - get; - set; - } - - [Category("Greenshot"), DefaultValue("Core"), Description("Specifies the Ini-Section to map this control with.")] - public string SectionName { get; set; } = "Core"; - - [Category("Greenshot"), DefaultValue(null), Description("Specifies the property name to map the configuration.")] - public string PropertyName - { - get; - set; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/GreenshotColumnSorter.cs b/Greenshot.ImageEditor/Controls/GreenshotColumnSorter.cs deleted file mode 100644 index 8c4bb17b2..000000000 --- a/Greenshot.ImageEditor/Controls/GreenshotColumnSorter.cs +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System.Collections; -using System.Windows.Forms; - -namespace GreenshotPlugin.Controls -{ - /// - /// This class is an implementation of the 'IComparer' interface. - /// - internal class GreenshotColumnSorter : IComparer - { - /// - /// Specifies the column to be sorted - /// - private int _columnToSort; - /// - /// Specifies the order in which to sort (i.e. 'Ascending'). - /// - private SortOrder _orderOfSort; - /// - /// Case insensitive comparer object - /// - private readonly CaseInsensitiveComparer _objectCompare; - - /// - /// Class constructor. Initializes various elements - /// - public GreenshotColumnSorter() - { - // Initialize the column to '0' - _columnToSort = 0; - - // Initialize the sort order to 'none' - _orderOfSort = SortOrder.None; - - // Initialize the CaseInsensitiveComparer object - _objectCompare = new CaseInsensitiveComparer(); - } - - /// - /// This method is inherited from the IComparer interface. It compares the two objects passed using a case insensitive comparison. - /// - /// First object to be compared - /// Second object to be compared - /// The result of the comparison. "0" if equal, negative if 'x' is less than 'y' and positive if 'x' is greater than 'y' - public int Compare(object x, object y) - { - if (x == null && y == null) - { - return 0; - } - if (x == null) - { - return -1; - } - if (y == null) - { - return 1; - } - // Cast the objects to be compared to ListViewItem objects - var listviewX = (ListViewItem)x; - var listviewY = (ListViewItem)y; - - // Compare the two items - var compareResult = _objectCompare.Compare(listviewX.SubItems[_columnToSort].Text, listviewY.SubItems[_columnToSort].Text); - - // Calculate correct return value based on object comparison - if (_orderOfSort == SortOrder.Ascending) - { - // Ascending sort is selected, return normal result of compare operation - return compareResult; - } - if (_orderOfSort == SortOrder.Descending) - { - // Descending sort is selected, return negative result of compare operation - return (-compareResult); - } - - // Return '0' to indicate they are equal - return 0; - } - - /// - /// Gets or sets the number of the column to which to apply the sorting operation (Defaults to '0'). - /// - public int SortColumn - { - set - { - _columnToSort = value; - } - get - { - return _columnToSort; - } - } - - /// - /// Gets or sets the order of sorting to apply (for example, 'Ascending' or 'Descending'). - /// - public SortOrder Order - { - set - { - _orderOfSort = value; - } - get - { - return _orderOfSort; - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/GreenshotComboBox.cs b/Greenshot.ImageEditor/Controls/GreenshotComboBox.cs deleted file mode 100644 index 40b43dbb0..000000000 --- a/Greenshot.ImageEditor/Controls/GreenshotComboBox.cs +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System; -using System.ComponentModel; -using System.Windows.Forms; - -namespace GreenshotPlugin.Controls -{ - internal class GreenshotComboBox : ComboBox, IGreenshotConfigBindable - { - private Type _enumType = null; - private Enum _selectedEnum = null; - - [Category("Greenshot"), DefaultValue("Core"), Description("Specifies the Ini-Section to map this control with.")] - public string SectionName { get; set; } = "Core"; - - [Category("Greenshot"), DefaultValue(null), Description("Specifies the property name to map the configuration.")] - public string PropertyName - { - get; - set; - } - - public GreenshotComboBox() - { - SelectedIndexChanged += delegate - { - StoreSelectedEnum(); - }; - } - - public void SetValue(Enum currentValue) - { - if (currentValue != null) - { - _selectedEnum = currentValue; - SelectedItem = currentValue; - } - } - - /// - /// This is a method to popululate the ComboBox - /// with the items from the enumeration - /// - /// TEnum to populate with - public void Populate(Type enumType) - { - // Store the enum-type, so we can work with it - _enumType = enumType; - - var availableValues = Enum.GetValues(enumType); - Items.Clear(); - foreach (var enumValue in availableValues) - { - Items.Add(enumValue); - } - } - - /// - /// Store the selected value internally - /// - private void StoreSelectedEnum() - { - string enumTypeName = _enumType.Name; - string selectedValue = SelectedItem as string; - var availableValues = Enum.GetValues(_enumType); - object returnValue = null; - - try - { - returnValue = Enum.Parse(_enumType, selectedValue); - } - catch (Exception) - { - } - - _selectedEnum = (Enum)returnValue; - } - - /// - /// Get the selected enum value from the combobox, uses generics - /// - /// The enum value of the combobox - public Enum GetSelectedEnum() - { - return _selectedEnum; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/GreenshotForm.cs b/Greenshot.ImageEditor/Controls/GreenshotForm.cs deleted file mode 100644 index f22652b31..000000000 --- a/Greenshot.ImageEditor/Controls/GreenshotForm.cs +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.IniFile; -using GreenshotPlugin.Core; -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.ComponentModel.Design; -using System.Reflection; -using System.Windows.Forms; - -namespace GreenshotPlugin.Controls -{ - /// - /// This form is used for automatically binding the elements of the form to the language - /// - public class GreenshotForm : Form, IGreenshotLanguageBindable - { - protected static CoreConfiguration coreConfiguration; - private static readonly IDictionary reflectionCache = new Dictionary(); - private IComponentChangeService m_changeService; - private bool _storeFieldsManually; - private IDictionary _designTimeControls; - private IDictionary _designTimeToolStripItems; - - static GreenshotForm() - { - if (!IsInDesignMode) - { - coreConfiguration = IniConfig.GetIniSection(); - } - } - - [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] - public string LanguageKey - { - get; - set; - } - - /// - /// Used to check the designmode during a constructor - /// - /// - protected static bool IsInDesignMode - { - get - { - return (Application.ExecutablePath.IndexOf("devenv.exe", StringComparison.OrdinalIgnoreCase) > -1) || (Application.ExecutablePath.IndexOf("sharpdevelop.exe", StringComparison.OrdinalIgnoreCase) > -1 || (Application.ExecutablePath.IndexOf("wdexpress.exe", StringComparison.OrdinalIgnoreCase) > -1)); - } - } - - protected bool ManualStoreFields - { - get - { - return _storeFieldsManually; - } - set - { - _storeFieldsManually = value; - } - } - - /// - /// When this is set, the form will be brought to the foreground as soon as it is shown. - /// - protected bool ToFront - { - get; - set; - } - - /// - /// Code to initialize the language etc during design time - /// - protected void InitializeForDesigner() - { - if (DesignMode) - { - _designTimeControls = new Dictionary(); - _designTimeToolStripItems = new Dictionary(); - } - } - - protected override void OnLoad(EventArgs e) - { - // Every GreenshotForm should have it's default icon - // And it might not ne needed for a Tool Window, but still for the task manager / switcher it's important - Icon = GreenshotResources.getGreenshotIcon(); - if (!DesignMode) - { - FillFields(); - base.OnLoad(e); - } - else - { - LOG.Info("OnLoad called from designer."); - InitializeForDesigner(); - base.OnLoad(e); - } - } - - /// - /// Make sure the form is visible, if this is wanted - /// - /// EventArgs - protected override void OnShown(EventArgs e) - { - base.OnShown(e); - if (ToFront) - { - WindowDetails.ToForeground(Handle); - } - } - - /// - /// check if the form was closed with an OK, if so store the values in the GreenshotControls - /// - /// - protected override void OnClosed(EventArgs e) - { - if (!DesignMode && !_storeFieldsManually) - { - if (DialogResult == DialogResult.OK) - { - LOG.Info("Form was closed with OK: storing field values."); - StoreFields(); - } - } - base.OnClosed(e); - } - - /// - /// This override allows the control to register event handlers for IComponentChangeService events - /// at the time the control is sited, which happens only in design mode. - /// - public override ISite Site - { - get - { - return base.Site; - } - set - { - // Clear any component change event handlers. - ClearChangeNotifications(); - - // Set the new Site value. - base.Site = value; - - m_changeService = (IComponentChangeService)GetService(typeof(IComponentChangeService)); - - // Register event handlers for component change events. - RegisterChangeNotifications(); - } - } - - private void ClearChangeNotifications() - { - // The m_changeService value is null when not in design mode, - // as the IComponentChangeService is only available at design time. - m_changeService = (IComponentChangeService)GetService(typeof(IComponentChangeService)); - - // Clear our the component change events to prepare for re-siting. - if (m_changeService != null) - { - m_changeService.ComponentAdded -= OnComponentAdded; - } - } - - private void RegisterChangeNotifications() - { - // Register the event handlers for the IComponentChangeService events - if (m_changeService != null) - { - m_changeService.ComponentAdded += OnComponentAdded; - } - } - - private void OnComponentAdded(object sender, ComponentEventArgs ce) - { - if (ce.Component != null && ((IComponent)ce.Component).Site != null) - { - Control control = ce.Component as Control; - if (control != null) - { - if (!_designTimeControls.ContainsKey(control.Name)) - { - _designTimeControls.Add(control.Name, control); - } - else - { - _designTimeControls[control.Name] = control; - } - } - else if (ce.Component is ToolStripItem) - { - ToolStripItem item = ce.Component as ToolStripItem; - if (!_designTimeControls.ContainsKey(item.Name)) - { - _designTimeToolStripItems.Add(item.Name, item); - } - else - { - _designTimeToolStripItems[item.Name] = item; - } - } - } - } - - // Clean up any resources being used. - protected override void Dispose(bool disposing) - { - if (disposing) - { - ClearChangeNotifications(); - } - base.Dispose(disposing); - } - - /// - /// Helper method to cache the fieldinfo values, so we don't need to reflect all the time! - /// - /// - /// - private static FieldInfo[] GetCachedFields(Type typeToGetFieldsFor) - { - FieldInfo[] fields = null; - if (!reflectionCache.TryGetValue(typeToGetFieldsFor, out fields)) - { - fields = typeToGetFieldsFor.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); - reflectionCache.Add(typeToGetFieldsFor, fields); - } - return fields; - } - - /// - /// Fill all GreenshotControls with the values from the configuration - /// - protected void FillFields() - { - foreach (FieldInfo field in GetCachedFields(GetType())) - { - Object controlObject = field.GetValue(this); - if (controlObject == null) - { - continue; - } - IGreenshotConfigBindable configBindable = controlObject as IGreenshotConfigBindable; - if (configBindable == null) - { - continue; - } - if (!string.IsNullOrEmpty(configBindable.SectionName) && !string.IsNullOrEmpty(configBindable.PropertyName)) - { - IniSection section = IniConfig.GetIniSection(configBindable.SectionName); - if (section != null) - { - IniValue iniValue = null; - if (!section.Values.TryGetValue(configBindable.PropertyName, out iniValue)) - { - LOG.DebugFormat("Wrong property '{0}' configured for field '{1}'", configBindable.PropertyName, field.Name); - continue; - } - - CheckBox checkBox = controlObject as CheckBox; - if (checkBox != null) - { - checkBox.Checked = (bool)iniValue.Value; - checkBox.Enabled = !iniValue.IsFixed; - continue; - } - RadioButton radíoButton = controlObject as RadioButton; - if (radíoButton != null) - { - radíoButton.Checked = (bool)iniValue.Value; - radíoButton.Enabled = !iniValue.IsFixed; - continue; - } - GreenshotComboBox comboxBox = controlObject as GreenshotComboBox; - if (comboxBox != null) - { - comboxBox.Populate(iniValue.ValueType); - comboxBox.SetValue((Enum)iniValue.Value); - comboxBox.Enabled = !iniValue.IsFixed; - } - } - } - } - OnFieldsFilled(); - } - - protected virtual void OnFieldsFilled() - { - } - - /// - /// Store all GreenshotControl values to the configuration - /// - protected void StoreFields() - { - bool iniDirty = false; - foreach (FieldInfo field in GetCachedFields(GetType())) - { - Object controlObject = field.GetValue(this); - if (controlObject == null) - { - continue; - } - IGreenshotConfigBindable configBindable = controlObject as IGreenshotConfigBindable; - if (configBindable == null) - { - continue; - } - - if (!string.IsNullOrEmpty(configBindable.SectionName) && !string.IsNullOrEmpty(configBindable.PropertyName)) - { - IniSection section = IniConfig.GetIniSection(configBindable.SectionName); - if (section != null) - { - IniValue iniValue = null; - if (!section.Values.TryGetValue(configBindable.PropertyName, out iniValue)) - { - continue; - } - CheckBox checkBox = controlObject as CheckBox; - if (checkBox != null) - { - iniValue.Value = checkBox.Checked; - iniDirty = true; - continue; - } - RadioButton radioButton = controlObject as RadioButton; - if (radioButton != null) - { - iniValue.Value = radioButton.Checked; - iniDirty = true; - continue; - } - GreenshotComboBox comboxBox = controlObject as GreenshotComboBox; - if (comboxBox != null) - { - iniValue.Value = comboxBox.GetSelectedEnum(); - iniDirty = true; - continue; - } - } - } - } - if (iniDirty) - { - //IniConfig.Save(); - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/GreenshotGroupBox.cs b/Greenshot.ImageEditor/Controls/GreenshotGroupBox.cs deleted file mode 100644 index eff5753dd..000000000 --- a/Greenshot.ImageEditor/Controls/GreenshotGroupBox.cs +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System.ComponentModel; -using System.Windows.Forms; - -namespace GreenshotPlugin.Controls -{ - internal class GreenshotGroupBox : GroupBox, IGreenshotLanguageBindable - { - [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] - public string LanguageKey - { - get; - set; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/GreenshotLabel.cs b/Greenshot.ImageEditor/Controls/GreenshotLabel.cs deleted file mode 100644 index 5743154f0..000000000 --- a/Greenshot.ImageEditor/Controls/GreenshotLabel.cs +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System.ComponentModel; -using System.Windows.Forms; - -namespace GreenshotPlugin.Controls -{ - internal class GreenshotLabel : Label, IGreenshotLanguageBindable - { - [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] - public string LanguageKey - { - get; - set; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/GreenshotRadioButton.cs b/Greenshot.ImageEditor/Controls/GreenshotRadioButton.cs deleted file mode 100644 index 34e780b04..000000000 --- a/Greenshot.ImageEditor/Controls/GreenshotRadioButton.cs +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System.ComponentModel; -using System.Windows.Forms; - -namespace GreenshotPlugin.Controls -{ - /// - /// Description of GreenshotCheckbox. - /// - internal class GreenshotRadioButton : RadioButton, IGreenshotLanguageBindable, IGreenshotConfigBindable - { - [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] - public string LanguageKey - { - get; - set; - } - - private string sectionName = "Core"; - [Category("Greenshot"), DefaultValue("Core"), Description("Specifies the Ini-Section to map this control with.")] - public string SectionName - { - get - { - return sectionName; - } - set - { - sectionName = value; - } - } - - [Category("Greenshot"), DefaultValue(null), Description("Specifies the property name to map the configuration.")] - public string PropertyName - { - get; - set; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/GreenshotTabPage.cs b/Greenshot.ImageEditor/Controls/GreenshotTabPage.cs deleted file mode 100644 index d9878fc60..000000000 --- a/Greenshot.ImageEditor/Controls/GreenshotTabPage.cs +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System.ComponentModel; -using System.Windows.Forms; - -namespace GreenshotPlugin.Controls -{ - internal class GreenshotTabPage : TabPage, IGreenshotLanguageBindable - { - [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] - public string LanguageKey - { - get; - set; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/GreenshotTextBox.cs b/Greenshot.ImageEditor/Controls/GreenshotTextBox.cs deleted file mode 100644 index c95a1a025..000000000 --- a/Greenshot.ImageEditor/Controls/GreenshotTextBox.cs +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System.ComponentModel; -using System.Windows.Forms; - -namespace GreenshotPlugin.Controls -{ - internal class GreenshotTextBox : TextBox, IGreenshotConfigBindable - { - [Category("Greenshot"), DefaultValue("Core"), Description("Specifies the Ini-Section to map this control with.")] - public string SectionName { get; set; } = "Core"; - - [Category("Greenshot"), DefaultValue(null), Description("Specifies the property name to map the configuration.")] - public string PropertyName - { - get; - set; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/GreenshotToolDropDownButton.cs b/Greenshot.ImageEditor/Controls/GreenshotToolDropDownButton.cs deleted file mode 100644 index a1dec74e0..000000000 --- a/Greenshot.ImageEditor/Controls/GreenshotToolDropDownButton.cs +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System.ComponentModel; -using System.Windows.Forms; - -namespace GreenshotPlugin.Controls -{ - internal class GreenshotToolStripDropDownButton : ToolStripDropDownButton, IGreenshotLanguageBindable - { - [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] - public string LanguageKey - { - get; - set; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/GreenshotToolStripButton.cs b/Greenshot.ImageEditor/Controls/GreenshotToolStripButton.cs deleted file mode 100644 index fea02e5f4..000000000 --- a/Greenshot.ImageEditor/Controls/GreenshotToolStripButton.cs +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System.ComponentModel; -using System.Windows.Forms; - -namespace GreenshotPlugin.Controls -{ - internal class GreenshotToolStripButton : ToolStripButton, IGreenshotLanguageBindable - { - [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] - public string LanguageKey - { - get; - set; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/GreenshotToolStripLabel.cs b/Greenshot.ImageEditor/Controls/GreenshotToolStripLabel.cs deleted file mode 100644 index 7835c0b22..000000000 --- a/Greenshot.ImageEditor/Controls/GreenshotToolStripLabel.cs +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System.ComponentModel; -using System.Windows.Forms; - -namespace GreenshotPlugin.Controls -{ - internal class GreenshotToolStripLabel : ToolStripLabel, IGreenshotLanguageBindable - { - [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] - public string LanguageKey - { - get; - set; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/GreenshotToolStripMenuItem.cs b/Greenshot.ImageEditor/Controls/GreenshotToolStripMenuItem.cs deleted file mode 100644 index 81b037881..000000000 --- a/Greenshot.ImageEditor/Controls/GreenshotToolStripMenuItem.cs +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System.ComponentModel; -using System.Windows.Forms; - -namespace GreenshotPlugin.Controls -{ - internal class GreenshotToolStripMenuItem : ToolStripMenuItem, IGreenshotLanguageBindable - { - [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] - public string LanguageKey - { - get; - set; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/IGreenshotConfigBindable.cs b/Greenshot.ImageEditor/Controls/IGreenshotConfigBindable.cs deleted file mode 100644 index 7121849ff..000000000 --- a/Greenshot.ImageEditor/Controls/IGreenshotConfigBindable.cs +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -namespace GreenshotPlugin.Controls -{ - internal interface IGreenshotConfigBindable - { - /// - /// The class where the property-value is stored - /// - string SectionName - { - get; - set; - } - - /// - /// Path to the property value which will be mapped with this control - /// - string PropertyName - { - get; - set; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/IGreenshotLanguageBindable.cs b/Greenshot.ImageEditor/Controls/IGreenshotLanguageBindable.cs deleted file mode 100644 index a7531aa92..000000000 --- a/Greenshot.ImageEditor/Controls/IGreenshotLanguageBindable.cs +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -namespace GreenshotPlugin.Controls -{ - /// - /// This interface describes the designer fields that need to be implemented for Greenshot controls - /// - internal interface IGreenshotLanguageBindable - { - /// - /// Language key to use to fill the Text value with - /// - string LanguageKey - { - get; - set; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/MenuStripEx.cs b/Greenshot.ImageEditor/Controls/MenuStripEx.cs deleted file mode 100644 index f890b05df..000000000 --- a/Greenshot.ImageEditor/Controls/MenuStripEx.cs +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System; -using System.Windows.Forms; - -namespace Greenshot.Controls -{ - /// - /// This is an extension of the default MenuStrip and allows us to click it even when the form doesn't have focus. - /// See: http://blogs.msdn.com/b/rickbrew/archive/2006/01/09/511003.aspx - /// - internal class MenuStripEx : MenuStrip - { - private const int WM_MOUSEACTIVATE = 0x21; - - private enum NativeConstants : uint - { - MA_ACTIVATE = 1, - MA_ACTIVATEANDEAT = 2, - } - - private bool _clickThrough; - /// - /// Gets or sets whether the ToolStripEx honors item clicks when its containing form does not have input focus. - /// - /// - /// Default value is false, which is the same behavior provided by the base ToolStrip class. - /// - public bool ClickThrough - { - get - { - return _clickThrough; - } - - set - { - _clickThrough = value; - } - } - - protected override void WndProc(ref Message m) - { - base.WndProc(ref m); - if (_clickThrough && m.Msg == WM_MOUSEACTIVATE && m.Result == (IntPtr)NativeConstants.MA_ACTIVATEANDEAT) - { - m.Result = (IntPtr)NativeConstants.MA_ACTIVATE; - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/NonJumpingPanel.cs b/Greenshot.ImageEditor/Controls/NonJumpingPanel.cs deleted file mode 100644 index f0c336a57..000000000 --- a/Greenshot.ImageEditor/Controls/NonJumpingPanel.cs +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System.Drawing; -using System.Windows.Forms; - -namespace GreenshotPlugin.Controls -{ - /// - /// See: http://nickstips.wordpress.com/2010/03/03/c-panel-resets-scroll-position-after-focus-is-lost-and-regained/ - /// - internal class NonJumpingPanel : Panel - { - protected override Point ScrollToControl(Control activeControl) - { - // Returning the current location prevents the panel from - // scrolling to the active control when the panel loses and regains focus - return DisplayRectangle.Location; - } - - /// - /// Add horizontal scrolling to the panel, when using the wheel and the shift key is pressed - /// - /// MouseEventArgs - protected override void OnMouseWheel(MouseEventArgs e) - { - if (VScroll && (ModifierKeys & Keys.Shift) == Keys.Shift) - { - VScroll = false; - base.OnMouseWheel(e); - VScroll = true; - } - else - { - base.OnMouseWheel(e); - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/Pipette.cs b/Greenshot.ImageEditor/Controls/Pipette.cs deleted file mode 100644 index 5e530eb55..000000000 --- a/Greenshot.ImageEditor/Controls/Pipette.cs +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Forms; -using GreenshotPlugin.UnmanagedHelpers; -using System; -using System.ComponentModel; -using System.Drawing; -using System.Windows.Forms; - -namespace Greenshot.Controls -{ - /// - /// This code was supplied by Hi-Coder as a patch for Greenshot - /// Needed some modifications to be stable. - /// - internal class Pipette : Label, IMessageFilter, IDisposable - { - private MovableShowColorForm movableShowColorForm; - private bool dragging; - private Cursor _cursor; - private readonly Bitmap _image; - private const int VK_ESC = 27; - - public event EventHandler PipetteUsed; - - public Pipette() - { - BorderStyle = BorderStyle.FixedSingle; - dragging = false; - _image = (Bitmap)new ComponentResourceManager(typeof(ColorDialog)).GetObject("pipette.Image"); - Image = _image; - _cursor = CreateCursor((Bitmap)_image, 1, 14); - movableShowColorForm = new MovableShowColorForm(); - Application.AddMessageFilter(this); - } - - /// - /// Create a cursor from the supplied bitmap & hotspot coordinates - /// - /// Bitmap to create an icon from - /// Hotspot X coordinate - /// Hotspot Y coordinate - /// Cursor - private static Cursor CreateCursor(Bitmap bitmap, int hotspotX, int hotspotY) - { - using (SafeIconHandle iconHandle = new SafeIconHandle(bitmap.GetHicon())) - { - IntPtr icon; - IconInfo iconInfo = new IconInfo(); - User32.GetIconInfo(iconHandle, out iconInfo); - iconInfo.xHotspot = hotspotX; - iconInfo.yHotspot = hotspotY; - iconInfo.fIcon = false; - icon = User32.CreateIconIndirect(ref iconInfo); - return new Cursor(icon); - } - } - - /// - /// The bulk of the clean-up code is implemented in Dispose(bool) - /// - public new void Dispose() - { - Dispose(true); - } - - /// - /// This Dispose is called from the Dispose and the Destructor. - /// - /// When disposing==true all non-managed resources should be freed too! - protected override void Dispose(bool disposing) - { - if (disposing) - { - if (_cursor != null) - { - _cursor.Dispose(); - } - if (movableShowColorForm != null) - { - movableShowColorForm.Dispose(); - } - } - movableShowColorForm = null; - _cursor = null; - base.Dispose(disposing); - } - - /// - /// Handle the mouse down on the Pipette "label", we take the capture and move the zoomer to the current location - /// - /// MouseEventArgs - protected override void OnMouseDown(MouseEventArgs e) - { - if (e.Button == MouseButtons.Left) - { - User32.SetCapture(Handle); - movableShowColorForm.MoveTo(PointToScreen(new Point(e.X, e.Y))); - } - base.OnMouseDown(e); - } - - /// - /// Handle the mouse up on the Pipette "label", we release the capture and fire the PipetteUsed event - /// - /// MouseEventArgs - protected override void OnMouseUp(MouseEventArgs e) - { - if (e.Button == MouseButtons.Left) - { - //Release Capture should consume MouseUp when canceled with the escape key - User32.ReleaseCapture(); - if (PipetteUsed != null) - { - PipetteUsed(this, new PipetteUsedArgs(movableShowColorForm.color)); - } - } - base.OnMouseUp(e); - } - - /// - /// Handle the mouse Move event, we move the ColorUnderCursor to the current location. - /// - /// MouseEventArgs - protected override void OnMouseMove(MouseEventArgs e) - { - if (dragging) - { - //display the form on the right side of the cursor by default; - Point zp = PointToScreen(new Point(e.X, e.Y)); - movableShowColorForm.MoveTo(zp); - } - base.OnMouseMove(e); - } - - /// - /// Handle the MouseCaptureChanged event - /// - /// - protected override void OnMouseCaptureChanged(EventArgs e) - { - if (Capture) - { - dragging = true; - Image = null; - Cursor c = _cursor; - Cursor = c; - movableShowColorForm.Visible = true; - } - else - { - dragging = false; - Image = _image; - Cursor = Cursors.Arrow; - movableShowColorForm.Visible = false; - } - Update(); - base.OnMouseCaptureChanged(e); - } - - #region IMessageFilter Members - - public bool PreFilterMessage(ref Message m) - { - if (dragging) - { - if (m.Msg == (int)WindowsMessages.WM_CHAR) - { - if ((int)m.WParam == VK_ESC) - { - User32.ReleaseCapture(); - } - } - } - return false; - } - - #endregion IMessageFilter Members - } - - public class PipetteUsedArgs : EventArgs - { - public Color color; - - public PipetteUsedArgs(Color c) - { - color = c; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/PleaseWaitForm.cs b/Greenshot.ImageEditor/Controls/PleaseWaitForm.cs deleted file mode 100644 index ac168d48f..000000000 --- a/Greenshot.ImageEditor/Controls/PleaseWaitForm.cs +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using GreenshotPlugin.Core; -using System; -using System.Threading; -using System.Windows.Forms; - -namespace GreenshotPlugin.Controls -{ - /// - /// Description of PleaseWaitForm. - /// - internal partial class PleaseWaitForm : Form - { - private Thread waitFor; - private string title; - - public PleaseWaitForm() - { - // - // The InitializeComponent() call is required for Windows Forms designer support. - // - InitializeComponent(); - Icon = GreenshotResources.getGreenshotIcon(); - } - - /// - /// Prevent the close-window button showing - /// - private const int CP_NOCLOSE_BUTTON = 0x200; - protected override CreateParams CreateParams - { - get - { - CreateParams createParams = base.CreateParams; - createParams.ClassStyle = createParams.ClassStyle | CP_NOCLOSE_BUTTON; - return createParams; - } - } - - /// - /// Show the "please wait" form, execute the code from the delegate and wait until execution finishes. - /// The supplied delegate will be wrapped with a try/catch so this method can return any exception that was thrown. - /// - /// The title of the form (and Thread) - /// The text in the form - /// delegate { with your code } - public void ShowAndWait(string title, string text, ThreadStart waitDelegate) - { - this.title = title; - Text = title; - label_pleasewait.Text = text; - cancelButton.Text = "Cancel"; - - // Make sure the form is shown. - Show(); - - // Variable to store the exception, if one is generated, from inside the thread. - Exception threadException = null; - try - { - // Wrap the passed delegate in a try/catch which makes it possible to save the exception - waitFor = new Thread(new ThreadStart( - delegate - { - try - { - waitDelegate.Invoke(); - } - catch (Exception ex) - { - LOG.Error("invoke error:", ex); - threadException = ex; - } - }) - ); - waitFor.Name = title; - waitFor.IsBackground = true; - waitFor.SetApartmentState(ApartmentState.STA); - waitFor.Start(); - - // Wait until finished - while (!waitFor.Join(TimeSpan.FromMilliseconds(100))) - { - Application.DoEvents(); - } - LOG.DebugFormat("Finished {0}", title); - } - catch (Exception ex) - { - LOG.Error(ex); - throw; - } - finally - { - Close(); - } - // Check if an exception occured, if so throw it - if (threadException != null) - { - throw threadException; - } - } - - /// - /// Called if the cancel button is clicked, will use Thread.Abort() - /// - /// - /// - private void CancelButtonClick(object sender, EventArgs e) - { - LOG.DebugFormat("Cancel clicked on {0}", title); - cancelButton.Enabled = false; - waitFor.Abort(); - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/PleaseWaitForm.designer.cs b/Greenshot.ImageEditor/Controls/PleaseWaitForm.designer.cs deleted file mode 100644 index 7a922387b..000000000 --- a/Greenshot.ImageEditor/Controls/PleaseWaitForm.designer.cs +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ -namespace GreenshotPlugin.Controls -{ - partial class PleaseWaitForm - { - /// - /// Designer variable used to keep track of non-visual components. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Disposes resources used by the form. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing) - { - if (components != null) - { - components.Dispose(); - } - } - base.Dispose(disposing); - } - - /// - /// This method is required for Windows Forms designer support. - /// Do not change the method contents inside the source code editor. The Forms designer might - /// not be able to load this method if it was changed manually. - /// - private void InitializeComponent() - { - this.label_pleasewait = new System.Windows.Forms.Label(); - this.cancelButton = new System.Windows.Forms.Button(); - this.SuspendLayout(); - // - // label_pleasewait - // - this.label_pleasewait.AutoSize = true; - this.label_pleasewait.Dock = System.Windows.Forms.DockStyle.Fill; - this.label_pleasewait.Location = new System.Drawing.Point(0, 0); - this.label_pleasewait.Name = "label_pleasewait"; - this.label_pleasewait.Padding = new System.Windows.Forms.Padding(10); - this.label_pleasewait.Size = new System.Drawing.Size(90, 33); - this.label_pleasewait.TabIndex = 0; - this.label_pleasewait.Text = "Please wait..."; - this.label_pleasewait.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.label_pleasewait.UseWaitCursor = true; - // - // cancelButton - // - this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.cancelButton.Location = new System.Drawing.Point(38, 41); - this.cancelButton.Name = "cancelButton"; - this.cancelButton.Size = new System.Drawing.Size(94, 23); - this.cancelButton.TabIndex = 1; - this.cancelButton.Text = "Cancel"; - this.cancelButton.UseVisualStyleBackColor = true; - this.cancelButton.UseWaitCursor = true; - this.cancelButton.Click += new System.EventHandler(this.CancelButtonClick); - // - // PleaseWaitForm - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.AutoSize = true; - this.CancelButton = this.cancelButton; - this.ClientSize = new System.Drawing.Size(169, 76); - this.Controls.Add(this.cancelButton); - this.Controls.Add(this.label_pleasewait); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "PleaseWaitForm"; - this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; - this.Text = "Greenshot"; - this.UseWaitCursor = true; - this.ResumeLayout(false); - this.PerformLayout(); - } - private System.Windows.Forms.Button cancelButton; - private System.Windows.Forms.Label label_pleasewait; - } -} diff --git a/Greenshot.ImageEditor/Controls/QualityDialog.cs b/Greenshot.ImageEditor/Controls/QualityDialog.cs deleted file mode 100644 index 218f878bb..000000000 --- a/Greenshot.ImageEditor/Controls/QualityDialog.cs +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.IniFile; -using Greenshot.Plugin; -using GreenshotPlugin.Core; -using System; - -namespace GreenshotPlugin.Controls -{ - /// - /// Description of JpegQualityDialog. - /// - internal partial class QualityDialog : GreenshotForm - { - private static readonly CoreConfiguration conf = IniConfig.GetIniSection(); - public SurfaceOutputSettings Settings - { - get; - set; - } - - public QualityDialog(SurfaceOutputSettings outputSettings) - { - Settings = outputSettings; - // - // The InitializeComponent() call is required for Windows Forms designer support. - // - InitializeComponent(); - - checkBox_reduceColors.Checked = Settings.ReduceColors; - trackBarJpegQuality.Enabled = OutputFormat.jpg.Equals(outputSettings.Format); - trackBarJpegQuality.Value = Settings.JPGQuality; - textBoxJpegQuality.Enabled = OutputFormat.jpg.Equals(outputSettings.Format); - textBoxJpegQuality.Text = Settings.JPGQuality.ToString(); - ToFront = true; - } - - private void Button_okClick(object sender, EventArgs e) - { - Settings.JPGQuality = trackBarJpegQuality.Value; - Settings.ReduceColors = checkBox_reduceColors.Checked; - if (checkbox_dontaskagain.Checked) - { - conf.OutputFileJpegQuality = Settings.JPGQuality; - conf.OutputFilePromptQuality = false; - conf.OutputFileReduceColors = Settings.ReduceColors; - IniConfig.Save(); - } - } - - private void TrackBarJpegQualityScroll(object sender, EventArgs e) - { - textBoxJpegQuality.Text = trackBarJpegQuality.Value.ToString(); - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/QualityDialog.designer.cs b/Greenshot.ImageEditor/Controls/QualityDialog.designer.cs deleted file mode 100644 index 0893caacb..000000000 --- a/Greenshot.ImageEditor/Controls/QualityDialog.designer.cs +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ -namespace GreenshotPlugin.Controls -{ - partial class QualityDialog - { - /// - /// Designer variable used to keep track of non-visual components. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Disposes resources used by the form. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing) - { - if (components != null) - { - components.Dispose(); - } - } - base.Dispose(disposing); - } - - /// - /// This method is required for Windows Forms designer support. - /// Do not change the method contents inside the source code editor. The Forms designer might - /// not be able to load this method if it was changed manually. - /// - private void InitializeComponent() - { - this.label_choosejpegquality = new GreenshotPlugin.Controls.GreenshotLabel(); - this.textBoxJpegQuality = new System.Windows.Forms.TextBox(); - this.trackBarJpegQuality = new System.Windows.Forms.TrackBar(); - this.checkbox_dontaskagain = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.button_ok = new GreenshotPlugin.Controls.GreenshotButton(); - this.checkBox_reduceColors = new System.Windows.Forms.CheckBox(); - ((System.ComponentModel.ISupportInitialize)(this.trackBarJpegQuality)).BeginInit(); - this.SuspendLayout(); - // - // label_choosejpegquality - // - this.label_choosejpegquality.Location = new System.Drawing.Point(12, 47); - this.label_choosejpegquality.Name = "label_choosejpegquality"; - this.label_choosejpegquality.Size = new System.Drawing.Size(268, 19); - this.label_choosejpegquality.TabIndex = 15; - this.label_choosejpegquality.LanguageKey = "jpegqualitydialog_choosejpegquality"; - // - // textBoxJpegQuality - // - this.textBoxJpegQuality.Location = new System.Drawing.Point(245, 69); - this.textBoxJpegQuality.Name = "textBoxJpegQuality"; - this.textBoxJpegQuality.ReadOnly = true; - this.textBoxJpegQuality.Size = new System.Drawing.Size(35, 20); - this.textBoxJpegQuality.TabIndex = 16; - this.textBoxJpegQuality.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; - // - // trackBarJpegQuality - // - this.trackBarJpegQuality.LargeChange = 10; - this.trackBarJpegQuality.Location = new System.Drawing.Point(12, 69); - this.trackBarJpegQuality.Maximum = 100; - this.trackBarJpegQuality.Name = "trackBarJpegQuality"; - this.trackBarJpegQuality.Size = new System.Drawing.Size(233, 45); - this.trackBarJpegQuality.TabIndex = 14; - this.trackBarJpegQuality.TickFrequency = 10; - this.trackBarJpegQuality.Scroll += new System.EventHandler(this.TrackBarJpegQualityScroll); - // - // checkbox_dontaskagain - // - this.checkbox_dontaskagain.CheckAlign = System.Drawing.ContentAlignment.TopLeft; - this.checkbox_dontaskagain.ImageAlign = System.Drawing.ContentAlignment.TopLeft; - this.checkbox_dontaskagain.Location = new System.Drawing.Point(12, 106); - this.checkbox_dontaskagain.Name = "checkbox_dontaskagain"; - this.checkbox_dontaskagain.LanguageKey = "qualitydialog_dontaskagain"; - this.checkbox_dontaskagain.Size = new System.Drawing.Size(268, 37); - this.checkbox_dontaskagain.TabIndex = 17; - this.checkbox_dontaskagain.TextAlign = System.Drawing.ContentAlignment.TopLeft; - this.checkbox_dontaskagain.UseVisualStyleBackColor = true; - // - // button_ok - // - this.button_ok.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.button_ok.Location = new System.Drawing.Point(205, 149); - this.button_ok.Name = "button_ok"; - this.button_ok.Size = new System.Drawing.Size(75, 23); - this.button_ok.TabIndex = 18; - this.button_ok.LanguageKey = "OK"; - this.button_ok.UseVisualStyleBackColor = true; - this.button_ok.Click += new System.EventHandler(this.Button_okClick); - // - // checkBox_reduceColors - // - this.checkBox_reduceColors.AutoSize = true; - this.checkBox_reduceColors.Location = new System.Drawing.Point(12, 11); - this.checkBox_reduceColors.Name = "checkBox_reduceColors"; - this.checkBox_reduceColors.Size = new System.Drawing.Size(95, 17); - this.checkBox_reduceColors.TabIndex = 19; - this.checkBox_reduceColors.Text = "settings_reducecolors"; - this.checkBox_reduceColors.UseVisualStyleBackColor = true; - // - // QualityDialog - // - this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; - this.ClientSize = new System.Drawing.Size(299, 184); - this.ControlBox = false; - this.Controls.Add(this.checkBox_reduceColors); - this.Controls.Add(this.button_ok); - this.Controls.Add(this.checkbox_dontaskagain); - this.Controls.Add(this.label_choosejpegquality); - this.Controls.Add(this.textBoxJpegQuality); - this.Controls.Add(this.trackBarJpegQuality); - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "QualityDialog"; - this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; - this.LanguageKey = "qualitydialog_title"; - ((System.ComponentModel.ISupportInitialize)(this.trackBarJpegQuality)).EndInit(); - this.ResumeLayout(false); - this.PerformLayout(); - - } - private GreenshotPlugin.Controls.GreenshotButton button_ok; - private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_dontaskagain; - private System.Windows.Forms.TrackBar trackBarJpegQuality; - private System.Windows.Forms.TextBox textBoxJpegQuality; - private GreenshotPlugin.Controls.GreenshotLabel label_choosejpegquality; - private System.Windows.Forms.CheckBox checkBox_reduceColors; - } -} diff --git a/Greenshot.ImageEditor/Controls/SaveImageFileDialog.cs b/Greenshot.ImageEditor/Controls/SaveImageFileDialog.cs deleted file mode 100644 index a20670b07..000000000 --- a/Greenshot.ImageEditor/Controls/SaveImageFileDialog.cs +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.IniFile; -using Greenshot.Plugin; -using GreenshotPlugin.Core; -using System; -using System.IO; -using System.Windows.Forms; - -namespace GreenshotPlugin.Controls -{ - /// - /// Custom dialog for saving images, wraps SaveFileDialog. - /// For some reason SFD is sealed :( - /// - internal class SaveImageFileDialog : IDisposable - { - private static readonly CoreConfiguration conf = IniConfig.GetIniSection(); - protected SaveFileDialog SaveFileDialog; - private FilterOption[] _filterOptions; - private DirectoryInfo _eagerlyCreatedDirectory; - private readonly ICaptureDetails _captureDetails = null; - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - if (SaveFileDialog != null) - { - SaveFileDialog.Dispose(); - SaveFileDialog = null; - } - } - } - - public SaveImageFileDialog() - { - Init(); - } - - public SaveImageFileDialog(ICaptureDetails captureDetails) - { - _captureDetails = captureDetails; - Init(); - } - - private void Init() - { - SaveFileDialog = new SaveFileDialog(); - ApplyFilterOptions(); - string initialDirectory = null; - try - { - initialDirectory = Path.GetDirectoryName(conf.OutputFileAsFullpath); - } - catch - { - LOG.WarnFormat("OutputFileAsFullpath was set to {0}, ignoring due to problem in path.", conf.OutputFileAsFullpath); - } - - if (!string.IsNullOrEmpty(initialDirectory) && Directory.Exists(initialDirectory)) - { - SaveFileDialog.InitialDirectory = initialDirectory; - } - else if (Directory.Exists(conf.OutputFilePath)) - { - SaveFileDialog.InitialDirectory = conf.OutputFilePath; - } - // The following property fixes a problem that the directory where we save is locked (bug #2899790) - SaveFileDialog.RestoreDirectory = true; - SaveFileDialog.OverwritePrompt = true; - SaveFileDialog.CheckPathExists = false; - SaveFileDialog.AddExtension = true; - ApplySuggestedValues(); - } - - private void ApplyFilterOptions() - { - PrepareFilterOptions(); - string fdf = ""; - int preselect = 0; - var outputFileFormatAsString = Enum.GetName(typeof(OutputFormat), conf.OutputFileFormat); - for (int i = 0; i < _filterOptions.Length; i++) - { - FilterOption fo = _filterOptions[i]; - fdf += fo.Label + "|*." + fo.Extension + "|"; - if (outputFileFormatAsString == fo.Extension) - preselect = i; - } - fdf = fdf.Substring(0, fdf.Length - 1); - SaveFileDialog.Filter = fdf; - SaveFileDialog.FilterIndex = preselect + 1; - } - - private void PrepareFilterOptions() - { - OutputFormat[] supportedImageFormats = (OutputFormat[])Enum.GetValues(typeof(OutputFormat)); - _filterOptions = new FilterOption[supportedImageFormats.Length]; - for (int i = 0; i < _filterOptions.Length; i++) - { - string ifo = supportedImageFormats[i].ToString(); - if (ifo.ToLower().Equals("jpeg")) ifo = "Jpg"; // we dont want no jpeg files, so let the dialog check for jpg - FilterOption fo = new FilterOption - { - Label = ifo.ToUpper(), - Extension = ifo.ToLower() - }; - _filterOptions.SetValue(fo, i); - } - } - - /// - /// filename exactly as typed in the filename field - /// - public string FileName - { - get { return SaveFileDialog.FileName; } - set { SaveFileDialog.FileName = value; } - } - - /// - /// initial directory of the dialog - /// - public string InitialDirectory - { - get { return SaveFileDialog.InitialDirectory; } - set { SaveFileDialog.InitialDirectory = value; } - } - - /// - /// returns filename as typed in the filename field with extension. - /// if filename field value ends with selected extension, the value is just returned. - /// otherwise, the selected extension is appended to the filename. - /// - public string FileNameWithExtension - { - get - { - string fn = SaveFileDialog.FileName; - // if the filename contains a valid extension, which is the same like the selected filter item's extension, the filename is okay - if (fn.EndsWith(Extension, StringComparison.CurrentCultureIgnoreCase)) return fn; - // otherwise we just add the selected filter item's extension - else return fn + "." + Extension; - } - set - { - FileName = Path.GetFileNameWithoutExtension(value); - Extension = Path.GetExtension(value); - } - } - - /// - /// gets or sets selected extension - /// - public string Extension - { - get - { - return _filterOptions[SaveFileDialog.FilterIndex - 1].Extension; - } - set - { - for (int i = 0; i < _filterOptions.Length; i++) - { - if (value.Equals(_filterOptions[i].Extension, StringComparison.CurrentCultureIgnoreCase)) - { - SaveFileDialog.FilterIndex = i + 1; - } - } - } - } - - public DialogResult ShowDialog() - { - DialogResult ret = SaveFileDialog.ShowDialog(); - CleanUp(); - return ret; - } - - /// - /// sets InitialDirectory and FileName property of a SaveFileDialog smartly, considering default pattern and last used path - /// - private void ApplySuggestedValues() - { - // build the full path and set dialog properties - FileName = FilenameHelper.GetFilenameWithoutExtensionFromPattern(conf.OutputFileFilenamePattern, _captureDetails); - } - - private class FilterOption - { - public string Label; - public string Extension; - } - - private void CleanUp() - { - // fix for bug #3379053 - try - { - if (_eagerlyCreatedDirectory != null && _eagerlyCreatedDirectory.GetFiles().Length == 0 && _eagerlyCreatedDirectory.GetDirectories().Length == 0) - { - _eagerlyCreatedDirectory.Delete(); - _eagerlyCreatedDirectory = null; - } - } - catch (Exception e) - { - LOG.WarnFormat("Couldn't cleanup directory due to: {0}", e.Message); - _eagerlyCreatedDirectory = null; - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/ToolStripColorButton.cs b/Greenshot.ImageEditor/Controls/ToolStripColorButton.cs deleted file mode 100644 index 7e18230d7..000000000 --- a/Greenshot.ImageEditor/Controls/ToolStripColorButton.cs +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using GreenshotPlugin.Controls; -using System; -using System.ComponentModel; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Windows.Forms; - -namespace Greenshot.Controls -{ - internal class ToolStripColorButton : ToolStripButton, INotifyPropertyChanged, IGreenshotLanguageBindable - { - public event PropertyChangedEventHandler PropertyChanged; - - [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] - public string LanguageKey - { - get; - set; - } - - private Color selectedColor = Color.Transparent; - - public ToolStripColorButton() - { - Click += ColorButtonClick; - } - - public Color SelectedColor - { - get - { - return selectedColor; - } - set - { - selectedColor = value; - - Brush brush; - if (value != Color.Transparent) - { - brush = new SolidBrush(value); - } - else - { - brush = new HatchBrush(HatchStyle.Percent50, Color.White, Color.Gray); - } - - if (Image != null) - { - using (Graphics graphics = Graphics.FromImage(Image)) - { - graphics.FillRectangle(brush, new Rectangle(0, 13, 16, 3)); - } - } - - // cleanup GDI Object - brush.Dispose(); - Invalidate(); - } - } - - private void ColorButtonClick(object sender, EventArgs e) - { - ColorDialog colorDialog = ColorDialog.GetInstance(); - colorDialog.Color = SelectedColor; - // Using the parent to make sure the dialog doesn't show on another window - colorDialog.ShowDialog(Parent.Parent); - if (colorDialog.DialogResult != DialogResult.Cancel) - { - if (!colorDialog.Color.Equals(SelectedColor)) - { - SelectedColor = colorDialog.Color; - if (PropertyChanged != null) - { - PropertyChanged(this, new PropertyChangedEventArgs("SelectedColor")); - } - } - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/ToolStripEx.cs b/Greenshot.ImageEditor/Controls/ToolStripEx.cs deleted file mode 100644 index ffd6f39fa..000000000 --- a/Greenshot.ImageEditor/Controls/ToolStripEx.cs +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System; -using System.Windows.Forms; - -namespace Greenshot.Controls -{ - /// - /// This is an extension of the default ToolStrip and allows us to click it even when the form doesn't have focus. - /// See: http://blogs.msdn.com/b/rickbrew/archive/2006/01/09/511003.aspx - /// - internal class ToolStripEx : ToolStrip - { - private const int WM_MOUSEACTIVATE = 0x21; - - private enum NativeConstants : uint - { - MA_ACTIVATE = 1, - MA_ACTIVATEANDEAT = 2, - } - - private bool _clickThrough = false; - /// - /// Gets or sets whether the ToolStripEx honors item clicks when its containing form does not have input focus. - /// - /// - /// Default value is false, which is the same behavior provided by the base ToolStrip class. - /// - - public bool ClickThrough - { - get - { - return _clickThrough; - } - - set - { - _clickThrough = value; - } - } - - protected override void WndProc(ref Message m) - { - base.WndProc(ref m); - if (_clickThrough && m.Msg == WM_MOUSEACTIVATE && m.Result == (IntPtr)NativeConstants.MA_ACTIVATEANDEAT) - { - m.Result = (IntPtr)NativeConstants.MA_ACTIVATE; - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Controls/ToolStripNumericUpDown.cs b/Greenshot.ImageEditor/Controls/ToolStripNumericUpDown.cs deleted file mode 100644 index 2954f3f4d..000000000 --- a/Greenshot.ImageEditor/Controls/ToolStripNumericUpDown.cs +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System; -using System.ComponentModel; -using System.Windows.Forms; -using System.Windows.Forms.Design; - -namespace Greenshot.Controls -{ - [ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.ToolStrip | ToolStripItemDesignerAvailability.StatusStrip)] - internal class ToolStripNumericUpDown : ToolStripControlHost, INotifyPropertyChanged - { - public event PropertyChangedEventHandler PropertyChanged; - - public ToolStripNumericUpDown() : base(new NumericUpDown()) - { - } - - public NumericUpDown NumericUpDown - { - get { return Control as NumericUpDown; } - } - - public decimal Value - { - get { return NumericUpDown.Value; } - set { NumericUpDown.Value = value; } - } - public decimal Minimum - { - get { return NumericUpDown.Minimum; } - set { NumericUpDown.Minimum = value; } - } - - public decimal Maximum - { - get { return NumericUpDown.Maximum; } - set { NumericUpDown.Maximum = value; } - } - - public decimal Increment - { - get { return NumericUpDown.Increment; } - set { NumericUpDown.Increment = value; } - } - - public int DecimalPlaces - { - get { return NumericUpDown.DecimalPlaces; } - set { NumericUpDown.DecimalPlaces = value; } - } - - protected override void OnSubscribeControlEvents(Control control) - { - base.OnSubscribeControlEvents(control); - NumericUpDown.ValueChanged += _valueChanged; - } - - protected override void OnUnsubscribeControlEvents(Control control) - { - base.OnUnsubscribeControlEvents(control); - NumericUpDown.ValueChanged -= _valueChanged; - } - - private void _valueChanged(object sender, EventArgs e) - { - if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Value")); - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Core/BinaryStructHelper.cs b/Greenshot.ImageEditor/Core/BinaryStructHelper.cs deleted file mode 100644 index 5668ce285..000000000 --- a/Greenshot.ImageEditor/Core/BinaryStructHelper.cs +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System; -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.Core -{ - /// - /// A helper class which does the mashalling for structs - /// - public static class BinaryStructHelper - { - /// - /// Get a struct from a byte array - /// - /// typeof struct - /// byte[] - /// struct - public static T FromByteArray(byte[] bytes) where T : struct - { - IntPtr ptr = IntPtr.Zero; - try - { - int size = Marshal.SizeOf(typeof(T)); - ptr = Marshal.AllocHGlobal(size); - Marshal.Copy(bytes, 0, ptr, size); - return FromIntPtr(ptr); - } - finally - { - if (ptr != IntPtr.Zero) - { - Marshal.FreeHGlobal(ptr); - } - } - } - - /// - /// Get a struct from a byte array - /// - /// typeof struct - /// byte[] - /// struct - public static T FromIntPtr(IntPtr intPtr) where T : struct - { - object obj = Marshal.PtrToStructure(intPtr, typeof(T)); - return (T)obj; - } - - /// - /// copy a struct to a byte array - /// - /// typeof struct - /// struct - /// byte[] - public static byte[] ToByteArray(T obj) where T : struct - { - IntPtr ptr = IntPtr.Zero; - try - { - int size = Marshal.SizeOf(typeof(T)); - ptr = Marshal.AllocHGlobal(size); - Marshal.StructureToPtr(obj, ptr, true); - return FromPtrToByteArray(ptr); - } - finally - { - if (ptr != IntPtr.Zero) - { - Marshal.FreeHGlobal(ptr); - } - } - } - - /// - /// copy a struct from a pointer to a byte array - /// - /// typeof struct - /// IntPtr to struct - /// byte[] - public static byte[] FromPtrToByteArray(IntPtr ptr) where T : struct - { - int size = Marshal.SizeOf(typeof(T)); - byte[] bytes = new byte[size]; - Marshal.Copy(ptr, bytes, 0, size); - return bytes; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Core/Cache.cs b/Greenshot.ImageEditor/Core/Cache.cs deleted file mode 100644 index 413ed9a4f..000000000 --- a/Greenshot.ImageEditor/Core/Cache.cs +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System; -using System.Collections.Generic; -using System.Timers; - -namespace GreenshotPlugin.Core -{ - /// - /// Cache class - /// - /// Type of key - /// Type of value - public class Cache - { - private readonly IDictionary internalCache = new Dictionary(); - private readonly object lockObject = new object(); - private readonly int secondsToExpire = 10; - private readonly CacheObjectExpired expiredCallback = null; - public delegate void CacheObjectExpired(TK key, TV cacheValue); - - /// - /// Initialize the cache - /// - public Cache() - { - } - - /// - /// Initialize the cache - /// - /// - public Cache(CacheObjectExpired expiredCallback) : this() - { - this.expiredCallback = expiredCallback; - } - - /// - /// Initialize the cache with a expire setting - /// - /// - public Cache(int secondsToExpire) : this() - { - this.secondsToExpire = secondsToExpire; - } - - /// - /// Initialize the cache with a expire setting - /// - /// - /// - public Cache(int secondsToExpire, CacheObjectExpired expiredCallback) : this(expiredCallback) - { - this.secondsToExpire = secondsToExpire; - } - - /// - /// Enumerable for the values in the cache - /// - public IEnumerable Elements - { - get - { - List elements = new List(); - - lock (lockObject) - { - foreach (TV element in internalCache.Values) - { - elements.Add(element); - } - } - foreach (TV element in elements) - { - yield return element; - } - } - } - - /// - /// Get the value by key from the cache - /// - /// - /// - public TV this[TK key] - { - get - { - TV result = default(TV); - lock (lockObject) - { - if (internalCache.ContainsKey(key)) - { - result = internalCache[key]; - } - } - return result; - } - } - - /// - /// Contains - /// - /// - /// true if the cache contains the key - public bool Contains(TK key) - { - lock (lockObject) - { - return internalCache.ContainsKey(key); - } - } - - /// - /// Add a value to the cache - /// - /// - /// - public void Add(TK key, TV value) - { - Add(key, value, null); - } - - /// - /// Add a value to the cache - /// - /// - /// - /// optional value for the seconds to expire - public void Add(TK key, TV value, int? secondsToExpire) - { - lock (lockObject) - { - var cachedItem = new CachedItem(key, value, secondsToExpire.HasValue ? secondsToExpire.Value : this.secondsToExpire); - cachedItem.Expired += delegate (TK cacheKey, TV cacheValue) - { - if (internalCache.ContainsKey(cacheKey)) - { - LOG.DebugFormat("Expiring object with Key: {0}", cacheKey); - if (expiredCallback != null) - { - expiredCallback(cacheKey, cacheValue); - } - Remove(cacheKey); - } - else - { - LOG.DebugFormat("Expired old object with Key: {0}", cacheKey); - } - }; - - if (internalCache.ContainsKey(key)) - { - internalCache[key] = value; - LOG.DebugFormat("Updated item with Key: {0}", key); - } - else - { - internalCache.Add(key, cachedItem); - LOG.DebugFormat("Added item with Key: {0}", key); - } - } - } - - /// - /// Remove item from cache - /// - /// - public void Remove(TK key) - { - lock (lockObject) - { - if (!internalCache.ContainsKey(key)) - { - throw new ApplicationException(String.Format("An object with key ‘{0}’ does not exists in cache", key)); - } - internalCache.Remove(key); - LOG.DebugFormat("Removed item with Key: {0}", key); - } - } - - /// - /// A cache item - /// - private class CachedItem - { - public event CacheObjectExpired Expired; - private readonly int secondsToExpire; - private readonly Timer _timerEvent; - - public CachedItem(TK key, TV item, int secondsToExpire) - { - if (key == null) - { - throw new ArgumentNullException("key is not valid"); - } - Key = key; - Item = item; - this.secondsToExpire = secondsToExpire; - if (secondsToExpire > 0) - { - _timerEvent = new Timer(secondsToExpire * 1000) { AutoReset = false }; - _timerEvent.Elapsed += timerEvent_Elapsed; - _timerEvent.Start(); - } - } - - private void ExpireNow() - { - _timerEvent.Stop(); - if (secondsToExpire > 0 && Expired != null) - { - Expired(Key, Item); - } - } - - private void timerEvent_Elapsed(object sender, ElapsedEventArgs e) - { - ExpireNow(); - } - - public TK Key { get; private set; } - public TV Item { get; private set; } - - public static implicit operator TV(CachedItem a) - { - return a.Item; - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Core/CaptureHandler.cs b/Greenshot.ImageEditor/Core/CaptureHandler.cs deleted file mode 100644 index e490f6a21..000000000 --- a/Greenshot.ImageEditor/Core/CaptureHandler.cs +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System.Drawing; - -namespace GreenshotPlugin.Core -{ - /// - /// This is the method signature which is used to capture a rectangle from the screen. - /// - /// - /// Captured Bitmap - public delegate Bitmap CaptureScreenRectangleHandler(Rectangle captureBounds); - - /// - /// This is a hack to experiment with different screen capture routines - /// - public static class CaptureHandler - { - /// - /// By changing this value, null is default - /// - public static CaptureScreenRectangleHandler CaptureScreenRectangle - { - get; - set; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Core/ClipboardHelper.cs b/Greenshot.ImageEditor/Core/ClipboardHelper.cs deleted file mode 100644 index dfe33f6b1..000000000 --- a/Greenshot.ImageEditor/Core/ClipboardHelper.cs +++ /dev/null @@ -1,1006 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.IniFile; -using Greenshot.Plugin; -using GreenshotPlugin.UnmanagedHelpers; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Drawing; -using System.Drawing.Imaging; -using System.IO; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading; -using System.Windows.Forms; - -namespace GreenshotPlugin.Core -{ - /// - /// Description of ClipboardHelper. - /// - public static class ClipboardHelper - { - private static readonly Object clipboardLockObject = new Object(); - private static readonly CoreConfiguration config = IniConfig.GetIniSection(); - private static readonly string FORMAT_FILECONTENTS = "FileContents"; - private static readonly string FORMAT_PNG = "PNG"; - private static readonly string FORMAT_PNG_OFFICEART = "PNG+Office Art"; - private static readonly string FORMAT_17 = "Format17"; - private static readonly string FORMAT_JPG = "JPG"; - private static readonly string FORMAT_JFIF = "JFIF"; - private static readonly string FORMAT_JFIF_OFFICEART = "JFIF+Office Art"; - private static readonly string FORMAT_GIF = "GIF"; - private static readonly string FORMAT_BITMAP = "System.Drawing.Bitmap"; - //private static readonly string FORMAT_HTML = "HTML Format"; - - private static IntPtr nextClipboardViewer = IntPtr.Zero; - // Template for the HTML Text on the clipboard - // see: http://msdn.microsoft.com/en-us/library/ms649015%28v=vs.85%29.aspx - // or: http://msdn.microsoft.com/en-us/library/Aa767917.aspx - private const string HTML_CLIPBOARD_STRING = @"Version:0.9 -StartHTML:<<<<<<<1 -EndHTML:<<<<<<<2 -StartFragment:<<<<<<<3 -EndFragment:<<<<<<<4 -StartSelection:<<<<<<<3 -EndSelection:<<<<<<<4 - - - -Greenshot capture - - - - - - -"; - private const string HTML_CLIPBOARD_BASE64_STRING = @"Version:0.9 -StartHTML:<<<<<<<1 -EndHTML:<<<<<<<2 -StartFragment:<<<<<<<3 -EndFragment:<<<<<<<4 -StartSelection:<<<<<<<3 -EndSelection:<<<<<<<4 - - - -Greenshot capture - - - - - - -"; - - /// - /// Get the current "ClipboardOwner" but only if it isn't us! - /// - /// current clipboard owner - private static string GetClipboardOwner() - { - string owner = null; - try - { - IntPtr hWnd = User32.GetClipboardOwner(); - if (hWnd != IntPtr.Zero) - { - int pid; - User32.GetWindowThreadProcessId(hWnd, out pid); - using (Process me = Process.GetCurrentProcess()) - using (Process ownerProcess = Process.GetProcessById(pid)) - { - // Exclude myself - if (ownerProcess != null && me.Id != ownerProcess.Id) - { - // Get Process Name - owner = ownerProcess.ProcessName; - // Try to get the starting Process Filename, this might fail. - try - { - owner = ownerProcess.Modules[0].FileName; - } - catch (Exception) - { - } - } - } - } - } - catch (Exception e) - { - LOG.Warn("Non critical error: Couldn't get clipboard owner.", e); - } - return owner; - } - - /// - /// The SetDataObject will lock/try/catch clipboard operations making it save and not show exceptions. - /// The bool "copy" is used to decided if the information stays on the clipboard after exit. - /// - /// - /// - private static void SetDataObject(IDataObject ido, bool copy) - { - lock (clipboardLockObject) - { - int retryCount = 5; - while (retryCount >= 0) - { - try - { - Clipboard.SetDataObject(ido, copy); - break; - } - catch (Exception ee) - { - if (retryCount == 0) - { - string messageText = null; - string clipboardOwner = GetClipboardOwner(); - if (clipboardOwner != null) - { - messageText = string.Format("Greenshot wasn't able to write to the clipboard as the process {0} blocked the access.", clipboardOwner); - } - else - { - messageText = "An unexpected error occured while writing to the clipboard."; - } - LOG.Error(messageText, ee); - } - else - { - Thread.Sleep(100); - } - } - finally - { - --retryCount; - } - } - } - } - - /// - /// The GetDataObject will lock/try/catch clipboard operations making it save and not show exceptions. - /// - public static IDataObject GetDataObject() - { - lock (clipboardLockObject) - { - int retryCount = 2; - while (retryCount >= 0) - { - try - { - return Clipboard.GetDataObject(); - } - catch (Exception ee) - { - if (retryCount == 0) - { - string messageText = null; - string clipboardOwner = GetClipboardOwner(); - if (clipboardOwner != null) - { - messageText = string.Format("Greenshot wasn't able to write to the clipboard as the process {0} blocked the access.", clipboardOwner); - } - else - { - messageText = "An unexpected error occured while writing to the clipboard."; - } - LOG.Error(messageText, ee); - } - else - { - Thread.Sleep(100); - } - } - finally - { - --retryCount; - } - } - } - return null; - } - - /// - /// Wrapper for Clipboard.ContainsText, Created for Bug #3432313 - /// - /// boolean if there is text on the clipboard - public static bool ContainsText() - { - IDataObject clipboardData = GetDataObject(); - return ContainsText(clipboardData); - } - - /// - /// Test if the IDataObject contains Text - /// - /// - /// - public static bool ContainsText(IDataObject dataObject) - { - if (dataObject != null) - { - if (dataObject.GetDataPresent(DataFormats.Text) || dataObject.GetDataPresent(DataFormats.UnicodeText)) - { - return true; - } - } - return false; - } - - /// - /// Wrapper for Clipboard.ContainsImage, specialized for Greenshot, Created for Bug #3432313 - /// - /// boolean if there is an image on the clipboard - public static bool ContainsImage() - { - IDataObject clipboardData = GetDataObject(); - return ContainsImage(clipboardData); - } - - /// - /// Check if the IDataObject has an image - /// - /// - /// true if an image is there - public static bool ContainsImage(IDataObject dataObject) - { - if (dataObject != null) - { - if (dataObject.GetDataPresent(DataFormats.Bitmap) - || dataObject.GetDataPresent(DataFormats.Dib) - || dataObject.GetDataPresent(DataFormats.Tiff) - || dataObject.GetDataPresent(DataFormats.EnhancedMetafile) - || dataObject.GetDataPresent(FORMAT_PNG) - || dataObject.GetDataPresent(FORMAT_17) - || dataObject.GetDataPresent(FORMAT_JPG) - || dataObject.GetDataPresent(FORMAT_GIF)) - { - return true; - } - List imageFiles = GetImageFilenames(dataObject); - if (imageFiles != null && imageFiles.Count > 0) - { - return true; - } - if (dataObject.GetDataPresent(FORMAT_FILECONTENTS)) - { - try - { - MemoryStream imageStream = dataObject.GetData(FORMAT_FILECONTENTS) as MemoryStream; - if (isValidStream(imageStream)) - { - using (Image tmpImage = Image.FromStream(imageStream)) - { - // If we get here, there is an image - return true; - } - } - } - catch (Exception) - { - } - } - } - return false; - } - - /// - /// Simple helper to check the stream - /// - /// - /// - private static bool isValidStream(MemoryStream memoryStream) - { - return memoryStream != null && memoryStream.Length > 0; - } - - /// - /// Wrapper for Clipboard.GetImage, Created for Bug #3432313 - /// - /// Image if there is an image on the clipboard - public static Image GetImage() - { - IDataObject clipboardData = GetDataObject(); - // Return the first image - foreach (Image clipboardImage in GetImages(clipboardData)) - { - return clipboardImage; - } - return null; - } - - /// - /// Get all images (multiple if filenames are available) from the dataObject - /// Returned images must be disposed by the calling code! - /// - /// - /// IEnumerable - public static IEnumerable GetImages(IDataObject dataObject) - { - // Get single image, this takes the "best" match - Image singleImage = GetImage(dataObject); - if (singleImage != null) - { - LOG.InfoFormat("Got image from clipboard with size {0} and format {1}", singleImage.Size, singleImage.PixelFormat); - yield return singleImage; - } - else - { - // check if files are supplied - List imageFiles = GetImageFilenames(dataObject); - if (imageFiles != null) - { - foreach (string imageFile in imageFiles) - { - Image returnImage = null; - try - { - returnImage = ImageHelper.LoadImage(imageFile); - } - catch (Exception streamImageEx) - { - LOG.Error("Problem retrieving Image from clipboard.", streamImageEx); - } - if (returnImage != null) - { - LOG.InfoFormat("Got image from clipboard with size {0} and format {1}", returnImage.Size, returnImage.PixelFormat); - yield return returnImage; - } - } - } - } - } - - /// - /// Get an Image from the IDataObject, don't check for FileDrop - /// - /// - /// Image or null - private static Image GetImage(IDataObject dataObject) - { - Image returnImage = null; - if (dataObject != null) - { - IList formats = GetFormats(dataObject); - string[] retrieveFormats; - - // Found a weird bug, where PNG's from Outlook 2010 are clipped - // So I build some special logik 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[] { DataFormats.Dib, FORMAT_BITMAP, FORMAT_FILECONTENTS, FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JFIF, DataFormats.Tiff, FORMAT_GIF }; - } - else - { - retrieveFormats = new[] { FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_17, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JFIF, DataFormats.Tiff, DataFormats.Dib, FORMAT_BITMAP, FORMAT_FILECONTENTS, FORMAT_GIF }; - } - foreach (string currentFormat in retrieveFormats) - { - if (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) - { - ImageHelper.Orientate(returnImage); - return returnImage; - } - } - } - return null; - } - - /// - /// Helper method to try to get an image in the specified format from the dataObject - /// the DIB readed should solve the issue reported here: https://sourceforge.net/projects/greenshot/forums/forum/676083/topic/6354353/index/page/1 - /// It also supports Format17/DibV5, by using the following information: http://stackoverflow.com/a/14335591 - /// - /// string with the format - /// IDataObject - /// Image or null - private static Image GetImageForFormat(string format, IDataObject dataObject) - { - object clipboardObject = GetFromDataObject(dataObject, format); - MemoryStream imageStream = clipboardObject as MemoryStream; - if (!isValidStream(imageStream)) - { - // add "HTML Format" support here... - return clipboardObject as Image; - } - else - { - if (config.EnableSpecialDIBClipboardReader) - { - if (format == FORMAT_17 || format == DataFormats.Dib) - { - LOG.Info("Found DIB stream, trying to process it."); - try - { - byte[] dibBuffer = new byte[imageStream.Length]; - imageStream.Read(dibBuffer, 0, dibBuffer.Length); - BITMAPINFOHEADER infoHeader = BinaryStructHelper.FromByteArray(dibBuffer); - if (!infoHeader.IsDibV5) - { - LOG.InfoFormat("Using special DIB (fileHeader); - - using (MemoryStream bitmapStream = new MemoryStream()) - { - bitmapStream.Write(fileHeaderBytes, 0, fileHeaderSize); - bitmapStream.Write(dibBuffer, 0, dibBuffer.Length); - bitmapStream.Seek(0, SeekOrigin.Begin); - using (Image tmpImage = Image.FromStream(bitmapStream)) - { - if (tmpImage != null) - { - return ImageHelper.Clone(tmpImage); - } - } - } - } - 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); - } - } - } - else - { - LOG.Info("Skipping special DIB format reader as it's disabled in the configuration."); - } - try - { - imageStream.Seek(0, SeekOrigin.Begin); - using (Image tmpImage = Image.FromStream(imageStream, true, true)) - { - if (tmpImage != null) - { - LOG.InfoFormat("Got image with clipboard format {0} from the clipboard.", format); - return ImageHelper.Clone(tmpImage); - } - } - } - catch (Exception streamImageEx) - { - LOG.Error(string.Format("Problem retrieving {0} from clipboard.", format), streamImageEx); - } - } - return null; - } - - /// - /// Wrapper for Clipboard.GetText created for Bug #3432313 - /// - /// string if there is text on the clipboard - public static string GetText() - { - return GetText(GetDataObject()); - } - - /// - /// Get Text from the DataObject - /// - /// string if there is text on the clipboard - public static string GetText(IDataObject dataObject) - { - if (ContainsText(dataObject)) - { - return (String)dataObject.GetData(DataFormats.Text); - } - return null; - } - - /// - /// Set text to the clipboard - /// - /// - public static void SetClipboardData(string text) - { - IDataObject ido = new DataObject(); - ido.SetData(DataFormats.Text, true, text); - SetDataObject(ido, true); - } - - private static string getHTMLString(ISurface surface, string filename) - { - string utf8EncodedHTMLString = Encoding.GetEncoding(0).GetString(Encoding.UTF8.GetBytes(HTML_CLIPBOARD_STRING)); - utf8EncodedHTMLString = utf8EncodedHTMLString.Replace("${width}", surface.Image.Width.ToString()); - utf8EncodedHTMLString = utf8EncodedHTMLString.Replace("${height}", surface.Image.Height.ToString()); - utf8EncodedHTMLString = utf8EncodedHTMLString.Replace("${file}", filename.Replace("\\", "/")); - StringBuilder sb = new StringBuilder(); - sb.Append(utf8EncodedHTMLString); - sb.Replace("<<<<<<<1", (utf8EncodedHTMLString.IndexOf("") + "".Length).ToString("D8")); - sb.Replace("<<<<<<<2", (utf8EncodedHTMLString.IndexOf("")).ToString("D8")); - sb.Replace("<<<<<<<3", (utf8EncodedHTMLString.IndexOf("") + "".Length).ToString("D8")); - sb.Replace("<<<<<<<4", (utf8EncodedHTMLString.IndexOf("")).ToString("D8")); - return sb.ToString(); - } - - private static string getHTMLDataURLString(ISurface surface, MemoryStream pngStream) - { - string utf8EncodedHTMLString = Encoding.GetEncoding(0).GetString(Encoding.UTF8.GetBytes(HTML_CLIPBOARD_BASE64_STRING)); - utf8EncodedHTMLString = utf8EncodedHTMLString.Replace("${width}", surface.Image.Width.ToString()); - utf8EncodedHTMLString = utf8EncodedHTMLString.Replace("${height}", surface.Image.Height.ToString()); - utf8EncodedHTMLString = utf8EncodedHTMLString.Replace("${format}", "png"); - utf8EncodedHTMLString = utf8EncodedHTMLString.Replace("${data}", Convert.ToBase64String(pngStream.GetBuffer(), 0, (int)pngStream.Length)); - StringBuilder sb = new StringBuilder(); - sb.Append(utf8EncodedHTMLString); - sb.Replace("<<<<<<<1", (utf8EncodedHTMLString.IndexOf("") + "".Length).ToString("D8")); - sb.Replace("<<<<<<<2", (utf8EncodedHTMLString.IndexOf("")).ToString("D8")); - sb.Replace("<<<<<<<3", (utf8EncodedHTMLString.IndexOf("") + "".Length).ToString("D8")); - sb.Replace("<<<<<<<4", (utf8EncodedHTMLString.IndexOf("")).ToString("D8")); - return sb.ToString(); - } - - /// - /// Set an Image to the clipboard - /// This method will place images to the clipboard depending on the ClipboardFormats setting. - /// e.g. Bitmap which works with pretty much everything and type Dib for e.g. OpenOffice - /// because OpenOffice has a bug http://qa.openoffice.org/issues/show_bug.cgi?id=85661 - /// The Dib (Device Indenpendend Bitmap) in 32bpp actually won't work with Powerpoint 2003! - /// When pasting a Dib in PP 2003 the Bitmap is somehow shifted left! - /// For this problem the user should not use the direct paste (=Dib), but select Bitmap - /// - private const int BITMAPFILEHEADER_LENGTH = 14; - - public static void SetClipboardData(ISurface surface) - { - DataObject dataObject = new DataObject(); - - // This will work for Office and most other applications - //ido.SetData(DataFormats.Bitmap, true, image); - - MemoryStream dibStream = null; - MemoryStream dibV5Stream = null; - MemoryStream pngStream = null; - Image imageToSave = null; - bool disposeImage = false; - try - { - SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(OutputFormat.png, 100, false); - // Create the image which is going to be saved so we don't create it multiple times - disposeImage = ImageOutput.CreateImageFromSurface(surface, outputSettings, out imageToSave); - try - { - // Create PNG stream - if (config.ClipboardFormats.Contains(ClipboardFormat.PNG)) - { - pngStream = new MemoryStream(); - // PNG works for e.g. Powerpoint - SurfaceOutputSettings pngOutputSettings = new SurfaceOutputSettings(OutputFormat.png, 100, false); - ImageOutput.SaveToStream(imageToSave, null, pngStream, pngOutputSettings); - pngStream.Seek(0, SeekOrigin.Begin); - // Set the PNG stream - dataObject.SetData(FORMAT_PNG, false, pngStream); - } - } - catch (Exception pngEX) - { - LOG.Error("Error creating PNG for the Clipboard.", pngEX); - } - - try - { - if (config.ClipboardFormats.Contains(ClipboardFormat.DIB)) - { - using (MemoryStream tmpBmpStream = new MemoryStream()) - { - // Save image as BMP - SurfaceOutputSettings bmpOutputSettings = new SurfaceOutputSettings(OutputFormat.bmp, 100, false); - ImageOutput.SaveToStream(imageToSave, null, tmpBmpStream, bmpOutputSettings); - - dibStream = new MemoryStream(); - // Copy the source, but skip the "BITMAPFILEHEADER" which has a size of 14 - dibStream.Write(tmpBmpStream.GetBuffer(), BITMAPFILEHEADER_LENGTH, (int)tmpBmpStream.Length - BITMAPFILEHEADER_LENGTH); - } - - // Set the DIB to the clipboard DataObject - dataObject.SetData(DataFormats.Dib, true, dibStream); - } - } - catch (Exception dibEx) - { - LOG.Error("Error creating DIB for the Clipboard.", dibEx); - } - - // CF_DibV5 - try - { - if (config.ClipboardFormats.Contains(ClipboardFormat.DIBV5)) - { - // Create the stream for the clipboard - dibV5Stream = new MemoryStream(); - - // Create the BITMAPINFOHEADER - BITMAPINFOHEADER header = new BITMAPINFOHEADER(imageToSave.Width, imageToSave.Height, 32); - // Make sure we have BI_BITFIELDS, this seems to be normal for Format17? - header.biCompression = BI_COMPRESSION.BI_BITFIELDS; - // Create a byte[] to write - byte[] headerBytes = BinaryStructHelper.ToByteArray(header); - // Write the BITMAPINFOHEADER to the stream - dibV5Stream.Write(headerBytes, 0, headerBytes.Length); - - // As we have specified BI_COMPRESSION.BI_BITFIELDS, the BitfieldColorMask needs to be added - BitfieldColorMask colorMask = new BitfieldColorMask(); - // Make sure the values are set - colorMask.InitValues(); - // Create the byte[] from the struct - byte[] colorMaskBytes = BinaryStructHelper.ToByteArray(colorMask); - Array.Reverse(colorMaskBytes); - // Write to the stream - dibV5Stream.Write(colorMaskBytes, 0, colorMaskBytes.Length); - - // Create the raw bytes for the pixels only - byte[] bitmapBytes = BitmapToByteArray((Bitmap)imageToSave); - // Write to the stream - dibV5Stream.Write(bitmapBytes, 0, bitmapBytes.Length); - - // Set the DIBv5 to the clipboard DataObject - dataObject.SetData(FORMAT_17, true, dibV5Stream); - } - } - catch (Exception dibEx) - { - LOG.Error("Error creating DIB for the Clipboard.", dibEx); - } - - // Set the HTML - if (config.ClipboardFormats.Contains(ClipboardFormat.HTML)) - { - string tmpFile = ImageOutput.SaveToTmpFile(surface, new SurfaceOutputSettings(OutputFormat.png, 100, false), null); - string html = getHTMLString(surface, tmpFile); - dataObject.SetText(html, TextDataFormat.Html); - } - else if (config.ClipboardFormats.Contains(ClipboardFormat.HTMLDATAURL)) - { - string html; - using (MemoryStream tmpPNGStream = new MemoryStream()) - { - SurfaceOutputSettings pngOutputSettings = new SurfaceOutputSettings(OutputFormat.png, 100, false); - // Do not allow to reduce the colors, some applications dislike 256 color images - // reported with bug #3594681 - pngOutputSettings.DisableReduceColors = true; - // Check if we can use the previously used image - if (imageToSave.PixelFormat != PixelFormat.Format8bppIndexed) - { - ImageOutput.SaveToStream(imageToSave, surface, tmpPNGStream, pngOutputSettings); - } - else - { - ImageOutput.SaveToStream(surface, tmpPNGStream, pngOutputSettings); - } - html = getHTMLDataURLString(surface, tmpPNGStream); - } - dataObject.SetText(html, TextDataFormat.Html); - } - } - finally - { - // we need to use the SetDataOject before the streams are closed otherwise the buffer will be gone! - // Check if Bitmap is wanted - if (config.ClipboardFormats.Contains(ClipboardFormat.BITMAP)) - { - dataObject.SetImage(imageToSave); - // Place the DataObject to the clipboard - SetDataObject(dataObject, true); - } - else - { - // Place the DataObject to the clipboard - SetDataObject(dataObject, true); - } - - if (pngStream != null) - { - pngStream.Dispose(); - pngStream = null; - } - - if (dibStream != null) - { - dibStream.Dispose(); - dibStream = null; - } - if (dibV5Stream != null) - { - dibV5Stream.Dispose(); - dibV5Stream = null; - } - // cleanup if needed - if (disposeImage && imageToSave != null) - { - imageToSave.Dispose(); - } - } - } - - /// - /// Helper method so get the bitmap bytes - /// See: http://stackoverflow.com/a/6570155 - /// - /// Bitmap - /// byte[] - private static byte[] BitmapToByteArray(Bitmap bitmap) - { - // Lock the bitmap's bits. - Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height); - BitmapData bmpData = bitmap.LockBits(rect, ImageLockMode.ReadOnly, bitmap.PixelFormat); - - int absStride = Math.Abs(bmpData.Stride); - int bytes = absStride * bitmap.Height; - long ptr = bmpData.Scan0.ToInt32(); - // Declare an array to hold the bytes of the bitmap. - byte[] rgbValues = new byte[bytes]; - - for (int i = 0; i < bitmap.Height; i++) - { - IntPtr pointer = new IntPtr(ptr + (bmpData.Stride * i)); - Marshal.Copy(pointer, rgbValues, absStride * (bitmap.Height - i - 1), absStride); - } - - // Unlock the bits. - bitmap.UnlockBits(bmpData); - - return rgbValues; - } - - /// - /// Set Object with type Type to the clipboard - /// - /// Type - /// object - public static void SetClipboardData(Type type, Object obj) - { - DataFormats.Format format = DataFormats.GetFormat(type.FullName); - - //now copy to clipboard - IDataObject dataObj = new DataObject(); - dataObj.SetData(format.Name, false, obj); - // Use false to make the object dissapear when the application stops. - SetDataObject(dataObj, true); - } - - /// - /// Retrieve a list of all formats currently on the clipboard - /// - /// List with the current formats - public static List GetFormats() - { - return GetFormats(GetDataObject()); - } - - /// - /// Retrieve a list of all formats currently in the IDataObject - /// - /// List with the current formats - public static List GetFormats(IDataObject dataObj) - { - string[] formats = null; - - if (dataObj != null) - { - formats = dataObj.GetFormats(); - } - if (formats != null) - { - LOG.DebugFormat("Got clipboard formats: {0}", String.Join(",", formats)); - return new List(formats); - } - return new List(); - } - - /// - /// Check if there is currently something in the dataObject which has the supplied format - /// - /// IDataObject - /// string with format - /// true if one the format is found - public static bool ContainsFormat(string format) - { - return ContainsFormat(GetDataObject(), new[] { format }); - } - - /// - /// Check if there is currently something on the clipboard which has the supplied format - /// - /// string with format - /// true if one the format is found - public static bool ContainsFormat(IDataObject dataObject, string format) - { - return ContainsFormat(dataObject, new[] { format }); - } - - /// - /// Check if there is currently something on the clipboard which has one of the supplied formats - /// - /// string[] with formats - /// true if one of the formats was found - public static bool ContainsFormat(string[] formats) - { - return ContainsFormat(GetDataObject(), formats); - } - - /// - /// Check if there is currently something on the clipboard which has one of the supplied formats - /// - /// IDataObject - /// string[] with formats - /// true if one of the formats was found - public static bool ContainsFormat(IDataObject dataObject, string[] formats) - { - bool formatFound = false; - List currentFormats = GetFormats(dataObject); - if (currentFormats == null || currentFormats.Count == 0 || formats == null || formats.Length == 0) - { - return false; - } - foreach (string format in formats) - { - if (currentFormats.Contains(format)) - { - formatFound = true; - break; - } - } - return formatFound; - } - - /// - /// Get Object of type Type from the clipboard - /// - /// Type to get - /// object from clipboard - public static Object GetClipboardData(Type type) - { - string format = type.FullName; - return GetClipboardData(format); - } - - /// - /// Get Object for format from IDataObject - /// - /// IDataObject - /// Type to get - /// object from IDataObject - public static Object GetFromDataObject(IDataObject dataObj, Type type) - { - if (type != null) - { - return GetFromDataObject(dataObj, type.FullName); - } - return null; - } - - /// - /// Get ImageFilenames from the IDataObject - /// - /// IDataObject - /// - public static List GetImageFilenames(IDataObject dataObject) - { - List filenames = new List(); - string[] dropFileNames = (string[])dataObject.GetData(DataFormats.FileDrop); - try - { - if (dropFileNames != null && dropFileNames.Length > 0) - { - foreach (string filename in dropFileNames) - { - string ext = Path.GetExtension(filename).ToLower(); - if ((ext == ".jpg") || (ext == ".jpeg") || (ext == ".tiff") || (ext == ".gif") || (ext == ".png") || (ext == ".bmp") || (ext == ".ico") || (ext == ".wmf")) - { - filenames.Add(filename); - } - } - } - } - catch (Exception ex) - { - LOG.Warn("Ignoring an issue with getting the dropFilenames from the clipboard: ", ex); - } - return filenames; - } - - /// - /// Get Object for format from IDataObject - /// - /// IDataObject - /// format to get - /// object from IDataObject - public static Object GetFromDataObject(IDataObject dataObj, string format) - { - if (dataObj != null) - { - try - { - return dataObj.GetData(format); - } - catch (Exception e) - { - LOG.Error("Error in GetClipboardData.", e); - } - } - return null; - } - - /// - /// Get Object for format from the clipboard - /// - /// format to get - /// object from clipboard - public static Object GetClipboardData(string format) - { - return GetFromDataObject(GetDataObject(), format); - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Core/Effects.cs b/Greenshot.ImageEditor/Core/Effects.cs deleted file mode 100644 index b5e59ef43..000000000 --- a/Greenshot.ImageEditor/Core/Effects.cs +++ /dev/null @@ -1,669 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using GreenshotPlugin; -using GreenshotPlugin.Core; -using System; -using System.ComponentModel; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Imaging; -using System.Globalization; -using System.Text; - -namespace Greenshot.Core -{ - /// - /// Interface to describe an effect - /// - public interface IEffect - { - /// - /// Apply this IEffect to the supplied sourceImage. - /// In the process of applying the supplied matrix will be modified to represent the changes. - /// - /// Image to apply the effect to - /// Matrix with the modifications like rotate, translate etc. this can be used to calculate the new location of elements on a canvas - /// new image with applied effect - Image Apply(Image sourceImage, Matrix matrix); - - /// - /// Reset all values to their defaults - /// - void Reset(); - } - - /// - /// DropShadowEffect - /// - [TypeConverter(typeof(EffectConverter))] - public class DropShadowEffect : IEffect - { - public DropShadowEffect() - { - Reset(); - } - - public float Darkness - { - get; - set; - } - public int ShadowSize - { - get; - set; - } - public Point ShadowOffset - { - get; - set; - } - - public virtual void Reset() - { - Darkness = 0.6f; - ShadowSize = 7; - ShadowOffset = new Point(-1, -1); - } - - public virtual Image Apply(Image sourceImage, Matrix matrix) - { - return ImageHelper.CreateShadow(sourceImage, Darkness, ShadowSize, ShadowOffset, matrix, PixelFormat.Format32bppArgb); - } - } - - /// - /// TornEdgeEffect extends on DropShadowEffect - /// - [TypeConverter(typeof(EffectConverter))] - public class TornEdgeEffect : DropShadowEffect - { - public TornEdgeEffect() - { - Reset(); - } - - public int ToothHeight - { - get; - set; - } - public int HorizontalToothRange - { - get; - set; - } - public int VerticalToothRange - { - get; - set; - } - public bool[] Edges - { - get; - set; - } - public bool GenerateShadow - { - get; - set; - } - - public override void Reset() - { - base.Reset(); - ShadowSize = 7; - ToothHeight = 12; - HorizontalToothRange = 20; - VerticalToothRange = 20; - Edges = new[] { true, true, true, true }; - GenerateShadow = true; - } - - public override Image Apply(Image sourceImage, Matrix matrix) - { - Image tmpTornImage = ImageHelper.CreateTornEdge(sourceImage, ToothHeight, HorizontalToothRange, VerticalToothRange, Edges); - if (GenerateShadow) - { - using (tmpTornImage) - { - return ImageHelper.CreateShadow(tmpTornImage, Darkness, ShadowSize, ShadowOffset, matrix, PixelFormat.Format32bppArgb); - } - } - return tmpTornImage; - } - } - - /// - /// GrayscaleEffect - /// - public class GrayscaleEffect : IEffect - { - public Image Apply(Image sourceImage, Matrix matrix) - { - return ImageHelper.CreateGrayscale(sourceImage); - } - - public void Reset() - { - // No settings to reset - } - } - - /// - /// MonochromeEffect - /// - public class MonochromeEffect : IEffect - { - private readonly byte _threshold; - - /// Threshold for monochrome filter (0 - 255), lower value means less black - public MonochromeEffect(byte threshold) - { - _threshold = threshold; - } - - public void Reset() - { - // Modify the threshold to have a default, which is reset here - } - - public Image Apply(Image sourceImage, Matrix matrix) - { - return ImageHelper.CreateMonochrome(sourceImage, _threshold); - } - } - - /// - /// AdjustEffect - /// - public class AdjustEffect : IEffect - { - public AdjustEffect() - { - Reset(); - } - - public float Contrast - { - get; - set; - } - public float Brightness - { - get; - set; - } - public float Gamma - { - get; - set; - } - - public void Reset() - { - Contrast = 1f; - Brightness = 1f; - Gamma = 1f; - } - - public Image Apply(Image sourceImage, Matrix matrix) - { - return ImageHelper.Adjust(sourceImage, Brightness, Contrast, Gamma); - } - } - - /// - /// ReduceColorsEffect - /// - public class ReduceColorsEffect : IEffect - { - public ReduceColorsEffect() - { - Reset(); - } - - public int Colors - { - get; - set; - } - - public void Reset() - { - Colors = 256; - } - - public Image Apply(Image sourceImage, Matrix matrix) - { - using (WuQuantizer quantizer = new WuQuantizer((Bitmap)sourceImage)) - { - int colorCount = quantizer.GetColorCount(); - if (colorCount > Colors) - { - try - { - return quantizer.GetQuantizedImage(Colors); - } - catch (Exception e) - { - LOG.Warn("Error occurred while Quantizing the image, ignoring and using original. Error: ", e); - } - } - } - return null; - } - } - - /// - /// InvertEffect - /// - public class InvertEffect : IEffect - { - public Image Apply(Image sourceImage, Matrix matrix) - { - return ImageHelper.CreateNegative(sourceImage); - } - - public void Reset() - { - // No settings to reset - } - } - - /// - /// BorderEffect - /// - public class BorderEffect : IEffect - { - public BorderEffect() - { - Reset(); - } - - public Color Color - { - get; - set; - } - public int Width - { - get; - set; - } - - public void Reset() - { - Width = 2; - Color = Color.Black; - } - - public Image Apply(Image sourceImage, Matrix matrix) - { - return ImageHelper.CreateBorder(sourceImage, Width, Color, sourceImage.PixelFormat, matrix); - } - } - - /// - /// RotateEffect - /// - public class RotateEffect : IEffect - { - public RotateEffect(int angle) - { - Angle = angle; - } - - public int Angle - { - get; - set; - } - - public void Reset() - { - // Angle doesn't have a default value - } - - public Image Apply(Image sourceImage, Matrix matrix) - { - RotateFlipType flipType; - if (Angle == 90) - { - matrix.Rotate(90, MatrixOrder.Append); - matrix.Translate(sourceImage.Height, 0, MatrixOrder.Append); - flipType = RotateFlipType.Rotate90FlipNone; - } - else if (Angle == -90 || Angle == 270) - { - flipType = RotateFlipType.Rotate270FlipNone; - matrix.Rotate(-90, MatrixOrder.Append); - matrix.Translate(0, sourceImage.Width, MatrixOrder.Append); - } - else - { - throw new NotSupportedException("Currently only an angle of 90 or -90 (270) is supported."); - } - return ImageHelper.RotateFlip(sourceImage, flipType); - } - } - - /// - /// ResizeEffect - /// - public class ResizeEffect : IEffect - { - public ResizeEffect(int width, int height, bool maintainAspectRatio) - { - Width = width; - Height = height; - MaintainAspectRatio = maintainAspectRatio; - } - - public int Width - { - get; - set; - } - public int Height - { - get; - set; - } - public bool MaintainAspectRatio - { - get; - set; - } - - public void Reset() - { - // values don't have a default value - } - - public Image Apply(Image sourceImage, Matrix matrix) - { - return ImageHelper.ResizeImage(sourceImage, MaintainAspectRatio, Width, Height, matrix); - } - } - - /// - /// ResizeCanvasEffect - /// - public class ResizeCanvasEffect : IEffect - { - public ResizeCanvasEffect(int left, int right, int top, int bottom) - { - Left = left; - Right = right; - Top = top; - Bottom = bottom; - BackgroundColor = Color.Empty; // Uses the default background color depending on the format - } - - public int Left - { - get; - set; - } - public int Right - { - get; - set; - } - public int Top - { - get; - set; - } - public int Bottom - { - get; - set; - } - public Color BackgroundColor - { - get; - set; - } - - public void Reset() - { - // values don't have a default value - } - - public Image Apply(Image sourceImage, Matrix matrix) - { - return ImageHelper.ResizeCanvas(sourceImage, BackgroundColor, Left, Right, Top, Bottom, matrix); - } - } - - public class EffectConverter : TypeConverter - { - // Fix to prevent BUG-1753 - private readonly NumberFormatInfo numberFormatInfo = new NumberFormatInfo(); - - public EffectConverter() - { - numberFormatInfo.NumberDecimalSeparator = "."; - numberFormatInfo.NumberGroupSeparator = ","; - } - - public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) - { - if (sourceType == typeof(string)) - { - return true; - } - return base.CanConvertFrom(context, sourceType); - } - - public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) - { - if (destinationType == typeof(string)) - { - return true; - } - if (destinationType == typeof(DropShadowEffect)) - { - return true; - } - if (destinationType == typeof(TornEdgeEffect)) - { - return true; - } - return base.CanConvertTo(context, destinationType); - } - - public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) - { - // to string - if (destinationType == typeof(string)) - { - StringBuilder sb = new StringBuilder(); - if (value.GetType() == typeof(DropShadowEffect)) - { - DropShadowEffect effect = value as DropShadowEffect; - RetrieveDropShadowEffectValues(effect, sb); - return sb.ToString(); - } - if (value.GetType() == typeof(TornEdgeEffect)) - { - TornEdgeEffect effect = value as TornEdgeEffect; - RetrieveDropShadowEffectValues(effect, sb); - sb.Append("|"); - RetrieveTornEdgeEffectValues(effect, sb); - return sb.ToString(); - } - } - // from string - if (value is string) - { - string settings = value as string; - if (destinationType == typeof(DropShadowEffect)) - { - DropShadowEffect effect = new DropShadowEffect(); - ApplyDropShadowEffectValues(settings, effect); - return effect; - } - if (destinationType == typeof(TornEdgeEffect)) - { - TornEdgeEffect effect = new TornEdgeEffect(); - ApplyDropShadowEffectValues(settings, effect); - ApplyTornEdgeEffectValues(settings, effect); - return effect; - } - } - return base.ConvertTo(context, culture, value, destinationType); - } - - public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) - { - if (value != null && value is string) - { - string settings = value as string; - if (settings.Contains("ToothHeight")) - { - return ConvertTo(context, culture, value, typeof(TornEdgeEffect)); - } - return ConvertTo(context, culture, value, typeof(DropShadowEffect)); - } - return base.ConvertFrom(context, culture, value); - } - - private void ApplyDropShadowEffectValues(string valuesString, DropShadowEffect effect) - { - string[] values = valuesString.Split('|'); - foreach (string nameValuePair in values) - { - string[] pair = nameValuePair.Split(':'); - switch (pair[0]) - { - case "Darkness": - float darkness; - // Fix to prevent BUG-1753 - if (pair[1] != null && float.TryParse(pair[1], NumberStyles.Float, numberFormatInfo, out darkness)) - { - if (darkness <= 1.0) - { - effect.Darkness = darkness; - } - } - break; - case "ShadowSize": - int shadowSize; - if (int.TryParse(pair[1], out shadowSize)) - { - effect.ShadowSize = shadowSize; - } - break; - case "ShadowOffset": - Point shadowOffset = new Point(); - int shadowOffsetX; - int shadowOffsetY; - string[] coordinates = pair[1].Split(','); - if (int.TryParse(coordinates[0], out shadowOffsetX)) - { - shadowOffset.X = shadowOffsetX; - } - if (int.TryParse(coordinates[1], out shadowOffsetY)) - { - shadowOffset.Y = shadowOffsetY; - } - effect.ShadowOffset = shadowOffset; - break; - } - } - } - - private void ApplyTornEdgeEffectValues(string valuesString, TornEdgeEffect effect) - { - string[] values = valuesString.Split('|'); - foreach (string nameValuePair in values) - { - string[] pair = nameValuePair.Split(':'); - switch (pair[0]) - { - case "GenerateShadow": - bool generateShadow; - if (bool.TryParse(pair[1], out generateShadow)) - { - effect.GenerateShadow = generateShadow; - } - break; - case "ToothHeight": - int toothHeight; - if (int.TryParse(pair[1], out toothHeight)) - { - effect.ToothHeight = toothHeight; - } - break; - case "HorizontalToothRange": - int horizontalToothRange; - if (int.TryParse(pair[1], out horizontalToothRange)) - { - effect.HorizontalToothRange = horizontalToothRange; - } - break; - case "VerticalToothRange": - int verticalToothRange; - if (int.TryParse(pair[1], out verticalToothRange)) - { - effect.VerticalToothRange = verticalToothRange; - } - break; - case "Edges": - string[] edges = pair[1].Split(','); - bool edge; - if (bool.TryParse(edges[0], out edge)) - { - effect.Edges[0] = edge; - } - if (bool.TryParse(edges[1], out edge)) - { - effect.Edges[1] = edge; - } - if (bool.TryParse(edges[2], out edge)) - { - effect.Edges[2] = edge; - } - if (bool.TryParse(edges[3], out edge)) - { - effect.Edges[3] = edge; - } - break; - } - } - } - - private void RetrieveDropShadowEffectValues(DropShadowEffect effect, StringBuilder sb) - { - // Fix to prevent BUG-1753 is to use the numberFormatInfo - sb.AppendFormat("Darkness:{0}|ShadowSize:{1}|ShadowOffset:{2},{3}", effect.Darkness.ToString("F2", numberFormatInfo), effect.ShadowSize, effect.ShadowOffset.X, effect.ShadowOffset.Y); - } - - private void RetrieveTornEdgeEffectValues(TornEdgeEffect effect, StringBuilder sb) - { - sb.AppendFormat("GenerateShadow:{0}|ToothHeight:{1}|HorizontalToothRange:{2}|VerticalToothRange:{3}|Edges:{4},{5},{6},{7}", effect.GenerateShadow, effect.ToothHeight, effect.HorizontalToothRange, effect.VerticalToothRange, effect.Edges[0], effect.Edges[1], effect.Edges[2], effect.Edges[3]); - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Core/EnumExtensions.cs b/Greenshot.ImageEditor/Core/EnumExtensions.cs deleted file mode 100644 index 6b76fec98..000000000 --- a/Greenshot.ImageEditor/Core/EnumExtensions.cs +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System; - -namespace GreenshotPlugin.Core -{ - public static class EnumerationExtensions - { - public static bool Has(this Enum type, T value) - { - Type underlyingType = Enum.GetUnderlyingType(value.GetType()); - try - { - if (underlyingType == typeof(int)) - { - return (((int)(object)type & (int)(object)value) == (int)(object)value); - } - else if (underlyingType == typeof(uint)) - { - return (((uint)(object)type & (uint)(object)value) == (uint)(object)value); - } - } - catch - { - } - return false; - } - - public static bool Is(this Enum type, T value) - { - Type underlyingType = Enum.GetUnderlyingType(value.GetType()); - try - { - if (underlyingType == typeof(int)) - { - return (int)(object)type == (int)(object)value; - } - else if (underlyingType == typeof(uint)) - { - return (uint)(object)type == (uint)(object)value; - } - } - catch - { - } - return false; - } - - /// - /// Add a flag to an enum - /// - /// - /// - /// - public static T Add(this Enum type, T value) - { - Type underlyingType = Enum.GetUnderlyingType(value.GetType()); - try - { - if (underlyingType == typeof(int)) - { - return (T)(object)(((int)(object)type | (int)(object)value)); - } - else if (underlyingType == typeof(uint)) - { - return (T)(object)(((uint)(object)type | (uint)(object)value)); - } - } - catch (Exception ex) - { - throw new ArgumentException(string.Format("Could not append value '{0}' to enumerated type '{1}'.", value, typeof(T).Name), ex); - } - throw new ArgumentException(string.Format("Could not append value '{0}' to enumerated type '{1}'.", value, typeof(T).Name)); - } - - /// - /// Remove a flag from an enum type - /// - /// - /// - /// - public static T Remove(this Enum type, T value) - { - Type underlyingType = Enum.GetUnderlyingType(value.GetType()); - try - { - if (underlyingType == typeof(int)) - { - return (T)(object)(((int)(object)type & ~(int)(object)value)); - } - else if (underlyingType == typeof(uint)) - { - return (T)(object)(((uint)(object)type & ~(uint)(object)value)); - } - } - catch (Exception ex) - { - throw new ArgumentException(string.Format("Could not remove value '{0}' from enumerated type '{1}'.", value, typeof(T).Name), ex); - } - throw new ArgumentException(string.Format("Could not remove value '{0}' from enumerated type '{1}'.", value, typeof(T).Name)); - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Core/EventDelay.cs b/Greenshot.ImageEditor/Core/EventDelay.cs deleted file mode 100644 index d6787077d..000000000 --- a/Greenshot.ImageEditor/Core/EventDelay.cs +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System; - -namespace GreenshotPlugin.Core -{ - public class EventDelay - { - private long lastCheck; - private readonly long waitTime; - - public EventDelay(long ticks) - { - waitTime = ticks; - } - - public bool Check() - { - lock (this) - { - long now = DateTime.Now.Ticks; - bool isPassed = now - lastCheck > waitTime; - lastCheck = now; - return isPassed; - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Core/FastBitmap.cs b/Greenshot.ImageEditor/Core/FastBitmap.cs deleted file mode 100644 index 53d713c83..000000000 --- a/Greenshot.ImageEditor/Core/FastBitmap.cs +++ /dev/null @@ -1,1167 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Imaging; - -namespace GreenshotPlugin.Core -{ - /// - /// The interface for the FastBitmap - /// - public interface IFastBitmap : IDisposable - { - /// - /// Get the color at x,y - /// The returned Color object depends on the underlying pixel format - /// - /// int x - /// int y - /// Color - Color GetColorAt(int x, int y); - - /// - /// Set the color at the specified location - /// - /// int x - /// int y - /// Color - void SetColorAt(int x, int y, Color color); - - /// - /// Get the color at x,y - /// The returned byte[] color depends on the underlying pixel format - /// - /// int x - /// int y - /// Set the color at the specified location - /// - /// int x - /// int y - /// byte[] color - void SetColorAt(int x, int y, byte[] color); - - /// - /// Lock the bitmap - /// - void Lock(); - - /// - /// Unlock the bitmap - /// - void Unlock(); - - /// - /// Unlock the bitmap and get the underlying bitmap in one call - /// - /// - Bitmap UnlockAndReturnBitmap(); - - /// - /// Size of the underlying image - /// - Size Size - { - get; - } - - /// - /// Height of the image area that this fastbitmap covers - /// - int Height - { - get; - } - - /// - /// Width of the image area that this fastbitmap covers - /// - int Width - { - get; - } - - /// - /// Top of the image area that this fastbitmap covers - /// - int Top - { - get; - } - - /// - /// Left of the image area that this fastbitmap covers - /// - int Left - { - get; - } - - /// - /// Right of the image area that this fastbitmap covers - /// - int Right - { - get; - } - - /// - /// Bottom of the image area that this fastbitmap covers - /// - int Bottom - { - get; - } - - /// - /// Does the underlying image need to be disposed - /// - bool NeedsDispose - { - get; - set; - } - - /// - /// Returns if this FastBitmap has an alpha channel - /// - bool hasAlphaChannel - { - get; - } - - /// - /// Draw the stored bitmap to the destionation bitmap at the supplied point - /// - /// Graphics - /// Point with location - void DrawTo(Graphics graphics, Point destination); - - /// - /// Draw the stored Bitmap on the Destination bitmap with the specified rectangle - /// Be aware that the stored bitmap will be resized to the specified rectangle!! - /// - /// Graphics - /// Rectangle with destination - void DrawTo(Graphics graphics, Rectangle destinationRect); - - /// - /// Return true if the coordinates are inside the FastBitmap - /// - /// - /// - /// - bool Contains(int x, int y); - - /// - /// Set the bitmap resolution - /// - /// - /// - void SetResolution(float horizontal, float vertical); - } - - /// - /// This interface can be used for when offsetting is needed - /// - public interface IFastBitmapWithOffset : IFastBitmap - { - /// - /// Return true if the coordinates are inside the FastBitmap - /// - /// - /// - /// - new bool Contains(int x, int y); - - /// - /// Set the color at the specified location, using offsetting so the original coordinates can be used - /// - /// int x - /// int y - /// Color color - new void SetColorAt(int x, int y, Color color); - - /// - /// Set the color at the specified location, using offsetting so the original coordinates can be used - /// - /// int x - /// int y - /// byte[] color - new void SetColorAt(int x, int y, byte[] color); - - /// - /// Get the color at x,y - /// The returned Color object depends on the underlying pixel format - /// - /// int x - /// int y - /// Color - new Color GetColorAt(int x, int y); - - /// - /// Get the color at x,y, using offsetting so the original coordinates can be used - /// The returned byte[] color depends on the underlying pixel format - /// - /// int x - /// int y - /// This interface can be used for when clipping is needed - /// - public interface IFastBitmapWithClip : IFastBitmap - { - Rectangle Clip - { - get; - set; - } - - bool InvertClip - { - get; - set; - } - - /// - /// Set the color at the specified location, this doesn't do anything if the location is excluded due to clipping - /// - /// int x - /// int y - /// Color color - new void SetColorAt(int x, int y, Color color); - - /// - /// Set the color at the specified location, this doesn't do anything if the location is excluded due to clipping - /// - /// int x - /// int y - /// byte[] color - new void SetColorAt(int x, int y, byte[] color); - - /// - /// Return true if the coordinates are inside the FastBitmap and not clipped - /// - /// - /// - /// - new bool Contains(int x, int y); - } - - /// - /// This interface is implemented when there is a alpha-blending possibility - /// - public interface IFastBitmapWithBlend : IFastBitmap - { - Color BackgroundBlendColor - { - get; - set; - } - - Color GetBlendedColorAt(int x, int y); - } - - /// - /// The base class for the fast bitmap implementation - /// - public unsafe abstract class FastBitmap : IFastBitmap, IFastBitmapWithClip, IFastBitmapWithOffset - { - protected const int PIXELFORMAT_INDEX_A = 3; - protected const int PIXELFORMAT_INDEX_R = 2; - protected const int PIXELFORMAT_INDEX_G = 1; - protected const int PIXELFORMAT_INDEX_B = 0; - - public const int COLOR_INDEX_R = 0; - public const int COLOR_INDEX_G = 1; - public const int COLOR_INDEX_B = 2; - public const int COLOR_INDEX_A = 3; - - protected Rectangle area = Rectangle.Empty; - /// - /// If this is set to true, the bitmap will be disposed when disposing the IFastBitmap - /// - public bool NeedsDispose - { - get; - set; - } - - public Rectangle Clip - { - get; - set; - } - - public bool InvertClip - { - get; - set; - } - - /// - /// The bitmap for which the FastBitmap is creating access - /// - protected Bitmap bitmap; - - protected BitmapData bmData; - protected int stride; /* bytes per pixel row */ - protected bool bitsLocked; - protected byte* pointer; - - public static IFastBitmap Create(Bitmap source) - { - return Create(source, Rectangle.Empty); - } - - public void SetResolution(float horizontal, float vertical) - { - bitmap.SetResolution(horizontal, vertical); - } - - /// - /// Factory for creating a FastBitmap depending on the pixelformat of the source - /// The supplied rectangle specifies the area for which the FastBitmap does its thing - /// - /// Bitmap to access - /// Rectangle which specifies the area to have access to, can be Rectangle.Empty for the whole image - /// IFastBitmap - public static IFastBitmap Create(Bitmap source, Rectangle area) - { - switch (source.PixelFormat) - { - case PixelFormat.Format8bppIndexed: - return new FastChunkyBitmap(source, area); - case PixelFormat.Format24bppRgb: - return new Fast24RGBBitmap(source, area); - case PixelFormat.Format32bppRgb: - return new Fast32RGBBitmap(source, area); - case PixelFormat.Format32bppArgb: - case PixelFormat.Format32bppPArgb: - return new Fast32ARGBBitmap(source, area); - default: - throw new NotSupportedException(string.Format("Not supported Pixelformat {0}", source.PixelFormat)); - } - } - - /// - /// Factory for creating a FastBitmap as a destination for the source - /// - /// Bitmap to clone - /// IFastBitmap - public static IFastBitmap CreateCloneOf(Image source) - { - return CreateCloneOf(source, source.PixelFormat, Rectangle.Empty); - } - - /// - /// Factory for creating a FastBitmap as a destination for the source - /// - /// Bitmap to clone - /// new Pixelformat - /// IFastBitmap - public static IFastBitmap CreateCloneOf(Image source, PixelFormat pixelFormat) - { - return CreateCloneOf(source, pixelFormat, Rectangle.Empty); - } - - /// - /// Factory for creating a FastBitmap as a destination for the source - /// - /// Bitmap to clone - /// Area of the bitmap to access, can be Rectangle.Empty for the whole - /// IFastBitmap - public static IFastBitmap CreateCloneOf(Image source, Rectangle area) - { - return CreateCloneOf(source, PixelFormat.DontCare, area); - } - - /// - /// Factory for creating a FastBitmap as a destination for the source - /// - /// Bitmap to clone - /// Pixelformat of the cloned bitmap - /// Area of the bitmap to access, can be Rectangle.Empty for the whole - /// IFastBitmap - public static IFastBitmap CreateCloneOf(Image source, PixelFormat pixelFormat, Rectangle area) - { - Bitmap destination = ImageHelper.CloneArea(source, area, pixelFormat); - FastBitmap fastBitmap = Create(destination) as FastBitmap; - fastBitmap.NeedsDispose = true; - fastBitmap.Left = area.Left; - fastBitmap.Top = area.Top; - return fastBitmap; - } - - /// - /// Factory for creating a FastBitmap as a destination - /// - /// - /// - /// - /// IFastBitmap - public static IFastBitmap CreateEmpty(Size newSize, PixelFormat pixelFormat, Color backgroundColor) - { - Bitmap destination = ImageHelper.CreateEmpty(newSize.Width, newSize.Height, pixelFormat, backgroundColor, 96f, 96f); - IFastBitmap fastBitmap = Create(destination); - fastBitmap.NeedsDispose = true; - return fastBitmap; - } - - /// - /// Constructor which stores the image and locks it when called - /// - /// - protected FastBitmap(Bitmap bitmap, Rectangle area) - { - this.bitmap = bitmap; - Rectangle bitmapArea = new Rectangle(Point.Empty, bitmap.Size); - if (area != Rectangle.Empty) - { - area.Intersect(bitmapArea); - this.area = area; - } - else - { - this.area = bitmapArea; - } - // As the lock takes care that only the specified area is made available we need to calculate the offset - Left = area.Left; - Top = area.Top; - // Default cliping is done to the area without invert - Clip = this.area; - InvertClip = false; - // Always lock, so we don't need to do this ourselves - Lock(); - } - - /// - /// Return the size of the image - /// - public Size Size - { - get - { - if (area == Rectangle.Empty) - { - return bitmap.Size; - } - return area.Size; - } - } - - /// - /// Return the width of the image - /// - public int Width - { - get - { - if (area == Rectangle.Empty) - { - return bitmap.Width; - } - return area.Width; - } - } - - /// - /// Return the height of the image - /// - public int Height - { - get - { - if (area == Rectangle.Empty) - { - return bitmap.Height; - } - return area.Height; - } - } - - private int left; - /// - /// Return the left of the fastbitmap, this is also used as an offset - /// - public int Left - { - get - { - return 0; - } - set - { - left = value; - } - } - - /// - /// Return the left of the fastbitmap, this is also used as an offset - /// - int IFastBitmapWithOffset.Left - { - get - { - return left; - } - set - { - left = value; - } - } - - private int top; - /// - /// Return the top of the fastbitmap, this is also used as an offset - /// - public int Top - { - get - { - return 0; - } - set - { - top = value; - } - } - - /// - /// Return the top of the fastbitmap, this is also used as an offset - /// - int IFastBitmapWithOffset.Top - { - get - { - return top; - } - set - { - top = value; - } - } - - /// - /// Return the right of the fastbitmap - /// - public int Right - { - get - { - return Left + Width; - } - } - - /// - /// Return the bottom of the fastbitmap - /// - public int Bottom - { - get - { - return Top + Height; - } - } - - /// - /// Returns the underlying bitmap, unlocks it and prevents that it will be disposed - /// - public Bitmap UnlockAndReturnBitmap() - { - if (bitsLocked) - { - Unlock(); - } - NeedsDispose = false; - return bitmap; - } - - public virtual bool hasAlphaChannel - { - get - { - return false; - } - } - - /// - /// Destructor - /// - ~FastBitmap() - { - Dispose(false); - } - - /// - /// The public accessible Dispose - /// Will call the GarbageCollector to SuppressFinalize, preventing being cleaned twice - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - // The bulk of the clean-up code is implemented in Dispose(bool) - - /// - /// This Dispose is called from the Dispose and the Destructor. - /// When disposing==true all non-managed resources should be freed too! - /// - /// - protected virtual void Dispose(bool disposing) - { - Unlock(); - if (disposing) - { - if (bitmap != null && NeedsDispose) - { - bitmap.Dispose(); - } - } - bitmap = null; - bmData = null; - pointer = null; - } - - /// - /// Lock the bitmap so we have direct access to the memory - /// - public void Lock() - { - if (Width > 0 && Height > 0 && !bitsLocked) - { - bmData = bitmap.LockBits(area, ImageLockMode.ReadWrite, bitmap.PixelFormat); - bitsLocked = true; - - IntPtr Scan0 = bmData.Scan0; - pointer = (byte*)(void*)Scan0; - stride = bmData.Stride; - } - } - - /// - /// Unlock the System Memory - /// - public void Unlock() - { - if (bitsLocked) - { - bitmap.UnlockBits(bmData); - bitsLocked = false; - } - } - - /// - /// Draw the stored bitmap to the destionation bitmap at the supplied point - /// - /// - /// - public void DrawTo(Graphics graphics, Point destination) - { - DrawTo(graphics, new Rectangle(destination, area.Size)); - } - - /// - /// Draw the stored Bitmap on the Destination bitmap with the specified rectangle - /// Be aware that the stored bitmap will be resized to the specified rectangle!! - /// - /// - /// - /// - public void DrawTo(Graphics graphics, Rectangle destinationRect) - { - // Make sure this.bitmap is unlocked, if it was locked - bool isLocked = bitsLocked; - if (isLocked) - { - Unlock(); - } - - graphics.DrawImage(bitmap, destinationRect, area, GraphicsUnit.Pixel); - } - - /// - /// returns true if x & y are inside the FastBitmap - /// - /// - /// - /// true if x & y are inside the FastBitmap - public bool Contains(int x, int y) - { - return area.Contains(x - Left, y - Top); - } - - public abstract Color GetColorAt(int x, int y); - - public abstract void SetColorAt(int x, int y, Color color); - - public abstract void GetColorAt(int x, int y, byte[] color); - - public abstract void SetColorAt(int x, int y, byte[] color); - - #region IFastBitmapWithClip - - bool IFastBitmapWithClip.Contains(int x, int y) - { - bool contains = Clip.Contains(x, y); - if (InvertClip) - { - return !contains; - } - else - { - return contains; - } - } - - void IFastBitmapWithClip.SetColorAt(int x, int y, byte[] color) - { - bool contains = Clip.Contains(x, y); - if ((InvertClip && contains) || (!InvertClip && !contains)) - { - return; - } - SetColorAt(x, y, color); - } - - void IFastBitmapWithClip.SetColorAt(int x, int y, Color color) - { - bool contains = Clip.Contains(x, y); - if ((InvertClip && contains) || (!InvertClip && !contains)) - { - return; - } - SetColorAt(x, y, color); - } - - #endregion IFastBitmapWithClip - - #region IFastBitmapWithOffset - - /// - /// returns true if x & y are inside the FastBitmap - /// - /// - /// - /// true if x & y are inside the FastBitmap - bool IFastBitmapWithOffset.Contains(int x, int y) - { - return area.Contains(x - Left, y - Top); - } - - Color IFastBitmapWithOffset.GetColorAt(int x, int y) - { - x -= left; - y -= top; - return GetColorAt(x, y); - } - - void IFastBitmapWithOffset.GetColorAt(int x, int y, byte[] color) - { - x -= left; - y -= top; - GetColorAt(x, y, color); - } - - void IFastBitmapWithOffset.SetColorAt(int x, int y, byte[] color) - { - x -= left; - y -= top; - SetColorAt(x, y, color); - } - - void IFastBitmapWithOffset.SetColorAt(int x, int y, Color color) - { - x -= left; - y -= top; - SetColorAt(x, y, color); - } - - #endregion IFastBitmapWithOffset - } - - /// - /// This is the implementation of the FastBitmat for the 8BPP pixelformat - /// - public unsafe class FastChunkyBitmap : FastBitmap - { - // Used for indexed images - private readonly Color[] colorEntries; - private readonly Dictionary colorCache = new Dictionary(); - - public FastChunkyBitmap(Bitmap source, Rectangle area) : base(source, area) - { - colorEntries = bitmap.Palette.Entries; - } - - /// - /// Get the color from the specified location - /// - /// - /// - /// Color - public override Color GetColorAt(int x, int y) - { - int offset = x + (y * stride); - byte colorIndex = pointer[offset]; - return colorEntries[colorIndex]; - } - - /// - /// Get the color from the specified location into the specified array - /// - /// - /// - /// byte[4] as reference - public override void GetColorAt(int x, int y, byte[] color) - { - throw new NotImplementedException("No performance gain!"); - } - - /// - /// Set the color at the specified location from the specified array - /// - /// - /// - /// byte[4] as reference - public override void SetColorAt(int x, int y, byte[] color) - { - throw new NotImplementedException("No performance gain!"); - } - - /// - /// Get the color-index from the specified location - /// - /// - /// - /// byte with index - public byte GetColorIndexAt(int x, int y) - { - int offset = x + (y * stride); - return pointer[offset]; - } - - /// - /// Set the color-index at the specified location - /// - /// - /// - /// - public void SetColorIndexAt(int x, int y, byte colorIndex) - { - int offset = x + (y * stride); - pointer[offset] = colorIndex; - } - - /// - /// Set the supplied color at the specified location. - /// Throws an ArgumentException if the color is not in the palette - /// - /// - /// - /// Color to set - public override void SetColorAt(int x, int y, Color color) - { - int offset = x + (y * stride); - byte colorIndex; - if (!colorCache.TryGetValue(color, out colorIndex)) - { - bool foundColor = false; - for (colorIndex = 0; colorIndex < colorEntries.Length; colorIndex++) - { - if (color == colorEntries[colorIndex]) - { - colorCache.Add(color, colorIndex); - foundColor = true; - break; - } - } - if (!foundColor) - { - throw new ArgumentException("No such color!"); - } - } - pointer[offset] = colorIndex; - } - } - - /// - /// This is the implementation of the IFastBitmap for 24 bit images (no Alpha) - /// - public unsafe class Fast24RGBBitmap : FastBitmap - { - public Fast24RGBBitmap(Bitmap source, Rectangle area) : base(source, area) - { - } - - /// - /// Retrieve the color at location x,y - /// Before the first time this is called the Lock() should be called once! - /// - /// X coordinate - /// Y Coordinate - /// Color - public override Color GetColorAt(int x, int y) - { - int offset = (x * 3) + (y * stride); - return Color.FromArgb(255, pointer[PIXELFORMAT_INDEX_R + offset], pointer[PIXELFORMAT_INDEX_G + offset], pointer[PIXELFORMAT_INDEX_B + offset]); - } - - /// - /// Set the color at location x,y - /// Before the first time this is called the Lock() should be called once! - /// - /// - /// - /// - public override void SetColorAt(int x, int y, Color color) - { - int offset = (x * 3) + (y * stride); - pointer[PIXELFORMAT_INDEX_R + offset] = color.R; - pointer[PIXELFORMAT_INDEX_G + offset] = color.G; - pointer[PIXELFORMAT_INDEX_B + offset] = color.B; - } - - /// - /// Get the color from the specified location into the specified array - /// - /// - /// - /// byte[4] as reference (r,g,b) - public override void GetColorAt(int x, int y, byte[] color) - { - int offset = (x * 3) + (y * stride); - color[PIXELFORMAT_INDEX_R] = pointer[PIXELFORMAT_INDEX_R + offset]; - color[PIXELFORMAT_INDEX_G] = pointer[PIXELFORMAT_INDEX_G + offset]; - color[PIXELFORMAT_INDEX_B] = pointer[PIXELFORMAT_INDEX_B + offset]; - } - - /// - /// Set the color at the specified location from the specified array - /// - /// - /// - /// byte[4] as reference (r,g,b) - public override void SetColorAt(int x, int y, byte[] color) - { - int offset = (x * 3) + (y * stride); - pointer[PIXELFORMAT_INDEX_R + offset] = color[PIXELFORMAT_INDEX_R]; - pointer[PIXELFORMAT_INDEX_G + offset] = color[PIXELFORMAT_INDEX_G]; - pointer[PIXELFORMAT_INDEX_B + offset] = color[PIXELFORMAT_INDEX_B]; - } - } - - /// - /// This is the implementation of the IFastBitmap for 32 bit images (no Alpha) - /// - public unsafe class Fast32RGBBitmap : FastBitmap - { - public Fast32RGBBitmap(Bitmap source, Rectangle area) : base(source, area) - { - } - - /// - /// Retrieve the color at location x,y - /// Before the first time this is called the Lock() should be called once! - /// - /// X coordinate - /// Y Coordinate - /// Color - public override Color GetColorAt(int x, int y) - { - int offset = (x * 4) + (y * stride); - return Color.FromArgb(255, pointer[PIXELFORMAT_INDEX_R + offset], pointer[PIXELFORMAT_INDEX_G + offset], pointer[PIXELFORMAT_INDEX_B + offset]); - } - - /// - /// Set the color at location x,y - /// Before the first time this is called the Lock() should be called once! - /// - /// - /// - /// - public override void SetColorAt(int x, int y, Color color) - { - int offset = (x * 4) + (y * stride); - pointer[PIXELFORMAT_INDEX_R + offset] = color.R; - pointer[PIXELFORMAT_INDEX_G + offset] = color.G; - pointer[PIXELFORMAT_INDEX_B + offset] = color.B; - } - - /// - /// Get the color from the specified location into the specified array - /// - /// - /// - /// byte[4] as reference (a,r,g,b) - public override void GetColorAt(int x, int y, byte[] color) - { - int offset = (x * 4) + (y * stride); - color[COLOR_INDEX_R] = pointer[PIXELFORMAT_INDEX_R + offset]; - color[COLOR_INDEX_G] = pointer[PIXELFORMAT_INDEX_G + offset]; - color[COLOR_INDEX_B] = pointer[PIXELFORMAT_INDEX_B + offset]; - } - - /// - /// Set the color at the specified location from the specified array - /// - /// - /// - /// byte[4] as reference (r,g,b) - public override void SetColorAt(int x, int y, byte[] color) - { - int offset = (x * 4) + (y * stride); - pointer[PIXELFORMAT_INDEX_R + offset] = color[COLOR_INDEX_R]; // R - pointer[PIXELFORMAT_INDEX_G + offset] = color[COLOR_INDEX_G]; - pointer[PIXELFORMAT_INDEX_B + offset] = color[COLOR_INDEX_B]; - } - } - - /// - /// This is the implementation of the IFastBitmap for 32 bit images with Alpha - /// - public unsafe class Fast32ARGBBitmap : FastBitmap, IFastBitmapWithBlend - { - public override bool hasAlphaChannel - { - get - { - return true; - } - } - - public Color BackgroundBlendColor - { - get; - set; - } - - public Fast32ARGBBitmap(Bitmap source, Rectangle area) : base(source, area) - { - BackgroundBlendColor = Color.White; - } - - /// - /// Retrieve the color at location x,y - /// - /// X coordinate - /// Y Coordinate - /// Color - public override Color GetColorAt(int x, int y) - { - int offset = (x * 4) + (y * stride); - return Color.FromArgb(pointer[PIXELFORMAT_INDEX_A + offset], pointer[PIXELFORMAT_INDEX_R + offset], pointer[PIXELFORMAT_INDEX_G + offset], pointer[PIXELFORMAT_INDEX_B + offset]); - } - - /// - /// Set the color at location x,y - /// Before the first time this is called the Lock() should be called once! - /// - /// - /// - /// - public override void SetColorAt(int x, int y, Color color) - { - int offset = (x * 4) + (y * stride); - pointer[PIXELFORMAT_INDEX_A + offset] = color.A; - pointer[PIXELFORMAT_INDEX_R + offset] = color.R; - pointer[PIXELFORMAT_INDEX_G + offset] = color.G; - pointer[PIXELFORMAT_INDEX_B + offset] = color.B; - } - - /// - /// Get the color from the specified location into the specified array - /// - /// - /// - /// byte[4] as reference (r,g,b,a) - public override void GetColorAt(int x, int y, byte[] color) - { - int offset = (x * 4) + (y * stride); - color[COLOR_INDEX_R] = pointer[PIXELFORMAT_INDEX_R + offset]; - color[COLOR_INDEX_G] = pointer[PIXELFORMAT_INDEX_G + offset]; - color[COLOR_INDEX_B] = pointer[PIXELFORMAT_INDEX_B + offset]; - color[COLOR_INDEX_A] = pointer[PIXELFORMAT_INDEX_A + offset]; - } - - /// - /// Set the color at the specified location from the specified array - /// - /// - /// - /// byte[4] as reference (r,g,b,a) - public override void SetColorAt(int x, int y, byte[] color) - { - int offset = (x * 4) + (y * stride); - pointer[PIXELFORMAT_INDEX_R + offset] = color[COLOR_INDEX_R]; // R - pointer[PIXELFORMAT_INDEX_G + offset] = color[COLOR_INDEX_G]; - pointer[PIXELFORMAT_INDEX_B + offset] = color[COLOR_INDEX_B]; - pointer[PIXELFORMAT_INDEX_A + offset] = color[COLOR_INDEX_A]; - } - - /// - /// Retrieve the color, without alpha (is blended), at location x,y - /// Before the first time this is called the Lock() should be called once! - /// - /// X coordinate - /// Y Coordinate - /// Color - public Color GetBlendedColorAt(int x, int y) - { - int offset = (x * 4) + (y * stride); - int a = pointer[PIXELFORMAT_INDEX_A + offset]; - int red = pointer[PIXELFORMAT_INDEX_R + offset]; - int green = pointer[PIXELFORMAT_INDEX_G + offset]; - int blue = pointer[PIXELFORMAT_INDEX_B + offset]; - - if (a < 255) - { - // As the request is to get without alpha, we blend. - int rem = 255 - a; - red = (red * a + BackgroundBlendColor.R * rem) / 255; - green = (green * a + BackgroundBlendColor.G * rem) / 255; - blue = (blue * a + BackgroundBlendColor.B * rem) / 255; - } - return Color.FromArgb(255, red, green, blue); - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Core/FilenameHelper.cs b/Greenshot.ImageEditor/Core/FilenameHelper.cs deleted file mode 100644 index 028c224dd..000000000 --- a/Greenshot.ImageEditor/Core/FilenameHelper.cs +++ /dev/null @@ -1,661 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.IniFile; -using Greenshot.Plugin; -using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Text.RegularExpressions; -using System.Windows.Forms; - -namespace GreenshotPlugin.Core -{ - public static class FilenameHelper - { - // Specify the regular expression for the filename formatting: - // Starting with ${ - // than the varname, which ends with a : or } - // If a parameters needs to be supplied, than a ":" should follow the name... everything from the : until the } is considered to be part of the parameters. - // The parameter format is a single alpha followed by the value belonging to the parameter, e.g. : - // ${capturetime:d"yyyy-MM-dd HH_mm_ss"} - private static readonly Regex VAR_REGEXP = new Regex(@"\${(?[^:}]+)[:]?(?[^}]*)}", RegexOptions.Compiled); - private static readonly Regex CMD_VAR_REGEXP = new Regex(@"%(?[^%]+)%", RegexOptions.Compiled); - - private static readonly Regex SPLIT_REGEXP = new Regex(";(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", RegexOptions.Compiled); - private const int MAX_TITLE_LENGTH = 80; - private static readonly CoreConfiguration conf = IniConfig.GetIniSection(); - private const string UNSAFE_REPLACEMENT = "_"; - - /// - /// Remove invalid characters from the fully qualified filename - /// - /// string with the full path to a file - /// string with the full path to a file, without invalid characters - public static string MakeFQFilenameSafe(string fullPath) - { - string path = MakePathSafe(Path.GetDirectoryName(fullPath)); - string filename = MakeFilenameSafe(Path.GetFileName(fullPath)); - // Make the fullpath again and return - return Path.Combine(path, filename); - } - - /// - /// Remove invalid characters from the filename - /// - /// string with the full path to a file - /// string with the full path to a file, without invalid characters - public static string MakeFilenameSafe(string filename) - { - // Make the filename save! - if (filename != null) - { - foreach (char disallowed in Path.GetInvalidFileNameChars()) - { - filename = filename.Replace(disallowed.ToString(), UNSAFE_REPLACEMENT); - } - } - return filename; - } - - /// - /// Remove invalid characters from the path - /// - /// string with the full path to a file - /// string with the full path to a file, without invalid characters - public static string MakePathSafe(string path) - { - // Make the path save! - if (path != null) - { - foreach (char disallowed in Path.GetInvalidPathChars()) - { - path = path.Replace(disallowed.ToString(), UNSAFE_REPLACEMENT); - } - } - return path; - } - - public static string GetFilenameWithoutExtensionFromPattern(string pattern) - { - return GetFilenameWithoutExtensionFromPattern(pattern, null); - } - - public static string GetFilenameWithoutExtensionFromPattern(string pattern, ICaptureDetails captureDetails) - { - return FillPattern(pattern, captureDetails, true); - } - - public static string GetFilenameFromPattern(string pattern, OutputFormat imageFormat) - { - return GetFilenameFromPattern(pattern, imageFormat, null); - } - - public static string GetFilenameFromPattern(string pattern, OutputFormat imageFormat, ICaptureDetails captureDetails) - { - return FillPattern(pattern, captureDetails, true) + "." + imageFormat.ToString().ToLower(); - } - - /// - /// Return a filename for the current image format (png,jpg etc) with the default file pattern - /// that is specified in the configuration - /// - /// A string with the format - /// The filename which should be used to save the image - public static string GetFilename(OutputFormat format, ICaptureDetails captureDetails) - { - string pattern = conf.OutputFileFilenamePattern; - if (pattern == null || string.IsNullOrEmpty(pattern.Trim())) - { - pattern = "greenshot ${capturetime}"; - } - return GetFilenameFromPattern(pattern, format, captureDetails); - } - - /// - /// This method will be called by the regexp.replace as a MatchEvaluator delegate! - /// Will delegate this to the MatchVarEvaluatorInternal and catch any exceptions - /// What are we matching? - /// The detail, can be null - /// Variables from the process - /// Variables from the user - /// Variables from the machine - /// string with the match replacement - private static string MatchVarEvaluator(Match match, ICaptureDetails captureDetails, IDictionary processVars, IDictionary userVars, IDictionary machineVars, bool filenameSafeMode) - { - try - { - return MatchVarEvaluatorInternal(match, captureDetails, processVars, userVars, machineVars, filenameSafeMode); - } - catch (Exception e) - { - LOG.Error("Error in MatchVarEvaluatorInternal", e); - } - return ""; - } - - /// - /// This method will be called by the regexp.replace as a MatchEvaluator delegate! - /// - /// What are we matching? - /// The detail, can be null - /// - private static string MatchVarEvaluatorInternal(Match match, ICaptureDetails captureDetails, IDictionary processVars, IDictionary userVars, IDictionary machineVars, bool filenameSafeMode) - { - // some defaults - int padWidth = 0; - int startIndex = 0; - int endIndex = 0; - char padChar = ' '; - string dateFormat = "yyyy-MM-dd HH-mm-ss"; - IDictionary replacements = new Dictionary(); - string replaceValue = ""; - string variable = match.Groups["variable"].Value; - string parameters = match.Groups["parameters"].Value; - - if (parameters != null && parameters.Length > 0) - { - string[] parms = SPLIT_REGEXP.Split(parameters); - foreach (string parameter in parms) - { - switch (parameter.Substring(0, 1)) - { - // Padding p[,pad-character] - case "p": - string[] padParams = parameter.Substring(1).Split(new[] { ',' }); - try - { - padWidth = int.Parse(padParams[0]); - } - catch - { - }; - if (padParams.Length > 1) - { - padChar = padParams[1][0]; - } - break; - // replace - // r, - case "r": - string[] replaceParameters = parameter.Substring(1).Split(new[] { ',' }); - if (replaceParameters != null && replaceParameters.Length == 2) - { - replacements.Add(replaceParameters[0], replaceParameters[1]); - } - break; - // Dateformat d - // Format can be anything that is used in C# date formatting - case "d": - dateFormat = parameter.Substring(1); - if (dateFormat.StartsWith("\"")) - { - dateFormat = dateFormat.Substring(1); - } - if (dateFormat.EndsWith("\"")) - { - dateFormat = dateFormat.Substring(0, dateFormat.Length - 1); - } - break; - // Substring: - // s[,length] - case "s": - string range = parameter.Substring(1); - string[] rangelist = range.Split(new[] { ',' }); - if (rangelist.Length > 0) - { - try - { - startIndex = int.Parse(rangelist[0]); - } - catch - { - // Ignore - } - } - if (rangelist.Length > 1) - { - try - { - endIndex = int.Parse(rangelist[1]); - } - catch - { - // Ignore - } - } - break; - } - } - } - if (processVars != null && processVars.Contains(variable)) - { - replaceValue = (string)processVars[variable]; - if (filenameSafeMode) - { - replaceValue = MakePathSafe(replaceValue); - } - } - else if (userVars != null && userVars.Contains(variable)) - { - replaceValue = (string)userVars[variable]; - if (filenameSafeMode) - { - replaceValue = MakePathSafe(replaceValue); - } - } - else if (machineVars != null && machineVars.Contains(variable)) - { - replaceValue = (string)machineVars[variable]; - if (filenameSafeMode) - { - replaceValue = MakePathSafe(replaceValue); - } - } - else if (captureDetails != null && captureDetails.MetaData != null && captureDetails.MetaData.ContainsKey(variable)) - { - replaceValue = captureDetails.MetaData[variable]; - if (filenameSafeMode) - { - replaceValue = MakePathSafe(replaceValue); - } - } - else - { - // Handle other variables - // Default use "now" for the capture take´n - DateTime capturetime = DateTime.Now; - // Use default application name for title - string title = Application.ProductName; - - // Check if we have capture details - if (captureDetails != null) - { - capturetime = captureDetails.DateTime; - if (captureDetails.Title != null) - { - title = captureDetails.Title; - if (title.Length > MAX_TITLE_LENGTH) - { - title = title.Substring(0, MAX_TITLE_LENGTH); - } - } - } - switch (variable) - { - case "domain": - replaceValue = Environment.UserDomainName; - break; - case "user": - replaceValue = Environment.UserName; - break; - case "hostname": - replaceValue = Environment.MachineName; - break; - case "YYYY": - if (padWidth == 0) - { - padWidth = -4; - padChar = '0'; - } - replaceValue = capturetime.Year.ToString(); - break; - case "MM": - replaceValue = capturetime.Month.ToString(); - if (padWidth == 0) - { - padWidth = -2; - padChar = '0'; - } - break; - case "DD": - replaceValue = capturetime.Day.ToString(); - if (padWidth == 0) - { - padWidth = -2; - padChar = '0'; - } - break; - case "hh": - if (padWidth == 0) - { - padWidth = -2; - padChar = '0'; - } - replaceValue = capturetime.Hour.ToString(); - break; - case "mm": - if (padWidth == 0) - { - padWidth = -2; - padChar = '0'; - } - replaceValue = capturetime.Minute.ToString(); - break; - case "ss": - if (padWidth == 0) - { - padWidth = -2; - padChar = '0'; - } - replaceValue = capturetime.Second.ToString(); - break; - case "now": - replaceValue = DateTime.Now.ToString(dateFormat); - if (filenameSafeMode) - { - replaceValue = MakeFilenameSafe(replaceValue); - } - break; - case "capturetime": - replaceValue = capturetime.ToString(dateFormat); - if (filenameSafeMode) - { - replaceValue = MakeFilenameSafe(replaceValue); - } - break; - case "NUM": - conf.OutputFileIncrementingNumber++; - IniConfig.Save(); - replaceValue = conf.OutputFileIncrementingNumber.ToString(); - if (padWidth == 0) - { - padWidth = -6; - padChar = '0'; - } - - break; - case "title": - replaceValue = title; - if (filenameSafeMode) - { - replaceValue = MakeFilenameSafe(replaceValue); - } - break; - case "MyPictures": - replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures); - break; - case "MyMusic": - replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.MyMusic); - break; - case "MyDocuments": - replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); - break; - case "Personal": - replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.Personal); - break; - case "Desktop": - replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); - break; - case "ApplicationData": - replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); - break; - case "LocalApplicationData": - replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); - break; - } - } - // do padding - if (padWidth > 0) - { - replaceValue = replaceValue.PadRight(padWidth, padChar); - } - else if (padWidth < 0) - { - replaceValue = replaceValue.PadLeft(-padWidth, padChar); - } - - // do substring - if (startIndex != 0 || endIndex != 0) - { - if (startIndex < 0) - { - startIndex = replaceValue.Length + startIndex; - } - if (endIndex < 0) - { - endIndex = replaceValue.Length + endIndex; - } - if (endIndex != 0) - { - try - { - replaceValue = replaceValue.Substring(startIndex, endIndex); - } - catch - { - // Ignore - } - } - else - { - try - { - replaceValue = replaceValue.Substring(startIndex); - } - catch - { - // Ignore - } - } - } - - // new for feature #697 - if (replacements.Count > 0) - { - foreach (string oldValue in replacements.Keys) - { - replaceValue = replaceValue.Replace(oldValue, replacements[oldValue]); - } - } - return replaceValue; - } - - /// - /// "Simply" fill the pattern with environment variables - /// - /// String with pattern %var% - /// true to make sure everything is filenamesafe - /// Filled string - public static string FillCmdVariables(string pattern, bool filenameSafeMode) - { - IDictionary processVars = null; - IDictionary userVars = null; - IDictionary machineVars = null; - try - { - processVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Process); - } - catch (Exception e) - { - LOG.Error("Error retrieving EnvironmentVariableTarget.Process", e); - } - - try - { - userVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.User); - } - catch (Exception e) - { - LOG.Error("Error retrieving EnvironmentVariableTarget.User", e); - } - - try - { - machineVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Machine); - } - catch (Exception e) - { - LOG.Error("Error retrieving EnvironmentVariableTarget.Machine", e); - } - - return CMD_VAR_REGEXP.Replace(pattern, - delegate (Match m) - { - return MatchVarEvaluator(m, null, processVars, userVars, machineVars, filenameSafeMode); - } - ); - } - - /// - /// "Simply" fill the pattern with environment variables - /// - /// String with pattern ${var} - /// true to make sure everything is filenamesafe - /// Filled string - public static string FillVariables(string pattern, bool filenameSafeMode) - { - IDictionary processVars = null; - IDictionary userVars = null; - IDictionary machineVars = null; - try - { - processVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Process); - } - catch (Exception e) - { - LOG.Error("Error retrieving EnvironmentVariableTarget.Process", e); - } - - try - { - userVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.User); - } - catch (Exception e) - { - LOG.Error("Error retrieving EnvironmentVariableTarget.User", e); - } - - try - { - machineVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Machine); - } - catch (Exception e) - { - LOG.Error("Error retrieving EnvironmentVariableTarget.Machine", e); - } - - return VAR_REGEXP.Replace(pattern, - delegate (Match m) - { - return MatchVarEvaluator(m, null, processVars, userVars, machineVars, filenameSafeMode); - } - ); - } - - /// - /// Fill the pattern wit the supplied details - /// - /// Pattern - /// CaptureDetails, can be null - /// Should the result be made "filename" safe? - /// Filled pattern - public static string FillPattern(string pattern, ICaptureDetails captureDetails, bool filenameSafeMode) - { - IDictionary processVars = null; - IDictionary userVars = null; - IDictionary machineVars = null; - try - { - processVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Process); - } - catch (Exception e) - { - LOG.Error("Error retrieving EnvironmentVariableTarget.Process", e); - } - - try - { - userVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.User); - } - catch (Exception e) - { - LOG.Error("Error retrieving EnvironmentVariableTarget.User", e); - } - - try - { - machineVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Machine); - } - catch (Exception e) - { - LOG.Error("Error retrieving EnvironmentVariableTarget.Machine", e); - } - - try - { - return VAR_REGEXP.Replace(pattern, - delegate (Match m) - { - return MatchVarEvaluator(m, captureDetails, processVars, userVars, machineVars, filenameSafeMode); - } - ); - } - catch (Exception e) - { - // adding additional data for bug tracking - if (captureDetails != null) - { - e.Data.Add("title", captureDetails.Title); - } - e.Data.Add("pattern", pattern); - throw; - } - } - - /// - /// Checks whether a directory name is valid in the current file system - /// - /// directory name (not path!) - /// true if directory name is valid - public static bool IsDirectoryNameValid(string directoryName) - { - var forbiddenChars = Path.GetInvalidPathChars(); - foreach (var forbiddenChar in forbiddenChars) - { - if (directoryName == null || directoryName.Contains(forbiddenChar.ToString())) - { - return false; - } - } - return true; - } - - /// - /// Checks whether a filename is valid in the current file system - /// - /// name of the file - /// true if filename is valid - public static bool IsFilenameValid(string filename) - { - var forbiddenChars = Path.GetInvalidFileNameChars(); - foreach (var forbiddenChar in forbiddenChars) - { - if (filename == null || filename.Contains(forbiddenChar.ToString())) - { - return false; - } - } - return true; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Core/GreenshotResources.cs b/Greenshot.ImageEditor/Core/GreenshotResources.cs deleted file mode 100644 index c6918ecaf..000000000 --- a/Greenshot.ImageEditor/Core/GreenshotResources.cs +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System.ComponentModel; -using System.Drawing; - -namespace GreenshotPlugin.Core -{ - /// - /// Centralized storage of the icons & bitmaps - /// - public static class GreenshotResources - { - private static readonly ComponentResourceManager greenshotResources = new ComponentResourceManager(typeof(GreenshotResources)); - - public static Image getImage(string imageName) - { - return (Image)greenshotResources.GetObject(imageName); - } - - public static Icon getIcon(string imageName) - { - return (Icon)greenshotResources.GetObject(imageName); - } - - public static Icon getGreenshotIcon() - { - return getIcon("Greenshot.Icon"); - } - - public static Image getGreenshotImage() - { - return getImage("Greenshot.Image"); - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Core/GreenshotResources.resx b/Greenshot.ImageEditor/Core/GreenshotResources.resx deleted file mode 100644 index 5613cbe7e..000000000 --- a/Greenshot.ImageEditor/Core/GreenshotResources.resx +++ /dev/null @@ -1,471 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - - AAABAAUAAAAAAAEACAClFwAAVgAAADAwAAABAAgAqA4AAPsXAAAgIAAAAQAIAKgIAACjJgAAGBgAAAEA - CADIBgAASy8AABAQAAABAAgAaAUAABM2AACJUE5HDQoaCgAAAA1JSERSAAABAAAAAQAIBgAAAFxyqGYA - ABdsSURBVHja7Z1fqFVVHsf3YQqnUTJQSJMcujkK3UHuFW5geBXGYK5B0EP6Gto8zIsG8zKY82rCvKXP - 6bv2FqQP9eAfEhS8Eilozo0xTAOFbGycKLjTd9u6nnvvXnuvvff6/dbea30/cEioPPucs9Z3/dbv72By - cnI2I4QkyYACQEi6UAAISRgKACEJQwEgJGEoAIQkDAWAkIShABCSMBQAQhKGAkBIwlAACEkYCgAhCUMB - ICRhKACEJAwFgJCEoQAQkjAUAEIShgJASMJQAAhJGAoAIQlDASAkYSgAhCQMBYCQhKEAEJIwFABCEoYC - QEjCUAAISRgKACEJQwEgJGEoAIQkDAWAkIShABCSMBQAQhKGAkBIwlAACEkYCgAhCUMBICRhKACEJAwF - gJCEoQAQkjAUAEIShgJASMJQAAhJmOgF4MllP2dP/+GH/M8rx77L7t9Ylv304Ins4e0l2X/v/Db04xES - lCgF4Her/pc9v+PbbNXkvezpdT9Y/7uHd5Zkt8+tzL4++Wz2/ZdLQz82IepEJQDY+Ov33Myen/q29v97 - 7/Ly7Nqx32f3ppeH/hiEqBGNAIzsvJVv/ieX/tzq75n5cE12/eja/JpASOxEIQBj715vdOrb+P7G0uyz - fRspAiR6ei8Avje/gSJAUqDXArBh97+z9btviv398AtABAiJld4KwIrx+9kr738u/j5XjoxkMyfWhP64 - hIjQWwF45fDn2Yqx++Lv89MPT2Sf7pzgVYBESS8FQOv0N1w/tjYPERISG70UgIn3rmarttxTez9YAad2 - bA79sQnxTu8EAKm9Ux+fV3/fiwdeyu6cXRH64xPild4JANJ7Jw5eVX9fJAhdOTwS+uMT4pXeCYB06M9G - m5AgfBYoRDJ/BihK+vk/v8nuXn6G6cckGL0TAO37vwGFQ5/setn5v0cFItKTYbFUpSfDx4DrBYqSKAZE - k94JgFb4r4iPtk5W/jcoSBrdN9NYpGBpfHHkRVYnEhUoADWoEgCUIGPzty1IAkxAIhr0TgBCXQFQG3B6 - zybrv8fGH3nzltf3/PrUs9nl99arf1aSDr0TgC46ASWfiSJAJOmdAIQKA9qyATWyEi8fWp87CAnxTe8E - IFQi0Om3Ny1yzOFZth29lD216kfR92Y9ApHCSQDg2cZJh38ivIWFj4aaprEmQleaDTalegDYsIUANa8j - vAoQCawCgE0OrzZi2S4nHJxk8Fojni19UnWhGAjfz/YTF714/F35dNcEOxkTrxQKAE62F3Z902hxw1xF - Tz3pEFbocmCI49j+6+LvPwxDg8Q38wQAJj7CbGWttF2B1/ziuy+JWQN41q3HpsVPYFsRUIhwZFUokpC6 - zAkA7vY4VX1uKNydLxwYFctqkz6Fy+7dUyfPq5r/hlOvbaYzkHgjFwCJzW+ACODUklq0kk1BbactrI/t - xy+KfJ4qPntnY+16ATxvPiTll985d+gOXZ1gqRlHrrYzl4Rn8Kcdm2ex+X2Y/Takm2v6zsK7c25FfvLb - REvbCTlMHQHAc+YFSTWuKvjs8DOwKCkNBn89sWbWdwprEdIOLJxwsAbaWDGuDsyQAuDyPeKUx3fRxkkK - 0YYI0iKIm8E/ZzOVRCCNZBaE5nDiNYlg4L6Pze+y4LtsAfgQQgN+M4gAOyHFi5oAAK3mmhACbAS8sFlt - mwGnHBY3XnVOOtylt31wSetrm0eZAEg5RZmKHC+qAlC3qYYvYBI/tfpxMhOskLaRidfPnFX/HMCWDCRd - I9HE+Ui6j6oAgKKc+j6CGgBJx2kRNgHVyEpkPUKcqAtALNls8DWM7p1RfU9bY1KtpCTWI8SHugA0XUTm - Pr983YNHBUm/nnaI1+NUgnl6+9xKNesiRC5AkfWk7ZCMxYIjj1AXgDo5Adhk8OjDueVq3sJMhoUBp5W0 - uapZlWj73rQrI2kFxEVnBaBNQRKAEKC5pmQIS9MKKHLCheqNwHTkeOicAGBR407rq9JP+sTS6Algu/uH - 6o7EKUnxoC4ASDVFlWAR2PwSacnSIiBZmgwfBwSz6MQN1R/RRz6HaSwDTGMZoo+6ANgWj9TmN0iKgNSz - l21+EKpFepPaDmx4+HIwIcn2PeHvxTUH/hsKgg7qAmBLKNEIZUmGICECcMj5+gwu/RT6IACIUvxx779q - iyPeAwcFk49kURUA25htrVCWRjIL8gPW77nZ2HmJZ/zq+HNOJnaXBcCXLweWG/wfdDrKoCoANjNccyFr - hLGaFCVh48P0xeZ3NX+7KgC++0vgKjR9aAPzDwRQFYCiPPYQlXWaYSxbAhMwzThMQVJdQglAmSNXqrkM - BBKiQxHwy+Dv08tnNRaR7eTVTmQBsVS3dS0KIN2nscopSuoz+PPOiVnp5ppld+8QvfXKTrA+Eaovgc2R - q2GRxPLbdYW8J6B0c03bgglVV29zRvYRbQG1fXeabdJZmuyPua7AIZpJhOysE0s6q8RU4jJsWYmvHr8g - PiLNIN1jMiXmzQXwOd/epZ1UqDssiOUU0a5KLHLkhkhJZlWiHxZNBoJZjsQNjYaSFAA/aH2PNudfiCEp - NkuE1MM6GxDWAF51hKBu9laIphqGmARAOo0alM1JCOHI5ZQkP1ROBzZDJeamAw8tMvwIZqhE3caaIKQP - 4KOtk0HeVwrJ4S5lMfiQDVLb/IZmPeNluH9jWb6GU7paOI0HlyLUhJ1QzUmlkRCBqgScLrdIXwgOMli1 - VdcVfGYcaKgbiV0MggoA0PQeG2LuauNzwCssPMTcyyy7EFOSDa4CgI0Pv1aTdYZrLRrLxCoEgzf2bcwF - IFRNtnYYC6TQ0KLtiHfXgqQu+3F8VmhqzbTQZlEtQNNhGU3RvgbElARUhSlKwintcvrhaoScDZi+rjkS - Xb0C4Do0vv+aV8eo9Mj7EJQWA9UZl9UGzXqAWJW8CmwINOPAgBQUJhng+IL1d/fyM43M3C4mc0nWJMSW - hORUDSi9abSsAOlR5akSYkpSmSNXemhLTDkIzuXA0uaPRjJLTLH/LhGiLNnmyNVKioplLdXqByBdjil5 - FYilBLiLhIgEFG1ATX9SLKHk2g1BpMsxJUQg1Xu/FhqzCYexbT7t3hIxHCqNOgJJz/fzFRqExx93tb7/ - SH1As67DtvG0U5JjcAg2EgCN5ppNu8kaYKlg87O9tA6wAuB8k07qsm26UENS+l5W3rgnoJYn1DV9E6SU - wtlFpEOC+H3P7B4vFPUQCWWg70lljQVAe148Tph5zTV/nSqDxWDi2DF4ZfuOpEOwbLOFapDad/9Sq67A - MThBiH98i4BLc5kQJcmg7z0KWwlAzEU1pB2w1pCK29Yn4DoTIEQyEui7I7CVALRpygAT3qSnDoPUVPzY - dN71nyYDUgx1CpIABaAZrQeD1GnKgAUBpx4WRZV3H7He2+dW1pqUQ7oJfvfckYvGMhX3dJjUMPXrXi1D - lJWDvlvBagLQpjxVqyiJ6LCwGw+sPjiT2zhx6QRshrgA+CrLZFIPKSNUg9m+1wSICgCUHt1pfHpn+25y - ERlC9CaMobdEKwEoK4iQ/EEoAqQIbT9ADOuwlQDYYqDSQyIBcxDIQrSrEouGpPQNkUQgDYdMWVooSRct - KyCG0x+0EoCiQgjNFlGx/AjEHxrrL6bDp7EA2DafdjgmBjOM+EW6MKjvBUDDNBaAoo0XwhMbU3824g+p - 5iCx+Z4aCYBt04UoyYylNRPxj28RiG3zg9oCUNYXMFQ2Fq8BxAbSjyEEbSJSrgVJfaSWAFQ5P0IVZMR0 - JyP+aVqUBOsSab6xnfrDOAsAvowLB0atKogveerj80E+RN/zsYke+cj78fuPhqQUhAtx2qM2wUzHih0n - AUDCDzz+Zd1/Qk6IoQCQpiBpDdOSQs3GDE2pAODUx2RUFyWkABDSPxYJgGms2cQECuUDkG5TTkisDP5y - dG0uAGiqCRO/jaczVF+2vpdkEhKKweTkZKty4GFQ+utjFntd6nQlIoQ8xqsAINQyundG9QP0vSsrISHx - KgAhQoExZmcRooVXAQCaAxq1h5MQEhveBUBzRDPDf4S0w7sAAI0GjW1mEhBCHiEiAECyMAimPwqSYizO - IEQTMQGAQxAi0LYd+EK4+Qnxx+CtwyOzUll0EAHkBviyBLj5CfHL4OCDJ2al+5v58Am4FCQRQuqR1wJo - NNdEdGD9npu1Q4QYvghPP1N9CfHPXDGQVlcdMyA0HxQ5fr+wdgCbHjXZSPChuU+IHHMCELKiztRk85Qn - RJc5AWBcnZD0mNcPgFV1hKTFPAFoUlePWQDos7Z83YNF4T6E7XCHx995+9xK3ucJ6RiNBQCbHuG9OnPY - cM2An4HVe4R0g9oCAM/9+P5rrQYwwsuPXoO0CAgJSy0B8NnwA9cDTBeiNUBIOJwFgLPWCIkPpyiAdKsv - TvYhJAyVeQAaE39jmrdOSJ+ozATUGvjJ5p6E6FNaC4B8/YmDV9Ue5vTbmxgZIESR0mpA7XHfGlWJhJDH - 5AJQdPprNvcchunIhOiRjwYr6qyLTL+x/dfVH4gRAUL0sPYE1OzvPwxbfROih1UAtO//BkYDCNHDKgDb - jl7y3tHXBdQJoPEnIUQeqwC8fuZskAeiABCiR+euABQAQvTonADMfLgmrxIkhMhjFQCN+X5FhGxOSkhq - WAVAOw3YoNWenBBSMRtw6uT5wr79UrAzMSG6lArA6L6ZbOTNW2oPQ/OfEF1KBQD1AFuPTatYAegJ8OnO - Cc7+I0SRyvHgWs5AtgYjRJ9KAQDSWYFM/yUkDE4CIHkVgOMPiT80/QnRx0kAAHoDIjnIpwhw8xMSFmcB - ABjtPfHeVS8ZgjD70f2Hm5+QcNQSAEOTsWCGh3eW5FOB2PSDkPA0EgADhAAvF4sAJz42PT39hHSHVgJg - wNUAPoKVY98t+nd3Lz+Td/qlqU9I9/AiAISQfkIBICRhFglAmTmPKj0MD2W1HiFxMCcAKP+FQ2/VlnuV - /xM8+SjagUOPd3tC+svgjX0bZ8f3X2sU0kMBz1fHn8vFgEJASP+YNx68KbAILhwY5Vw/QnqGFwEAsAaQ - 2ccEH0L6gzcBABAB5PbTEggL/DnL1z3IVow/StBCohasNDhv8cLvA6GmM5d4FQDAxh5hQMXmC7u+yR25 - rgVbaMEORy6zM9PFuwAA1vfrgroMbP6mlZqoypw+tIGWW4KICAD47J2Nec4AkQM5GyjR9tWshT0Z00NM - ADjhRxaJ/gzg61PP5s5ckgZiAgDY418GnPxo09Ykd8MFjmhPB1EBoEkpg8bYNl7h0kBUAOgM9A+8/GP7 - r4u/D8KGn+x6OfTHJcKICgAXkX9ePX5BzPRfCFu1x4+oAICPtk6G/ozRoHX6Gyjg8UMB6BFoyOpSremT - iwdeYnp3xFAAegI8/1Mfn1d/35kP12RXDo+E/vhECApAT0Be/yvvf67+vr4mNpu6BPaH7BaiAsBkIH9o - zWgsoq6Iw1rJu0X/sunxKkpWgrCgYSycjExBDoeoANB89EcfBAAFSev33Myen/q21t8PMTAdpoguogJw - +u1NVHdPdF0AfDwfLEakITN7VA8xAWAIyS9dFQCf4+IAG8voIiYAzCf3y8jOW9no3pkg720TAN/ViMMw - CUkHEQHA6Q/PMb29/ggVBShz5ErWJLC7lA4iAsDkERleP3NW/T1tjlyNKwkPEnm8CwA9/3KEyAQscuTC - 27/12LT3XgRF8Copi1cBYDMJWdDsc+LgVbX3szlyx969XjvU1xT2mJTFmwDw5NchdDUgHH/bT1xUOf0N - 7Cshx+BvZ1fMtjErcUp8ceRF3vmV0HIG2lKAtSsSy56FtCefDYhFhTBTHSHgfMBwaJjgtiSuEH4IcOq1 - zVxnAsybDgznDu6ZEAQMllhoaiIkdP/GsrxVFE/8cEjG30FZDF7zCjJMmxZlWNdPrf5x3sRrrGMzJCVl - Fo0HJ/1ASgSqEnBChCJB3WiAGZSyesvdUsGCkxGHGT5zij0QKQA9BiKA64APk9w1BbfrAoCNP7pvptF3 - kqI/iwIQAXDMITGnqWmO5q2I4LgU4XRZAHylS+P7gBim4HMYvHV4ZJaDIvsPrAH4b7AJXK8FyNuAI7fO - PbirAuDbMYrIAzpax74v5vIA4ODDF5ziPSg2YAbDkYvpQXDmGnCiYbPDAdbUzA0lAGXp5VJRkRRSkRcl - AuFUgDkY84cmzdEYSlKEbcqUdE1C7DkIhZmAUL4LB0aTD5GQxYQoS7alJGslRcVcj2BNBWY5JikC14vt - xy+qvqctzVzTGol1zmVpLUAKdyBSH+1rQNHm0+6PEGuhW2UxEOf7kYVobj7bxtNOSY61KtGpGpCTYslC - NDYgNt2Z3eOLTv9QQ1JibHTjJADs708WolEWbEtLDtUeLcZrgHM/AFoBZCHIM4A/QEIEyjZbqA7JMR6E - zgIQo/qR9kiIQNVa0+xItJDYRt05CwD7/BMbCA3CJ9C2MhF3foT7qtqBh0pGAskKAGjTlAEnBRbKcGoq - ZsM9vL0kyvhqiiBJCKPBmlgDOPWvH13rtBYoAP6oJQB1/QBw1qBSDUUqZYsC1gXEoG5hCukm5jevihLg - d799bmX21fHnah0CKPcdefOW+ueK0QoWEQBsfDhqmqg0HC2oyaYQxAHWAiw/vAxtLT86Af3hVQAQGoIJ - 6EOd2WWY2AgVBoyxJsCbAEi0qILiIgsxtuwr0p6pk+dVW5ODGKdd1xIAW0GEZJPK2Msx+wKcuGiqieaa - w45c9BaAOQ+zXnNzaIcCY7z/A2cBQIjm1I7Nhf9O2ivLHIQwQNjh2YdTz6XdGDYJQnhw5kpbbdpViTGa - /8BZAGxFQVr14THmYXcZONrQVbeJmY3DAp596Q2jZQXEWggEnAUg9JioWE2wrgFTf3z/NS/XOVzfpg9t - ELsaaA0pjfnwcRIAm/mvHY6p6llP2iGR1ivdWEZ6YGrs108nAbDdf7SnxNAhKIdkYY+0CEjNK0xhvVUK - QOh+bAuJtTVTSKRHjQHpzeRbBFJpjlspALbYZ6hsLF4D/KOVWivtScehBP9FG6sU1gpqElIZR14qAGWb - LVRBRtMMQdMr3/zT4KNXfp/RDqdpWHA4nFxDl8PUKUiKBasAVJ20oQSgbj42FgJers+KRZDSoEjtwhrN - eHpekPTLK09gKhADnPZm0jVesZv7RSwSANeZACFSMYGrALQ1B/E+8P7Gfhpo/45lCWXSDFt+WN8pbviF - zAmASd5wzeIKNSfeRQB8nWquDSr6SihHLtvLdYfBP75cOosFjlcdReziFQDebHSm8f1csVYmhnLkxppW - 20cajwfX7stuKFs8ks905chIdJ7hUCLeZNaEmX4MqwXFSAtDljgY4Mg1d3riRmMBCDEjDtjSMjVOs9hM - 1y5acQtBlAI9Jqq6Sg1T9zqbMo0FAJlj2z64pP7ARX0JtZ4ltlFpXReAtqKeWky/CY0FAGw7ekk0e2wh - NtNRcyHHdH/tqgD4zkzEukFEJxbh9kkrAZDKwbZRZIJrJ7KEDGP5posCIJWWjFRkvCdFYD6tBABohQNt - iyZEh9hYykNDdde1WVHSNQkxNvVsS2sB0Iol22oSQuQjxFIiKl1Ka8MmoBqRpZiucD5oLQBA+iSxpSVr - m/+GWJqThJiya7tCaSYlsaL0MV4EAEi1Zyo7bUNlsoEmE2IQrVi95W7+3PjzcFgLd1QsShPH1lqg2s01 - bb+npj8iFgvOB94EAPheTFXmWqhMNlAnJwDOUjxrnasKPNcIX0nnHWiLaNHpG0LIaQU8wqsAANwrIQRt - CkxgYqOXXNXi77oA+KhP1whhaWV12k7eENN+Y8zsbIJ3AQCmnXTdrrJ1M7i6LAA+n026pZZGc9eyzroh - HLmMCDxCRAAMJn/b5HAXLTAzGNTUZNchlBcblE1KljjRpEVA2gy3CWYoRy6IbdJvE0QFoIjhmuy299tQ - 6chlyUCSVklfm2uWNZcJ6ciNcdRXXdQFwDchGpPYUpI1FrN0RpsPH44BgoXvqUzotbNJh4mtuKsJ/wfb - mhgAeoKg9wAAAABJRU5ErkJggigAAAAwAAAAYAAAAAEACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8 - PDwAOkE+ADpEPwA5RUAAN01DADdORAA4SUEAOExDADVRRAA0VUYANFhHADNaSAA0WUgAMl1JAC9nTQAu - ak4ALWxPADFgSwAwY0wAMGRMAC1uUAAscVEAKnRSACp3VAApeVQAKH1WACeAVwAmg1gAJYVZACSIWgAk - i1wAIo1cACGSXgAhlF8AH5lhAB6cYgAdn2QAIJZgACCYYQAcomQAG6ZmABykZQAbqGcAGqpoABmtaQAX - smsAFrVsABixagAVuW4AFLxvABO/cAAUvnAADs52ABLAcQARx3MAEcd0ABDKdAAO0HcADdJ4AAzWeQAL - 2XoADNh6AAndfAAH5X8ACOJ+AAjkfwAH5oAABumBAATuggAD8oUABPCEAAL1hQAB+IcAAfqIAAD+iQBx - /50Akf+yALH/yQDR/98A////AAAAAAACLwAABFAAAAZwAAAIkAAACrAAAAvPAAAO8AAAIP8SAD3/MQBb - /1EAef9xAJj/kQC1/7EA1P/RAP///wAAAAAAFC8AACJQAAAwcAAAPZAAAEywAABZzwAAZ/AAAHj/EQCK - /zEAnP9RAK7/cQDA/5EA0v+xAOT/0QD///8AAAAAACYvAABAUAAAWnAAAHSQAACOsAAAqc8AAMLwAADR - /xEA2P8xAN7/UQDj/3EA6f+RAO//sQD2/9EA////AAAAAAAvJgAAUEEAAHBbAACQdAAAsI4AAM+pAADw - wwAA/9IRAP/YMQD/3VEA/+RxAP/qkQD/8LEA//bRAP///wAAAAAALxQAAFAiAABwMAAAkD4AALBNAADP - WwAA8GkAAP95EQD/ijEA/51RAP+vcQD/wZEA/9KxAP/l0QD///8AAAAAAC8DAABQBAAAcAYAAJAJAACw - CgAAzwwAAPAOAAD/IBIA/z4xAP9cUQD/enEA/5eRAP+2sQD/1NEA////AAAAAAAvAA4AUAAXAHAAIQCQ - ACsAsAA2AM8AQADwAEkA/xFaAP8xcAD/UYYA/3GcAP+RsgD/scgA/9HfAP///wAAAAAALwAgAFAANgBw - AEwAkABiALAAeADPAI4A8ACkAP8RswD/Mb4A/1HHAP9x0QD/kdwA/7HlAP/R8AD///8AAAAAACwALwBL - AFAAaQBwAIcAkAClALAAxADPAOEA8ADwEf8A8jH/APRR/wD2cf8A95H/APmx/wD70f8A////AAAAAAAb - AC8ALQBQAD8AcABSAJAAYwCwAHYAzwCIAPAAmRH/AKYx/wC0Uf8AwnH/AM+R/wDcsf8A69H/AP///wAA - AAAACAAvAA4AUAAVAHAAGwCQACEAsAAmAM8ALADwAD4R/wBYMf8AcVH/AIxx/wCmkf8Av7H/ANrR/wD/ - //8AAAAAAiYwJgIHSkpKSkkzBz1KSkEMAAAAJkpKSkAHPUpKSko7AAAAAAAAAAAAAAAAAAAAOUpKSj0C - SUpKSkoqAAIUFAIAAAACSUpKSkohHkpKSkodAAAAAAAAAAAAAAAAAgAUSkpKSkoXKUpKSkkMAAAAAAAA - AAAMSkpKSkorAB05ORsAAAAAAAAAAAAAAAAARBQZSkpKSkobAB4zLAwAAAAAAAAAAAAAQ0pKSkoZAAAA - BSQxHgIAAAAAAAAAAAAASkIFRUpKSkkFAAAAAAAAAAAAAAAAAAAAD0FKSSoAAAADQEpKSjMAAAAAAAAA - AAAASkoFFUJKQxcAAAAAAAAAAAAAAAAAAAAAAAIRBRMPAQAeSkpKSkoMAAAAAAAAAAAASkYCAAAHAAAA - AAAAAAAAAAAAAAAAAAAAAAAHOUpKQg0mSkpKSkoOAAAAAAAAAAAASR4AAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAApSkpKSjgRSkpKSkMCAAAAAAAAAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAACKkE9GQA4SkpKSkUB - HERKPhMAAAAAAAAAAAAAOUlBFwAAAAAAAAAAAAAAAAAAAAAvSkpKSRcvSkpKSj0AAAEHAAAAAAAAAAAA - AAAASkpKSREAAAAAAAAAAAAAAAAAAAJFSkpKSjAKQ0pKRxUAAAAAAAAAAAAAAAAAAAAASkpKSiYAAAAA - AAAAAAAAAAAAAAdGSkpKSjAABx4gCQAAAAAAAAAAAAAAAAAAAAAASkpKSh4AAAAAAAAAAAAAAAAAAAAs - SUpKShUAAAAAAAAAAAAAAAAAAAAAAAAAAAAASkpKQwUAAAAAAAAAAAAAAAAAAAACJEE5FwAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAIzcsDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAXMzMXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABlKSkpKGwAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADlKSkpKPQAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj1KSkpKQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAHyNKSkpKKQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAALwIqRUUsAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAEXIQ8A - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAATdKSkokAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAF0pKSkpKDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAASjcFJkpKSkpKFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIaIREAAAAAAAAA - AAAASko1D0pKSkpJBwAAAAAAAgAAAAAAAAAAAAAAAAAAAAAABj1KSkkeAAAAAAAAAAAASkpKAClKSkke - AgAAAAAAAAAAAAACAAAAAAAAAAACAgAAIUpKSkpFAgAAAAAAAAAASkpDAAAMFQURBQAAAAACAAAAAgAA - AAAAAAAAAjBKSTACL0pKSkpKCQAAAAAAAAAASkohAAAAEUFKSS8CAAAAAAAAAAAAAAAAAAAAKkpKSkoo - HEpKSkpDAAAAAAAAAAAALhcAAAAAPUpKSkoeAAAAAAIAAAAAAh4zLAwAQUpKSko+ATFKSkYVAAAAAAAA - AAAACS09LgkHSkpKSkozAAAAAAAAAAAAL0pKSkYJOkpKSko5AAANFAMAAAAAAAAAAAAAPkpKSkEHRkpK - SkopAAIAAAwXBQIHSUpKSkojGEpKSkkXAAAAAAAAAAAAAAAAAAAASkpKSkoZHkpKSkMFAAAAKUpKSR4M - SkpKSkoqABAtLw8AAAAAAAAAAAAAAAAAAAAASkpKSkoaABQpIQcAAAATSkpKSkkMPUpKSkoUAAAAAAAA - AAAAAAAAAAAAAAAAAAAAQ0pKSkYHAAAAGz5DKwceSkpKSkoXDDlKQx4AAAAAAAAAAAAAAAAAAAAAAAAA - AAAAEThGORMAAAAXSkpKSjAUSkpKSkoMAAICAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAx - SkpKSkkCMEpKSSoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwSkpKSkUCABUhDgAC - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPSkpKSisCAAAAAAAAAQAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFTg9JgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAgAAAgABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAAEAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIA - AAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAA - AKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIA - AAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAA - AKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIA - AAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAA - AKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCKAAAACAAAABA - AAAAAQAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADw9PQA6QT4AOkQ/ADlGQAA3TUMAN05EADhJQQA4 - TEMANVFFADRVRgAzWkgANFhIADJdSQAvZk0ALmlOADFhSgAwY0wAMGRMAC1tUAArc1IALHJRACp1UgAq - d1QAKXlUACh9VgAngFcAJoJYACWGWgAliVsAJItcACOOXAAkjFwAIZJeACGVXwAfmWEAHpxiAB2fZAAg - lmAAIJhhAByhZAAbp2cAHKVmABuoZwAaqWgAF7JrABezbAAXtWwAGLBqABa4bQAUvXAADs52ABLBcQAR - xXMAEch0AA7QdwAN0ngADNV5AAvaegAK3HwACeB9AAjlfwAH5oAABumBAAPyhQAE8YQAA/SFAAH4hwAB - +ogAAP6JAACwNgAAz0AAAPBKABH/WwAx/3EAUf+HAHH/nQCR/7IAsf/JANH/3wD///8AAAAAAAIvAAAE - UAAABnAAAAiQAAAKsAAAC88AAA7wAAAg/xIAPf8xAFv/UQB5/3EAmP+RALX/sQDU/9EA////AAAAAAAU - LwAAIlAAADBwAAA9kAAATLAAAFnPAABn8AAAeP8RAIr/MQCc/1EArv9xAMD/kQDS/7EA5P/RAP///wAA - AAAAJi8AAEBQAABacAAAdJAAAI6wAACpzwAAwvAAANH/EQDY/zEA3v9RAOP/cQDp/5EA7/+xAPb/0QD/ - //8AAAAAAC8mAABQQQAAcFsAAJB0AACwjgAAz6kAAPDDAAD/0hEA/9gxAP/dUQD/5HEA/+qRAP/wsQD/ - 9tEA////AAAAAAAvFAAAUCIAAHAwAACQPgAAsE0AAM9bAADwaQAA/3kRAP+KMQD/nVEA/69xAP/BkQD/ - 0rEA/+XRAP///wAAAAAALwMAAFAEAABwBgAAkAkAALAKAADPDAAA8A4AAP8gEgD/PjEA/1xRAP96cQD/ - l5EA/7axAP/U0QD///8AAAAAAC8ADgBQABcAcAAhAJAAKwCwADYAzwBAAPAASQD/EVoA/zFwAP9RhgD/ - cZwA/5GyAP+xyAD/0d8A////AAAAAAAvACAAUAA2AHAATACQAGIAsAB4AM8AjgDwAKQA/xGzAP8xvgD/ - UccA/3HRAP+R3AD/seUA/9HwAP///wAAAAAALAAvAEsAUABpAHAAhwCQAKUAsADEAM8A4QDwAPAR/wDy - Mf8A9FH/APZx/wD3kf8A+bH/APvR/wD///8AAAAAABsALwAtAFAAPwBwAFIAkABjALAAdgDPAIgA8ACZ - Ef8ApjH/ALRR/wDCcf8Az5H/ANyx/wDr0f8A////AAAAAAAIAC8ADgBQABUAcAAbAJAAIQCwACYAzwAs - APAAPhH/AFgx/wBxUf8AjHH/AKaR/wC/sf8A2tH/AP///wAAABg2KgdEQ0M2DzY4EgAANkRDHDpEQzkA - AAAAAAAAAAEIREREITZDQyYAAAAAAAdDREQ1ETg4EQAAAAAAAAAAOxJEREQpBx8WAAAAAAAAADpERCEA - AB81KQAAAAAAAABEGy1EOwUAAAAAAAAAAAAABx8YDAARQ0REGQAAAAAAAEQNAAIAAAAAAAAAAAAAAAAA - Cz5DORZDQ0MfAAAAAAAAGAAAAAAAAAAAAAAAAAAfKgsmQ0NDFjFDOAcAAAAAAAA+QBsAAAAAAAAAAAAA - JkRDQBlDQ0MLAAIAAAAAAAAAAEREPwAAAAAAAAAAAAAwQ0NDBRwuFAAAAAAAAAAAAAAAREQ+AAAAAAAA - AAAAABRDQzEAAAAAAAAAAAAAAAAAAAA0Ng4AAAAAAAAAAAAAAAcPAAAAAAAAAAAAAAAAAAAAAAAcOC4C - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACURERCYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAS - REREKQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABsrQzkFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAADQAAIS0RAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABACFEREEDAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAEMcLURERAsAAAAAAAAAAAAAAAAAAAACJi4LAAAAAAAAREENQUQ0AAAAAAAAAAAAAAAAAAIA - ACpERDwAAAAAAABEPAAHER8YAAAAAAAAAAAAAAAYQUEXNURERAIAAAAAADURAAA2REQjAAAAAAAABx8W - ADxERDsUQ0QvAAAAAAAAHjsxB0RERDYAAAAAAAA6REQhOERENgAHCwAAAAAAAABEREQjNUREHgAAJjsw - CERERDULMzELAAAAAAAAAAAAAERERCQCFhYUAw9EREQhNkRDGwAAAAAAAAAAAAAAAAAAJEA1BwAIQEQ+ - FERERCYCFxEAAAAAAAAAAAAAAAAAAAAAAAAAACFEREQZKUA1AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - DUREQwsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCcNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAGAAAADAAAAAB - AAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPDw8ADpBPgA6RD8AOkRAADdPRAA4SkEAOExDADZRRAA1 - VUYAM1pIADJeSQAxYEsAMGRMAC1tUAArc1IALHFRACp1UgAqd1QAKXlUACh9VgAngFcAJoJYACWFWQAk - iVsAJItcACONXAAkjFwAIpFeACGUXwAfmmIAHp5jACCWYAAgmGEAHaFkABumZgAcpGUAGqpoABitaQAV - uW4AFL5wAA/NdgASwXEAEcVzABDJdAAO0HcADdN4AAzVeQAL2HoACdx8AAjhfQAI5H8AB+eAAAbqgQAE - 7oMABPCEAAH4hwAB+ogAAP6JAFH/yABx/9MAkf/cALH/5QDR//AA////AAAAAAAALw4AAFAYAABwIgAA - kCwAALA2AADPQAAA8EoAEf9bADH/cQBR/4cAcf+dAJH/sgCx/8kA0f/fAP///wAAAAAAAi8AAARQAAAG - cAAACJAAAAqwAAALzwAADvAAACD/EgA9/zEAW/9RAHn/cQCY/5EAtf+xANT/0QD///8AAAAAABQvAAAi - UAAAMHAAAD2QAABMsAAAWc8AAGfwAAB4/xEAiv8xAJz/UQCu/3EAwP+RANL/sQDk/9EA////AAAAAAAm - LwAAQFAAAFpwAAB0kAAAjrAAAKnPAADC8AAA0f8RANj/MQDe/1EA4/9xAOn/kQDv/7EA9v/RAP///wAA - AAAALyYAAFBBAABwWwAAkHQAALCOAADPqQAA8MMAAP/SEQD/2DEA/91RAP/kcQD/6pEA//CxAP/20QD/ - //8AAAAAAC8UAABQIgAAcDAAAJA+AACwTQAAz1sAAPBpAAD/eREA/4oxAP+dUQD/r3EA/8GRAP/SsQD/ - 5dEA////AAAAAAAvAwAAUAQAAHAGAACQCQAAsAoAAM8MAADwDgAA/yASAP8+MQD/XFEA/3pxAP+XkQD/ - trEA/9TRAP///wAAAAAALwAOAFAAFwBwACEAkAArALAANgDPAEAA8ABJAP8RWgD/MXAA/1GGAP9xnAD/ - kbIA/7HIAP/R3wD///8AAAAAAC8AIABQADYAcABMAJAAYgCwAHgAzwCOAPAApAD/EbMA/zG+AP9RxwD/ - cdEA/5HcAP+x5QD/0fAA////AAAAAAAsAC8ASwBQAGkAcACHAJAApQCwAMQAzwDhAPAA8BH/APIx/wD0 - Uf8A9nH/APeR/wD5sf8A+9H/AP///wAAAAAAGwAvAC0AUAA/AHAAUgCQAGMAsAB2AM8AiADwAJkR/wCm - Mf8AtFH/AMJx/wDPkf8A3LH/AOvR/wD///8AAAAAAAgALwAOAFAAFQBwABsAkAAhALAAJgDPACwA8AA+ - Ef8AWDH/AHFR/wCMcf8AppH/AL+x/wDa0f8A////AAAMLSQhOTkTISMDADI5JC45LQAAAAAAABEmOTkR - LCcDAAAAAzg5KAYYGAQAAAAAADgUOC0DAAAAAwAAABEkDQMkOTQDAwAAADAAAwAAAwAAAAAAAAAkOScn - OTgGAAAAAB0RAAAAAAAAAAAkNhoyOTYEHg8AAAAAADk5CQAAAAAAAwM4OS8PJxQAAAAAAAMAADk4CAAD - AAAAAAAjMxgDAAADAAAAAAAAABEZDQAAAAAAAAAAAAAAAAAAAAAAAwAAAA85OREAAAADAAAAAAMAAAAA - AAAAAAAAABs5ORQAAAEAAAAAAwAAAAAAAAMAAAAAAA8WIAsAAAAAAAAAAAAAAAMAAAAAAwAAAAEGNjka - AAAAAAAAAAADAAAAAAAAAAAAADYWOTklAAAAAAAAAAAAAAADIycEAAAAADkgGiUKAAAAAAAAAAABGhoO - OTkhAAAAACgHACo5HgAAAAAADwsUOTkbNjgRAwAAACYxDjg5LwAABwMaOTgbOTkPAwYAAAAAADk5Jxoo - DwAbOTEhOTkMDAwAAAAAAAAAACo1EQAZNiQnOTkJHBMBAAMAAAMAAAMAAAAAAAAwOTgLJxwAAAAAAAAA - AAAAAAAAAAAAAAAWNCEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQABAAEAAQAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAQAAAAIAAAAAEACAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8PT0AOkE+ADlGQAA3TUMAOElBADhMQwA1U0UANVVGADNbSQAy - XUkALmtPAC5sTwAxYUsAMGJMAC1vUAArc1IAK3RTACh8VgAngFcAJ4FYACaEWQAkiVsAH5piACGVYAAg - mGEAHKJlABunZwAaqWgAGa1pABa1bAAYsGoAFbtvABS8bwAPzXYAEsJyABHEcgAQynUADtF4AAzVeQAL - 2nsACt18AAjifgAI5X8ABuuCAATvgwAD84UABPCEAAL2hgAB+YgAAP6JAABQNwAAcEwAAJBjAACweQAA - z48AAPCmABH/tAAx/74AUf/IAHH/0wCR/9wAsf/lANH/8AD///8AAAAAAAAvDgAAUBgAAHAiAACQLAAA - sDYAAM9AAADwSgAR/1sAMf9xAFH/hwBx/50Akf+yALH/yQDR/98A////AAAAAAACLwAABFAAAAZwAAAI - kAAACrAAAAvPAAAO8AAAIP8SAD3/MQBb/1EAef9xAJj/kQC1/7EA1P/RAP///wAAAAAAFC8AACJQAAAw - cAAAPZAAAEywAABZzwAAZ/AAAHj/EQCK/zEAnP9RAK7/cQDA/5EA0v+xAOT/0QD///8AAAAAACYvAABA - UAAAWnAAAHSQAACOsAAAqc8AAMLwAADR/xEA2P8xAN7/UQDj/3EA6f+RAO//sQD2/9EA////AAAAAAAv - JgAAUEEAAHBbAACQdAAAsI4AAM+pAADwwwAA/9IRAP/YMQD/3VEA/+RxAP/qkQD/8LEA//bRAP///wAA - AAAALxQAAFAiAABwMAAAkD4AALBNAADPWwAA8GkAAP95EQD/ijEA/51RAP+vcQD/wZEA/9KxAP/l0QD/ - //8AAAAAAC8DAABQBAAAcAYAAJAJAACwCgAAzwwAAPAOAAD/IBIA/z4xAP9cUQD/enEA/5eRAP+2sQD/ - 1NEA////AAAAAAAvAA4AUAAXAHAAIQCQACsAsAA2AM8AQADwAEkA/xFaAP8xcAD/UYYA/3GcAP+RsgD/ - scgA/9HfAP///wAAAAAALwAgAFAANgBwAEwAkABiALAAeADPAI4A8ACkAP8RswD/Mb4A/1HHAP9x0QD/ - kdwA/7HlAP/R8AD///8AAAAAACwALwBLAFAAaQBwAIcAkAClALAAxADPAOEA8ADwEf8A8jH/APRR/wD2 - cf8A95H/APmx/wD70f8A////AAAAAAAbAC8ALQBQAD8AcABSAJAAYwCwAHYAzwCIAPAAmRH/AKYx/wC0 - Uf8AwnH/AM+R/wDcsf8A69H/AP///wAAAAAACAAvAA4AUAAVAHAAGwCQACEAsAAmAM8ALADwAD4R/wBY - Mf8AcVH/AIxx/wCmkf8Av7H/ANrR/wD///8AAiUZLScLDgAtJSQiAAAAAB0rHQcFAAAAHBgFJhgAAAAV - AAAAAAAACwwwHiscAAAALxEAAAAAEDEcJRMAAAAAACoQAAAAAAUbCAAAAAAAAAAUKQcAAAAAAAAAAAAA - AAAAGi0IAAAAAAAAAAAAAAAAAAQWIgAAAAAAAAAAAAAAAAAoIi4CAAAAAAAAABkfAAAAIwAeFwAAAAcF - JiUhKwEAACcaLiYAEQwvJh8fAAEAAAApHgYdEjEkGRUAAAAAAAAAAAAJMR0UDAAAAAAAAAAAAAAAAA0C - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= - - - - - iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAwBQTFRFgICA//// - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAODgHVgAAAAlwSFlzAAAOvgAA - Dr4B6kKxwAAAABZJREFUGFdjYAABRhAAs4hlkq4DZDgACywAM12jTsYAAAAASUVORK5CYII= - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAnBJREFUOE+dk11I - k1Ecxs+2q1DLqwRvvCgoM6mLvoTAC6WLSrDUYBcSGK6y6EMzc6a2NnERlVKhSEMTYWSyksTZh7KZGboU - HNmUKemcupnuI5tuqHs6/7cSUenrwMPhPf/n97wPB46IrVrHCwuTxCJR5EbxbHiUZHQnEzE2uhj18Wsw - zPPLGgQmdErli9Ws8C2VX8wFX9y0rmiWnJ9/dg38Qc02dZdKUlQ3DrcuBINIfQTItMDJWiBHByj1gMEK - 0OxY9rkrywEvb7OQdzclR6tKDjRUV522qh7Kl5q6unDqQTnuNbZD89qEyhYTNK9M0PcMwLewgOsFh5oH - 70oSbXfYBmZUiM8P1Se06Z4WBP5UvarFALffj+q6goDjTXJTf7k4nWVmp159ayhDnVYu1Ot7tvmnImB+ - ztX4Y6dZUYMRzrk5VD4uxPueWmTlpVxmCVlZF1wuG8pqVJj0eKA+s5cHRMNm2Iapvn3wjCRirGOHUF2j - 12PY7Ubx/SJ4vJMglsXLZJcWefrI+Ge09PZCGr8V105sQU3xdgx0HYHfJ4O5ebdQXVNXjLb2Csy4x0EM - sexgRka2f2kJvkAAEzz9VmkCatWR0JaEoqkiDJ26cDxRh2LQ6YSyQgGna0zwEkMs25+envON13P7fII+ - 2e3QGo1rVN/RAZPFvOwjhli2RyrNdfNEh9eL0elpdFutsPMmLl55peiMZuQhLzHEsl1paXlf5udhdTjQ - abEIu21mZl2t9BBDLItOSpKP8HSj2Yx+Xn9oauq3Ig95iSGWRcTFKVr57Q/zv9pnZ/9K5CWGWBYaG5sZ - EhNT+j8idt0X+S+H3wE2DYYIXysH6QAAAABJRU5ErkJggg== - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAm1JREFUOE+Nkl9I - U1Ecx39T31o9SBq97cWHiUIimKiQ0zFbbcJ1U2YkBtLuFYkQnMrcdKQyEUIwWk+GDy58EfUhmYoTRtKE - HitI8kGZIkEW/oF0um/nd3OyYUnn8rn3nMPn+733wNXYe3spOTQajVXMb55vpE/CiUTiqyB91+b1Ugry - j3gcWwcH2Nzfx8benspsJALhyII8qaeHUiHJ7U5F+Xl0hM3dXXzZ2cGn7W183NpCcG4OPISrmNvbdQZF - IaZOlolsNhvVOZ1U29XFtO4fH+ObeGtqyYuJCSTJM5s9Aqqqr1ez6s1ut5OtqYksHR1tB6Lg++HhhRL+ - Ej4OO+yqmbOCDLGwCuSsrKznLpcLl8EOu5wRBRkkSdJ1t9vdtyPOrCgK+vv74fV6L+DxeODz+VQnFouh - u7u7j7NksVj0o6Oj42tra3A4HOjs7ITT6URzczMkqQ7V1UaUl1egpOQ2zOZ7qjM/v4yBgcFxzlJNTU3l - 1NTU8urqKoxGowjLMJnMqKioFME7aRiNd1VndnYRIyOBZc6SwWBwRKPR9XA4jKKiIjQ0PBSS9a+YTLWq - 4xTX5OTbdc5SWVnZk1AohGAwCJ1OB7v9EazWB/+EnbGxMUxPT4OzVFxc7IpE3mFmJoS2tqcYHg5gaOgl - /P5ACq/E/A+tre1YXPygwlnS6/XupaUVLCysoLGx8b9IFnCWcnJyWrKzsweZzMzMIf5l7weA1++BN9HP - MPhacEv2o8o1iV8nJ2An6XOWxIK0Wi1dy82lG6Wlz9SfPmWcJhJg4qeniIsnO+xyhrPnBVcLC0lbUPD4 - Sn6+/zLYUd2zgt/AGvcWHCMAZwAAAABJRU5ErkJggg== - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAW1JREFUOE+NkL1L - QlEYh9/b4NzS1BgNShBRQQ3VGEGr/0BDBEG0uLRIFIREIX2ANhgZKphj/4PLASOi0i4SYWWmWH5y/bhv - 5yc4HTl04YHD+z4893AMGvB53S7Hg+1cNQxjBGtm/p4YerrdvXlsDfJ7s7MlCp4ukgD7U3QX8mx+ZDIm - A5wx6+/hKiEs0+drnNiY5WTynlOpZ85mcz1wxgw7OHCVwPECCXlVDoev2ec75EDggiORGMfjCQ5dXrHf - f8LRaAwKw1UCR/MkbLns2Da/mOZAsIMDVwn45ki0pWB1OlrgwFUCBzMkrG6X662WFjhwlcDeNIlGu82/ - zaYWOHCVgHeSRFX+vVSraYEDVwnsuEj8WBbnKxUtcOAqAY+TREleP1cua4EDVwlsj5MoNBr8WixqgQNX - CWyNkfis19ksFLTAgasE1kdJvMsHTOfzWuDAVQLuYRJf8oHeqlUtcOAqgRUHBZcdJP4D3H7gDzdsNup2 - mXizAAAAAElFTkSuQmCC - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAXJJREFUOE+lk0FL - AkEYhlvwv3jzoiDoQdCbdEnYf6CrqCgoHgRRAk/9EQVLdEGyFiQNMS+dvHnoEkgglGAmCL7NO6RMIZvU - wsMO3zzzzGk0ACf/+hjQNO1ccKlXKsYx0OUZeflXoFmtVsUS2P4CHboi0FQDrXK5jM12i/VmYwsduiLQ - UgNmqVTCuzj8tlrZQoeuCJhqoFMsFvG6XmO2WNhCh64IdNRAt1Ao4EXc/jSf20KHrgh01YCVy+Uwnkzw - vFzaQoeuCFhqoJfJZBCLxY6Crgj01EA/lUrB4/HA7XYfhHs78vk8A301MIzH4/B6vRiNHjAY3H+DM+7p - ug6fz4dsNsvAUA2Mo9Eo/H4/LOsOTqdTYprXEs64x0AwGEQ6nWZgrAYeDcNAIBBAu30r/6Reb0t2MwbC - 4TCSySQDj/uAeEyngqnL5fpoNG4QCoUktVpHspsxEIlEkEgk+AKnaoAP8kwwczgcF4fg3g+u9gEu/son - bfJW/NwRDyIAAAAASUVORK5CYII= - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAUNJREFUOE+lk79L - QlEcxW9/gqCrm6vg4uYoOAgOrqLk4ioP0r2Glhp0SSjoF1FE0BIUDU3RdIOGoKBVGlpapaHTObeuCPe6 - 9ITD5fs9n3Pue8JbAWBS/VSQRvPwKR/j3JgaZXVqPv5TzPOXLhYoZDEcQidVWyhw3qzfn3tBAWH7PRjg - uV7HV5JAM6USyX50u86btlrOCwoOCR7Q+Oz1cFcu473dhmbppdFwu8dq1e3EBgU0zB6NXQJvzSaui0U8 - VCq4LZWwn8vhLJ+HPDFiowUEzITADsGrQgFHmYzTSTYL7eSJiRZs0timRoTGhC956wXDXtrJEyM2eAIt - t34Be8NgTPLELCuQYe8Z9tK8ZBf+ieuEnxj20rzB26SYF7zCGsGEoVeW6NTMoJFiXlDAkFllqMOwTs2+ - IOYFBf/9oFJ9ibr0B4f94vVG3bWDAAAAAElFTkSuQmCC - - - \ No newline at end of file diff --git a/Greenshot.ImageEditor/Core/ImageHelper.cs b/Greenshot.ImageEditor/Core/ImageHelper.cs deleted file mode 100644 index 3c322bed3..000000000 --- a/Greenshot.ImageEditor/Core/ImageHelper.cs +++ /dev/null @@ -1,1672 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Core; -using GreenshotPlugin.UnmanagedHelpers; -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Imaging; -using System.IO; - -namespace GreenshotPlugin.Core -{ - internal enum ExifOrientations : byte - { - Unknown = 0, - TopLeft = 1, - TopRight = 2, - BottomRight = 3, - BottomLeft = 4, - LeftTop = 5, - RightTop = 6, - RightBottom = 7, - LeftBottom = 8, - } - - /// - /// Description of ImageHelper. - /// - public static class ImageHelper - { - private const int EXIF_ORIENTATION_ID = 0x0112; - - /// - /// Make sure the image is orientated correctly - /// - /// - public static void Orientate(Image image) - { - /*if (!conf.ProcessEXIFOrientation) - { - return; - }*/ - try - { - // Get the index of the orientation property. - int orientationIndex = Array.IndexOf(image.PropertyIdList, EXIF_ORIENTATION_ID); - // If there is no such property, return Unknown. - if (orientationIndex < 0) - { - return; - } - PropertyItem item = image.GetPropertyItem(EXIF_ORIENTATION_ID); - - ExifOrientations orientation = (ExifOrientations)item.Value[0]; - // Orient the image. - switch (orientation) - { - case ExifOrientations.Unknown: - case ExifOrientations.TopLeft: - break; - case ExifOrientations.TopRight: - image.RotateFlip(RotateFlipType.RotateNoneFlipX); - break; - case ExifOrientations.BottomRight: - image.RotateFlip(RotateFlipType.Rotate180FlipNone); - break; - case ExifOrientations.BottomLeft: - image.RotateFlip(RotateFlipType.RotateNoneFlipY); - break; - case ExifOrientations.LeftTop: - image.RotateFlip(RotateFlipType.Rotate90FlipX); - break; - case ExifOrientations.RightTop: - image.RotateFlip(RotateFlipType.Rotate90FlipNone); - break; - case ExifOrientations.RightBottom: - image.RotateFlip(RotateFlipType.Rotate90FlipY); - break; - case ExifOrientations.LeftBottom: - image.RotateFlip(RotateFlipType.Rotate270FlipNone); - break; - } - // Set the orientation to be normal, as we rotated the image. - item.Value[0] = (byte)ExifOrientations.TopLeft; - image.SetPropertyItem(item); - } - catch (Exception orientEx) - { - LOG.Warn("Problem orientating the image: ", orientEx); - } - } - - /// - /// Create a thumbnail from an image - /// - /// - /// - /// - /// - public static Image CreateThumbnail(Image image, int thumbWidth, int thumbHeight) - { - return CreateThumbnail(image, thumbWidth, thumbHeight, -1, -1); - } - - /// - /// Create a Thumbnail - /// - /// - /// - /// - /// - /// - /// - public static Image CreateThumbnail(Image image, int thumbWidth, int thumbHeight, int maxWidth, int maxHeight) - { - int srcWidth = image.Width; - int srcHeight = image.Height; - if (thumbHeight < 0) - { - thumbHeight = (int)(thumbWidth * (srcHeight / (float)srcWidth)); - } - if (thumbWidth < 0) - { - thumbWidth = (int)(thumbHeight * (srcWidth / (float)srcHeight)); - } - if (maxWidth > 0 && thumbWidth > maxWidth) - { - thumbWidth = Math.Min(thumbWidth, maxWidth); - thumbHeight = (int)(thumbWidth * (srcHeight / (float)srcWidth)); - } - if (maxHeight > 0 && thumbHeight > maxHeight) - { - thumbHeight = Math.Min(thumbHeight, maxHeight); - thumbWidth = (int)(thumbHeight * (srcWidth / (float)srcHeight)); - } - - Bitmap bmp = new Bitmap(thumbWidth, thumbHeight); - using (Graphics graphics = Graphics.FromImage(bmp)) - { - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - Rectangle rectDestination = new Rectangle(0, 0, thumbWidth, thumbHeight); - graphics.DrawImage(image, rectDestination, 0, 0, srcWidth, srcHeight, GraphicsUnit.Pixel); - } - return bmp; - } - - /// - /// Crops the image to the specified rectangle - /// - /// Image to crop - /// Rectangle with bitmap coordinates, will be "intersected" to the bitmap - public static bool Crop(ref Image image, ref Rectangle cropRectangle) - { - Image returnImage = null; - if (image != null && image is Bitmap && ((image.Width * image.Height) > 0)) - { - cropRectangle.Intersect(new Rectangle(0, 0, image.Width, image.Height)); - if (cropRectangle.Width != 0 || cropRectangle.Height != 0) - { - returnImage = CloneArea(image, cropRectangle, PixelFormat.DontCare); - image.Dispose(); - image = returnImage; - return true; - } - } - LOG.Warn("Can't crop a null/zero size image!"); - return false; - } - - /// - /// Private helper method for the FindAutoCropRectangle - /// - /// - /// - /// - /// Rectangle - private static Rectangle FindAutoCropRectangle(IFastBitmap fastBitmap, Point colorPoint, int cropDifference) - { - Rectangle cropRectangle = Rectangle.Empty; - Color referenceColor = fastBitmap.GetColorAt(colorPoint.X, colorPoint.Y); - Point min = new Point(int.MaxValue, int.MaxValue); - Point max = new Point(int.MinValue, int.MinValue); - - if (cropDifference > 0) - { - for (int y = 0; y < fastBitmap.Height; y++) - { - for (int x = 0; x < fastBitmap.Width; x++) - { - Color currentColor = fastBitmap.GetColorAt(x, y); - int diffR = Math.Abs(currentColor.R - referenceColor.R); - int diffG = Math.Abs(currentColor.G - referenceColor.G); - int diffB = Math.Abs(currentColor.B - referenceColor.B); - if (((diffR + diffG + diffB) / 3) <= cropDifference) - { - continue; - } - if (x < min.X) min.X = x; - if (y < min.Y) min.Y = y; - if (x > max.X) max.X = x; - if (y > max.Y) max.Y = y; - } - } - } - else - { - for (int y = 0; y < fastBitmap.Height; y++) - { - for (int x = 0; x < fastBitmap.Width; x++) - { - Color currentColor = fastBitmap.GetColorAt(x, y); - if (!referenceColor.Equals(currentColor)) - { - continue; - } - if (x < min.X) min.X = x; - if (y < min.Y) min.Y = y; - if (x > max.X) max.X = x; - if (y > max.Y) max.Y = y; - } - } - } - - if (!(Point.Empty.Equals(min) && max.Equals(new Point(fastBitmap.Width - 1, fastBitmap.Height - 1)))) - { - if (!(min.X == int.MaxValue || min.Y == int.MaxValue || max.X == int.MinValue || min.X == int.MinValue)) - { - cropRectangle = new Rectangle(min.X, min.Y, max.X - min.X + 1, max.Y - min.Y + 1); - } - } - return cropRectangle; - } - - /// - /// Get a rectangle for the image which crops the image of all colors equal to that on 0,0 - /// - /// - /// - /// Rectangle - public static Rectangle FindAutoCropRectangle(Image image, int cropDifference) - { - Rectangle cropRectangle = Rectangle.Empty; - Rectangle currentRectangle; - List checkPoints = new List(); - // Top Left - checkPoints.Add(new Point(0, 0)); - // Bottom Left - checkPoints.Add(new Point(0, image.Height - 1)); - // Top Right - checkPoints.Add(new Point(image.Width - 1, 0)); - // Bottom Right - checkPoints.Add(new Point(image.Width - 1, image.Height - 1)); - using (IFastBitmap fastBitmap = FastBitmap.Create((Bitmap)image)) - { - // find biggest area - foreach (Point checkPoint in checkPoints) - { - currentRectangle = FindAutoCropRectangle(fastBitmap, checkPoint, cropDifference); - if (currentRectangle.Width * currentRectangle.Height > cropRectangle.Width * cropRectangle.Height) - { - cropRectangle = currentRectangle; - } - } - } - return cropRectangle; - } - - /// - /// Load an image from file - /// - /// - /// - public static Image LoadImage(string filename) - { - if (string.IsNullOrEmpty(filename)) - { - return null; - } - if (!File.Exists(filename)) - { - return null; - } - Image fileImage = null; - LOG.InfoFormat("Loading image from file {0}", filename); - // Fixed lock problem Bug #3431881 - using (Stream imageFileStream = File.OpenRead(filename)) - { - // And fixed problem that the bitmap stream is disposed... by Cloning the image - // This also ensures the bitmap is correctly created - - if (filename.EndsWith(".ico")) - { - // Icon logic, try to get the Vista icon, else the biggest possible - try - { - using (Image tmpImage = ExtractVistaIcon(imageFileStream)) - { - if (tmpImage != null) - { - fileImage = Clone(tmpImage); - } - } - } - catch (Exception vistaIconException) - { - LOG.Warn("Can't read icon from " + filename, vistaIconException); - } - if (fileImage == null) - { - try - { - // No vista icon, try normal icon - imageFileStream.Position = 0; - // We create a copy of the bitmap, so everything else can be disposed - using (Icon tmpIcon = new Icon(imageFileStream, new Size(1024, 1024))) - { - using (Image tmpImage = tmpIcon.ToBitmap()) - { - fileImage = Clone(tmpImage); - } - } - } - catch (Exception iconException) - { - LOG.Warn("Can't read icon from " + filename, iconException); - } - } - } - if (fileImage == null) - { - // We create a copy of the bitmap, so everything else can be disposed - imageFileStream.Position = 0; - using (Image tmpImage = Image.FromStream(imageFileStream, true, true)) - { - LOG.DebugFormat("Loaded {0} with Size {1}x{2} and PixelFormat {3}", filename, tmpImage.Width, tmpImage.Height, tmpImage.PixelFormat); - fileImage = Clone(tmpImage); - } - } - } - if (fileImage != null) - { - LOG.InfoFormat("Information about file {0}: {1}x{2}-{3} Resolution {4}x{5}", filename, fileImage.Width, fileImage.Height, fileImage.PixelFormat, fileImage.HorizontalResolution, fileImage.VerticalResolution); - } - // Make sure the orientation is set correctly so Greenshot can process the image correctly - Orientate(fileImage); - return fileImage; - } - - /// - /// Based on: http://www.codeproject.com/KB/cs/IconExtractor.aspx - /// And a hint from: http://www.codeproject.com/KB/cs/IconLib.aspx - /// - /// Stream with the icon information - /// Bitmap with the Vista Icon (256x256) - private static Bitmap ExtractVistaIcon(Stream iconStream) - { - const int SizeICONDIR = 6; - const int SizeICONDIRENTRY = 16; - Bitmap bmpPngExtracted = null; - try - { - byte[] srcBuf = new byte[iconStream.Length]; - iconStream.Read(srcBuf, 0, (int)iconStream.Length); - int iCount = BitConverter.ToInt16(srcBuf, 4); - for (int iIndex = 0; iIndex < iCount; iIndex++) - { - int iWidth = srcBuf[SizeICONDIR + SizeICONDIRENTRY * iIndex]; - int iHeight = srcBuf[SizeICONDIR + SizeICONDIRENTRY * iIndex + 1]; - int iBitCount = BitConverter.ToInt16(srcBuf, SizeICONDIR + SizeICONDIRENTRY * iIndex + 6); - if (iWidth == 0 && iHeight == 0) - { - int iImageSize = BitConverter.ToInt32(srcBuf, SizeICONDIR + SizeICONDIRENTRY * iIndex + 8); - int iImageOffset = BitConverter.ToInt32(srcBuf, SizeICONDIR + SizeICONDIRENTRY * iIndex + 12); - using (MemoryStream destStream = new MemoryStream()) - { - destStream.Write(srcBuf, iImageOffset, iImageSize); - destStream.Seek(0, SeekOrigin.Begin); - bmpPngExtracted = new Bitmap(destStream); // This is PNG! :) - } - break; - } - } - } - catch - { - return null; - } - return bmpPngExtracted; - } - - /// - /// See: http://msdn.microsoft.com/en-us/library/windows/desktop/ms648069%28v=vs.85%29.aspx - /// - /// The icon to - /// The file (EXE or DLL) to get the icon from - /// Index of the icon - /// true if the large icon is wanted - /// Icon - public static Icon ExtractAssociatedIcon(string location, int index, bool takeLarge) - { - IntPtr large; - IntPtr small; - Shell32.ExtractIconEx(location, index, out large, out small, 1); - Icon returnIcon = null; - bool isLarge = false; - bool isSmall = false; - try - { - if (takeLarge && !IntPtr.Zero.Equals(large)) - { - returnIcon = Icon.FromHandle(large); - isLarge = true; - } - else if (!IntPtr.Zero.Equals(small)) - { - returnIcon = Icon.FromHandle(small); - isSmall = true; - } - else if (!IntPtr.Zero.Equals(large)) - { - returnIcon = Icon.FromHandle(large); - isLarge = true; - } - } - finally - { - if (isLarge && !IntPtr.Zero.Equals(small)) - { - User32.DestroyIcon(small); - } - if (isSmall && !IntPtr.Zero.Equals(large)) - { - User32.DestroyIcon(large); - } - } - return returnIcon; - } - - /// - /// Get the number of icon in the file - /// - /// Location of the EXE or DLL - /// - public static int CountAssociatedIcons(string location) - { - IntPtr large; - IntPtr small; - return Shell32.ExtractIconEx(location, -1, out large, out small, 0); - } - - /// - /// Apply the effect to the bitmap - /// - /// Bitmap - /// IEffect - /// - /// Bitmap - public static Image ApplyEffect(Image sourceImage, IEffect effect, Matrix matrix) - { - List effects = new List(); - effects.Add(effect); - return ApplyEffects(sourceImage, effects, matrix); - } - - /// - /// Apply the effects in the supplied order to the bitmap - /// - /// Bitmap - /// List - /// - /// Bitmap - public static Image ApplyEffects(Image sourceImage, List effects, Matrix matrix) - { - Image currentImage = sourceImage; - bool disposeImage = false; - foreach (IEffect effect in effects) - { - Image tmpImage = effect.Apply(currentImage, matrix); - if (tmpImage != null) - { - if (disposeImage) - { - currentImage.Dispose(); - } - currentImage = tmpImage; - tmpImage = null; - // Make sure the "new" image is disposed - disposeImage = true; - } - } - return currentImage; - } - - /// - /// Helper method for the tornedge - /// - /// Path to draw to - /// Points for the lines to draw - private static void DrawLines(GraphicsPath path, List points) - { - path.AddLine(points[0], points[1]); - for (int i = 0; i < points.Count - 1; i++) - { - path.AddLine(points[i], points[i + 1]); - } - } - - /// - /// Make the picture look like it's torn - /// - /// Bitmap to make torn edge off - /// How large (height) is each tooth - /// How wide is a horizontal tooth - /// How wide is a vertical tooth - /// bool[] with information on if the edge needs torn or not. Order is clockwise: 0=top,1=right,2=bottom,3=left - /// Changed bitmap - public static Image CreateTornEdge(Image sourceImage, int toothHeight, int horizontalToothRange, int verticalToothRange, bool[] edges) - { - Image returnImage = CreateEmpty(sourceImage.Width, sourceImage.Height, PixelFormat.Format32bppArgb, Color.Empty, sourceImage.HorizontalResolution, sourceImage.VerticalResolution); - using (GraphicsPath path = new GraphicsPath()) - { - Random random = new Random(); - int horizontalRegions = (int)Math.Round((float)sourceImage.Width / horizontalToothRange); - int verticalRegions = (int)Math.Round((float)sourceImage.Height / verticalToothRange); - - Point topLeft = new Point(0, 0); - Point topRight = new Point(sourceImage.Width, 0); - Point bottomLeft = new Point(0, sourceImage.Height); - Point bottomRight = new Point(sourceImage.Width, sourceImage.Height); - - List points = new List(); - - if (edges[0]) - { - // calculate starting point only if the left edge is torn - if (!edges[3]) - { - points.Add(topLeft); - } - else - { - points.Add(new Point(random.Next(1, toothHeight), random.Next(1, toothHeight))); - } - for (int i = 1; i < horizontalRegions - 1; i++) - { - points.Add(new Point(i * horizontalToothRange, random.Next(1, toothHeight))); - } - points.Add(new Point(sourceImage.Width - random.Next(1, toothHeight), random.Next(1, toothHeight))); - } - else - { - // set start & endpoint to be the default "whole-line" - points.Add(topLeft); - points.Add(topRight); - } - // Right - if (edges[1]) - { - for (int i = 1; i < verticalRegions - 1; i++) - { - points.Add(new Point(sourceImage.Width - random.Next(1, toothHeight), i * verticalToothRange)); - } - points.Add(new Point(sourceImage.Width - random.Next(1, toothHeight), sourceImage.Height - random.Next(1, toothHeight))); - } - else - { - // correct previous ending point - points[points.Count - 1] = topRight; - // set endpoint to be the default "whole-line" - points.Add(bottomRight); - } - // Bottom - if (edges[2]) - { - for (int i = 1; i < horizontalRegions - 1; i++) - { - points.Add(new Point(sourceImage.Width - i * horizontalToothRange, sourceImage.Height - random.Next(1, toothHeight))); - } - points.Add(new Point(random.Next(1, toothHeight), sourceImage.Height - random.Next(1, toothHeight))); - } - else - { - // correct previous ending point - points[points.Count - 1] = bottomRight; - // set endpoint to be the default "whole-line" - points.Add(bottomLeft); - } - // Left - if (edges[3]) - { - // One fewer as the end point is the starting point - for (int i = 1; i < verticalRegions - 1; i++) - { - points.Add(new Point(random.Next(1, toothHeight), points[points.Count - 1].Y - verticalToothRange)); - } - } - else - { - // correct previous ending point - points[points.Count - 1] = bottomLeft; - // set endpoint to be the default "whole-line" - points.Add(topLeft); - } - // End point always is the starting point - points[points.Count - 1] = points[0]; - - DrawLines(path, points); - - path.CloseFigure(); - - // Draw the created figure with the original image by using a TextureBrush so we have anti-aliasing - using (Graphics graphics = Graphics.FromImage(returnImage)) - { - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - using (Brush brush = new TextureBrush(sourceImage)) - { - // Important note: If the target wouldn't be at 0,0 we need to translate-transform!! - graphics.FillPath(brush, path); - } - } - } - return returnImage; - } - - /// - /// Apply BoxBlur to the destinationBitmap - /// - /// Bitmap to blur - /// Must be ODD! - public static void ApplyBoxBlur(Bitmap destinationBitmap, int range) - { - // We only need one fastbitmap as we use it as source and target (the reading is done for one line H/V, writing after "parsing" one line H/V) - using (IFastBitmap fastBitmap = FastBitmap.Create(destinationBitmap)) - { - ApplyBoxBlur(fastBitmap, range); - } - } - - /// - /// Apply BoxBlur to the fastBitmap - /// - /// IFastBitmap to blur - /// Must be ODD! - public static void ApplyBoxBlur(IFastBitmap fastBitmap, int range) - { - // Range must be odd! - if ((range & 1) == 0) - { - range++; - } - if (range <= 1) - { - return; - } - // Box blurs are frequently used to approximate a Gaussian blur. - // By the central limit theorem, if applied 3 times on the same image, a box blur approximates the Gaussian kernel to within about 3%, yielding the same result as a quadratic convolution kernel. - // This might be true, but the GDI+ BlurEffect doesn't look the same, a 2x blur is more simular and we only make 2x Box-Blur. - // (Might also be a mistake in our blur, but for now it looks great) - if (fastBitmap.hasAlphaChannel) - { - BoxBlurHorizontalAlpha(fastBitmap, range); - BoxBlurVerticalAlpha(fastBitmap, range); - BoxBlurHorizontalAlpha(fastBitmap, range); - BoxBlurVerticalAlpha(fastBitmap, range); - } - else - { - BoxBlurHorizontal(fastBitmap, range); - BoxBlurVertical(fastBitmap, range); - BoxBlurHorizontal(fastBitmap, range); - BoxBlurVertical(fastBitmap, range); - } - } - - /// - /// BoxBlurHorizontal is a private helper method for the BoxBlur - /// - /// Target BitmapBuffer - /// Range must be odd! - private static void BoxBlurHorizontal(IFastBitmap targetFastBitmap, int range) - { - if (targetFastBitmap.hasAlphaChannel) - { - throw new NotSupportedException("BoxBlurHorizontal should NOT be called for bitmaps with alpha channel"); - } - int halfRange = range / 2; - Color[] newColors = new Color[targetFastBitmap.Width]; - byte[] tmpColor = new byte[3]; - for (int y = targetFastBitmap.Top; y < targetFastBitmap.Bottom; y++) - { - int hits = 0; - int r = 0; - int g = 0; - int b = 0; - for (int x = targetFastBitmap.Left - halfRange; x < targetFastBitmap.Right; x++) - { - int oldPixel = x - halfRange - 1; - if (oldPixel >= targetFastBitmap.Left) - { - targetFastBitmap.GetColorAt(oldPixel, y, tmpColor); - r -= tmpColor[FastBitmap.COLOR_INDEX_R]; - g -= tmpColor[FastBitmap.COLOR_INDEX_G]; - b -= tmpColor[FastBitmap.COLOR_INDEX_B]; - hits--; - } - - int newPixel = x + halfRange; - if (newPixel < targetFastBitmap.Right) - { - targetFastBitmap.GetColorAt(newPixel, y, tmpColor); - r += tmpColor[FastBitmap.COLOR_INDEX_R]; - g += tmpColor[FastBitmap.COLOR_INDEX_G]; - b += tmpColor[FastBitmap.COLOR_INDEX_B]; - hits++; - } - - if (x >= targetFastBitmap.Left) - { - newColors[x - targetFastBitmap.Left] = Color.FromArgb(255, (byte)(r / hits), (byte)(g / hits), (byte)(b / hits)); - } - } - for (int x = targetFastBitmap.Left; x < targetFastBitmap.Right; x++) - { - targetFastBitmap.SetColorAt(x, y, newColors[x - targetFastBitmap.Left]); - } - } - } - - /// - /// BoxBlurHorizontal is a private helper method for the BoxBlur, only for IFastBitmaps with alpha channel - /// - /// Target BitmapBuffer - /// Range must be odd! - private static void BoxBlurHorizontalAlpha(IFastBitmap targetFastBitmap, int range) - { - if (!targetFastBitmap.hasAlphaChannel) - { - throw new NotSupportedException("BoxBlurHorizontalAlpha should be called for bitmaps with alpha channel"); - } - int halfRange = range / 2; - Color[] newColors = new Color[targetFastBitmap.Width]; - byte[] tmpColor = new byte[4]; - for (int y = targetFastBitmap.Top; y < targetFastBitmap.Bottom; y++) - { - int hits = 0; - int a = 0; - int r = 0; - int g = 0; - int b = 0; - for (int x = targetFastBitmap.Left - halfRange; x < targetFastBitmap.Right; x++) - { - int oldPixel = x - halfRange - 1; - if (oldPixel >= targetFastBitmap.Left) - { - targetFastBitmap.GetColorAt(oldPixel, y, tmpColor); - a -= tmpColor[FastBitmap.COLOR_INDEX_A]; - r -= tmpColor[FastBitmap.COLOR_INDEX_R]; - g -= tmpColor[FastBitmap.COLOR_INDEX_G]; - b -= tmpColor[FastBitmap.COLOR_INDEX_B]; - hits--; - } - - int newPixel = x + halfRange; - if (newPixel < targetFastBitmap.Right) - { - targetFastBitmap.GetColorAt(newPixel, y, tmpColor); - a += tmpColor[FastBitmap.COLOR_INDEX_A]; - r += tmpColor[FastBitmap.COLOR_INDEX_R]; - g += tmpColor[FastBitmap.COLOR_INDEX_G]; - b += tmpColor[FastBitmap.COLOR_INDEX_B]; - hits++; - } - - if (x >= targetFastBitmap.Left) - { - newColors[x - targetFastBitmap.Left] = Color.FromArgb((byte)(a / hits), (byte)(r / hits), (byte)(g / hits), (byte)(b / hits)); - } - } - for (int x = targetFastBitmap.Left; x < targetFastBitmap.Right; x++) - { - targetFastBitmap.SetColorAt(x, y, newColors[x - targetFastBitmap.Left]); - } - } - } - - /// - /// BoxBlurVertical is a private helper method for the BoxBlur - /// - /// BitmapBuffer which previously was created with BoxBlurHorizontal - /// Range must be odd! - private static void BoxBlurVertical(IFastBitmap targetFastBitmap, int range) - { - if (targetFastBitmap.hasAlphaChannel) - { - throw new NotSupportedException("BoxBlurVertical should NOT be called for bitmaps with alpha channel"); - } - int halfRange = range / 2; - Color[] newColors = new Color[targetFastBitmap.Height]; - byte[] tmpColor = new byte[4]; - for (int x = targetFastBitmap.Left; x < targetFastBitmap.Right; x++) - { - int hits = 0; - int r = 0; - int g = 0; - int b = 0; - for (int y = targetFastBitmap.Top - halfRange; y < targetFastBitmap.Bottom; y++) - { - int oldPixel = y - halfRange - 1; - if (oldPixel >= targetFastBitmap.Top) - { - targetFastBitmap.GetColorAt(x, oldPixel, tmpColor); - r -= tmpColor[FastBitmap.COLOR_INDEX_R]; - g -= tmpColor[FastBitmap.COLOR_INDEX_G]; - b -= tmpColor[FastBitmap.COLOR_INDEX_B]; - hits--; - } - - int newPixel = y + halfRange; - if (newPixel < targetFastBitmap.Bottom) - { - targetFastBitmap.GetColorAt(x, newPixel, tmpColor); - r += tmpColor[FastBitmap.COLOR_INDEX_R]; - g += tmpColor[FastBitmap.COLOR_INDEX_G]; - b += tmpColor[FastBitmap.COLOR_INDEX_B]; - hits++; - } - - if (y >= targetFastBitmap.Top) - { - newColors[y - targetFastBitmap.Top] = Color.FromArgb(255, (byte)(r / hits), (byte)(g / hits), (byte)(b / hits)); - } - } - - for (int y = targetFastBitmap.Top; y < targetFastBitmap.Bottom; y++) - { - targetFastBitmap.SetColorAt(x, y, newColors[y - targetFastBitmap.Top]); - } - } - } - - /// - /// BoxBlurVertical is a private helper method for the BoxBlur - /// - /// BitmapBuffer which previously was created with BoxBlurHorizontal - /// Range must be odd! - private static void BoxBlurVerticalAlpha(IFastBitmap targetFastBitmap, int range) - { - if (!targetFastBitmap.hasAlphaChannel) - { - throw new NotSupportedException("BoxBlurVerticalAlpha should be called for bitmaps with alpha channel"); - } - - int halfRange = range / 2; - Color[] newColors = new Color[targetFastBitmap.Height]; - byte[] tmpColor = new byte[4]; - for (int x = targetFastBitmap.Left; x < targetFastBitmap.Right; x++) - { - int hits = 0; - int a = 0; - int r = 0; - int g = 0; - int b = 0; - for (int y = targetFastBitmap.Top - halfRange; y < targetFastBitmap.Bottom; y++) - { - int oldPixel = y - halfRange - 1; - if (oldPixel >= targetFastBitmap.Top) - { - targetFastBitmap.GetColorAt(x, oldPixel, tmpColor); - a -= tmpColor[FastBitmap.COLOR_INDEX_A]; - r -= tmpColor[FastBitmap.COLOR_INDEX_R]; - g -= tmpColor[FastBitmap.COLOR_INDEX_G]; - b -= tmpColor[FastBitmap.COLOR_INDEX_B]; - hits--; - } - - int newPixel = y + halfRange; - if (newPixel < targetFastBitmap.Bottom) - { - //int colorg = pixels[index + newPixelOffset]; - targetFastBitmap.GetColorAt(x, newPixel, tmpColor); - a += tmpColor[FastBitmap.COLOR_INDEX_A]; - r += tmpColor[FastBitmap.COLOR_INDEX_R]; - g += tmpColor[FastBitmap.COLOR_INDEX_G]; - b += tmpColor[FastBitmap.COLOR_INDEX_B]; - hits++; - } - - if (y >= targetFastBitmap.Top) - { - newColors[y - targetFastBitmap.Top] = Color.FromArgb((byte)(a / hits), (byte)(r / hits), (byte)(g / hits), (byte)(b / hits)); - } - } - - for (int y = targetFastBitmap.Top; y < targetFastBitmap.Bottom; y++) - { - targetFastBitmap.SetColorAt(x, y, newColors[y - targetFastBitmap.Top]); - } - } - } - - /// - /// This method fixes the problem that we can't apply a filter outside the target bitmap, - /// therefor the filtered-bitmap will be shifted if we try to draw it outside the target bitmap. - /// It will also account for the Invert flag. - /// - /// - /// - /// - /// - public static Rectangle CreateIntersectRectangle(Size applySize, Rectangle rect, bool invert) - { - Rectangle myRect; - if (invert) - { - myRect = new Rectangle(0, 0, applySize.Width, applySize.Height); - } - else - { - Rectangle applyRect = new Rectangle(0, 0, applySize.Width, applySize.Height); - myRect = new Rectangle(rect.X, rect.Y, rect.Width, rect.Height); - myRect.Intersect(applyRect); - } - return myRect; - } - - /// - /// Create a new bitmap where the sourceBitmap has a shadow - /// - /// Bitmap to make a shadow on - /// How dark is the shadow - /// Size of the shadow - /// What pixel format must the returning bitmap have - /// - /// The transform matrix which describes how the elements need to be transformed to stay at the same location - /// Bitmap with the shadow, is bigger than the sourceBitmap!! - public static Bitmap CreateShadow(Image sourceBitmap, float darkness, int shadowSize, Point shadowOffset, Matrix matrix, PixelFormat targetPixelformat) - { - Point offset = shadowOffset; - offset.X += shadowSize - 1; - offset.Y += shadowSize - 1; - matrix.Translate(offset.X, offset.Y, MatrixOrder.Append); - // Create a new "clean" image - Bitmap returnImage = CreateEmpty(sourceBitmap.Width + (shadowSize * 2), sourceBitmap.Height + (shadowSize * 2), targetPixelformat, Color.Empty, sourceBitmap.HorizontalResolution, sourceBitmap.VerticalResolution); - // Make sure the shadow is odd, there is no reason for an even blur! - if ((shadowSize & 1) == 0) - { - shadowSize++; - } - bool useGDIBlur = GDIplus.IsBlurPossible(shadowSize); - // Create "mask" for the shadow - ColorMatrix maskMatrix = new ColorMatrix(); - maskMatrix.Matrix00 = 0; - maskMatrix.Matrix11 = 0; - maskMatrix.Matrix22 = 0; - if (useGDIBlur) - { - maskMatrix.Matrix33 = darkness + 0.1f; - } - else - { - maskMatrix.Matrix33 = darkness; - } - Rectangle shadowRectangle = new Rectangle(new Point(shadowSize, shadowSize), sourceBitmap.Size); - ApplyColorMatrix((Bitmap)sourceBitmap, Rectangle.Empty, returnImage, shadowRectangle, maskMatrix); - - // blur "shadow", apply to whole new image - if (useGDIBlur) - { - // Use GDI Blur - Rectangle newImageRectangle = new Rectangle(0, 0, returnImage.Width, returnImage.Height); - GDIplus.ApplyBlur(returnImage, newImageRectangle, shadowSize + 1, false); - } - else - { - // try normal software blur - //returnImage = CreateBlur(returnImage, newImageRectangle, true, shadowSize, 1d, false, newImageRectangle); - ApplyBoxBlur(returnImage, shadowSize); - } - - // Draw the original image over the shadow - using (Graphics graphics = Graphics.FromImage(returnImage)) - { - // Make sure we draw with the best quality! - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - // draw original with a TextureBrush so we have nice antialiasing! - using (Brush textureBrush = new TextureBrush(sourceBitmap, WrapMode.Clamp)) - { - // We need to do a translate-transform otherwise the image is wrapped - graphics.TranslateTransform(offset.X, offset.Y); - graphics.FillRectangle(textureBrush, 0, 0, sourceBitmap.Width, sourceBitmap.Height); - } - } - return returnImage; - } - - /// - /// Return negative of Bitmap - /// - /// Bitmap to create a negative off - /// Negative bitmap - public static Bitmap CreateNegative(Image sourceImage) - { - Bitmap clone = (Bitmap)Clone(sourceImage); - ColorMatrix invertMatrix = new ColorMatrix(new[] { - new float[] {-1, 0, 0, 0, 0}, - new float[] {0, -1, 0, 0, 0}, - new float[] {0, 0, -1, 0, 0}, - new float[] {0, 0, 0, 1, 0}, - new float[] {1, 1, 1, 1, 1} - }); - ApplyColorMatrix(clone, invertMatrix); - return clone; - } - - /// - /// Apply a color matrix to the image - /// - /// Image to apply matrix to - /// ColorMatrix to apply - public static void ApplyColorMatrix(Bitmap source, ColorMatrix colorMatrix) - { - ApplyColorMatrix(source, Rectangle.Empty, source, Rectangle.Empty, colorMatrix); - } - - /// - /// Apply a color matrix by copying from the source to the destination - /// - /// Image to copy from - /// Rectangle to copy from - /// Rectangle to copy to - /// Image to copy to - /// ColorMatrix to apply - public static void ApplyColorMatrix(Bitmap source, Rectangle sourceRect, Bitmap dest, Rectangle destRect, ColorMatrix colorMatrix) - { - using (ImageAttributes imageAttributes = new ImageAttributes()) - { - imageAttributes.ClearColorMatrix(); - imageAttributes.SetColorMatrix(colorMatrix); - ApplyImageAttributes(source, sourceRect, dest, destRect, imageAttributes); - } - } - - /// - /// Apply image attributes to the image - /// - /// Image to apply matrix to - /// ImageAttributes to apply - public static void ApplyColorMatrix(Bitmap source, ImageAttributes imageAttributes) - { - ApplyImageAttributes(source, Rectangle.Empty, source, Rectangle.Empty, imageAttributes); - } - - /// - /// Apply a color matrix by copying from the source to the destination - /// - /// Image to copy from - /// Rectangle to copy from - /// Rectangle to copy to - /// Image to copy to - /// ImageAttributes to apply - public static void ApplyImageAttributes(Bitmap source, Rectangle sourceRect, Bitmap dest, Rectangle destRect, ImageAttributes imageAttributes) - { - if (sourceRect == Rectangle.Empty) - { - sourceRect = new Rectangle(0, 0, source.Width, source.Height); - } - if (dest == null) - { - dest = source; - } - if (destRect == Rectangle.Empty) - { - destRect = new Rectangle(0, 0, dest.Width, dest.Height); - } - using (Graphics graphics = Graphics.FromImage(dest)) - { - // Make sure we draw with the best quality! - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - graphics.CompositingMode = CompositingMode.SourceCopy; - - graphics.DrawImage(source, destRect, sourceRect.X, sourceRect.Y, sourceRect.Width, sourceRect.Height, GraphicsUnit.Pixel, imageAttributes); - } - } - - /// - /// Returns a b/w of Bitmap - /// - /// Bitmap to create a b/w of - /// Threshold for monochrome filter (0 - 255), lower value means less black - /// b/w bitmap - public static Bitmap CreateMonochrome(Image sourceImage, byte threshold) - { - using (IFastBitmap fastBitmap = FastBitmap.CreateCloneOf(sourceImage, sourceImage.PixelFormat)) - { - for (int y = 0; y < fastBitmap.Height; y++) - { - for (int x = 0; x < fastBitmap.Width; x++) - { - Color color = fastBitmap.GetColorAt(x, y); - int colorBrightness = ((color.R + color.G + color.B) / 3 > threshold) ? 255 : 0; - Color monoColor = Color.FromArgb(color.A, colorBrightness, colorBrightness, colorBrightness); - fastBitmap.SetColorAt(x, y, monoColor); - } - } - return fastBitmap.UnlockAndReturnBitmap(); - } - } - - /// - /// Create a new bitmap where the sourceBitmap has a Simple border around it - /// - /// Bitmap to make a border on - /// Size of the border - /// Color of the border - /// What pixel format must the returning bitmap have - /// The transform matrix which describes how the elements need to be transformed to stay at the same location - /// Bitmap with the shadow, is bigger than the sourceBitmap!! - public static Image CreateBorder(Image sourceImage, int borderSize, Color borderColor, PixelFormat targetPixelformat, Matrix matrix) - { - // "return" the shifted offset, so the caller can e.g. move elements - Point offset = new Point(borderSize, borderSize); - matrix.Translate(offset.X, offset.Y, MatrixOrder.Append); - - // Create a new "clean" image - Bitmap newImage = CreateEmpty(sourceImage.Width + (borderSize * 2), sourceImage.Height + (borderSize * 2), targetPixelformat, Color.Empty, sourceImage.HorizontalResolution, sourceImage.VerticalResolution); - using (Graphics graphics = Graphics.FromImage(newImage)) - { - // Make sure we draw with the best quality! - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - using (GraphicsPath path = new GraphicsPath()) - { - path.AddRectangle(new Rectangle(borderSize >> 1, borderSize >> 1, newImage.Width - (borderSize), newImage.Height - (borderSize))); - using (Pen pen = new Pen(borderColor, borderSize)) - { - pen.LineJoin = LineJoin.Round; - pen.StartCap = LineCap.Round; - pen.EndCap = LineCap.Round; - graphics.DrawPath(pen, path); - } - } - // draw original with a TextureBrush so we have nice antialiasing! - using (Brush textureBrush = new TextureBrush(sourceImage, WrapMode.Clamp)) - { - // We need to do a translate-tranform otherwise the image is wrapped - graphics.TranslateTransform(offset.X, offset.Y); - graphics.FillRectangle(textureBrush, 0, 0, sourceImage.Width, sourceImage.Height); - } - } - return newImage; - } - - /// - /// Create ImageAttributes to modify - /// - /// - /// - /// - /// ImageAttributes - public static ImageAttributes CreateAdjustAttributes(float brightness, float contrast, float gamma) - { - float adjustedBrightness = brightness - 1.0f; - ColorMatrix applyColorMatrix = new ColorMatrix( - new[] { - new[] {contrast, 0, 0, 0, 0}, // scale red - new[] {0, contrast, 0, 0, 0}, // scale green - new[] {0, 0, contrast, 0, 0}, // scale blue - new[] {0, 0, 0, 1.0f, 0}, // don't scale alpha - new[] {adjustedBrightness, adjustedBrightness, adjustedBrightness, 0, 1} - }); - - //create some image attributes - ImageAttributes attributes = new ImageAttributes(); - attributes.ClearColorMatrix(); - attributes.SetColorMatrix(applyColorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); - attributes.SetGamma(gamma, ColorAdjustType.Bitmap); - return attributes; - } - - /// - /// Adjust the brightness, contract or gamma of an image. - /// Use the value "1.0f" for no changes. - /// - /// Original bitmap - /// - /// - /// - /// Bitmap with grayscale - public static Image Adjust(Image sourceImage, float brightness, float contrast, float gamma) - { - //create a blank bitmap the same size as original - // If using 8bpp than the following exception comes: A Graphics object cannot be created from an image that has an indexed pixel format. - Bitmap newBitmap = CreateEmpty(sourceImage.Width, sourceImage.Height, PixelFormat.Format24bppRgb, Color.Empty, sourceImage.HorizontalResolution, sourceImage.VerticalResolution); - using (ImageAttributes adjustAttributes = CreateAdjustAttributes(brightness, contrast, gamma)) - { - ApplyImageAttributes((Bitmap)sourceImage, Rectangle.Empty, newBitmap, Rectangle.Empty, adjustAttributes); - } - return newBitmap; - } - - /// - /// Create a new bitmap where the sourceBitmap is in grayscale - /// - /// Original bitmap - /// Bitmap with grayscale - public static Image CreateGrayscale(Image sourceImage) - { - Bitmap clone = (Bitmap)Clone(sourceImage); - ColorMatrix grayscaleMatrix = new ColorMatrix(new[] { - new[] {.3f, .3f, .3f, 0, 0}, - new[] {.59f, .59f, .59f, 0, 0}, - new[] {.11f, .11f, .11f, 0, 0}, - new float[] {0, 0, 0, 1, 0}, - new float[] {0, 0, 0, 0, 1} - }); - ApplyColorMatrix(clone, grayscaleMatrix); - return clone; - } - - /// - /// Checks if the supplied Bitmap has a PixelFormat we support - /// - /// bitmap to check - /// bool if we support it - public static bool SupportsPixelFormat(Image image) - { - return SupportsPixelFormat(image.PixelFormat); - } - - /// - /// Checks if we support the pixel format - /// - /// PixelFormat to check - /// bool if we support it - public static bool SupportsPixelFormat(PixelFormat pixelformat) - { - return (pixelformat.Equals(PixelFormat.Format32bppArgb) || - pixelformat.Equals(PixelFormat.Format32bppPArgb) || - pixelformat.Equals(PixelFormat.Format32bppRgb) || - pixelformat.Equals(PixelFormat.Format24bppRgb)); - } - - /// - /// Wrapper for just cloning which calls the CloneArea - /// - /// Image to clone - /// Bitmap with clone image data - public static Image Clone(Image sourceImage) - { - if (sourceImage is Metafile) - { - return (Image)sourceImage.Clone(); - } - return CloneArea(sourceImage, Rectangle.Empty, PixelFormat.DontCare); - } - - /// - /// Wrapper for just cloning & TargetFormat which calls the CloneArea - /// - /// Image to clone - /// Target Format, use PixelFormat.DontCare if you want the original (or a default if the source PixelFormat is not supported) - /// Bitmap with clone image data - public static Bitmap Clone(Image sourceBitmap, PixelFormat targetFormat) - { - return CloneArea(sourceBitmap, Rectangle.Empty, targetFormat); - } - - /// - /// Clone an image, taking some rules into account: - /// 1) When sourceRect is the whole bitmap there is a GDI+ bug in Clone - /// Clone will than return the same PixelFormat as the source - /// a quick workaround is using new Bitmap which uses a default of Format32bppArgb - /// 2) When going from a transparent to a non transparent bitmap, we draw the background white! - /// - /// Source bitmap to clone - /// Rectangle to copy from the source, use Rectangle.Empty for all - /// Target Format, use PixelFormat.DontCare if you want the original (or a default if the source PixelFormat is not supported) - /// - public static Bitmap CloneArea(Image sourceImage, Rectangle sourceRect, PixelFormat targetFormat) - { - Bitmap newImage = null; - Rectangle bitmapRect = new Rectangle(0, 0, sourceImage.Width, sourceImage.Height); - - // Make sure the source is not Rectangle.Empty - if (Rectangle.Empty.Equals(sourceRect)) - { - sourceRect = new Rectangle(0, 0, sourceImage.Width, sourceImage.Height); - } - else - { - sourceRect.Intersect(bitmapRect); - } - - // If no pixelformat is supplied - if (PixelFormat.DontCare == targetFormat || PixelFormat.Undefined == targetFormat) - { - if (SupportsPixelFormat(sourceImage.PixelFormat)) - { - targetFormat = sourceImage.PixelFormat; - } - else if (Image.IsAlphaPixelFormat(sourceImage.PixelFormat)) - { - targetFormat = PixelFormat.Format32bppArgb; - } - else - { - targetFormat = PixelFormat.Format24bppRgb; - } - } - - // check the target format - if (!SupportsPixelFormat(targetFormat)) - { - if (Image.IsAlphaPixelFormat(targetFormat)) - { - targetFormat = PixelFormat.Format32bppArgb; - } - else - { - targetFormat = PixelFormat.Format24bppRgb; - } - } - - bool destinationIsTransparent = Image.IsAlphaPixelFormat(targetFormat); - bool sourceIsTransparent = Image.IsAlphaPixelFormat(sourceImage.PixelFormat); - bool fromTransparentToNon = !destinationIsTransparent && sourceIsTransparent; - bool isBitmap = sourceImage is Bitmap; - bool isAreaEqual = sourceRect.Equals(bitmapRect); - if (isAreaEqual || fromTransparentToNon || !isBitmap) - { - // Rule 1: if the areas are equal, always copy ourselves - newImage = new Bitmap(bitmapRect.Width, bitmapRect.Height, targetFormat); - // Make sure both images have the same resolution - newImage.SetResolution(sourceImage.HorizontalResolution, sourceImage.VerticalResolution); - - using (Graphics graphics = Graphics.FromImage(newImage)) - { - if (fromTransparentToNon) - { - // Rule 2: Make sure the background color is white - graphics.Clear(Color.White); - } - // decide fastest copy method - if (isAreaEqual) - { - graphics.DrawImageUnscaled(sourceImage, 0, 0); - } - else - { - graphics.DrawImage(sourceImage, 0, 0, sourceRect, GraphicsUnit.Pixel); - } - } - } - else - { - // Let GDI+ decide how to convert, need to test what is quicker... - newImage = (sourceImage as Bitmap).Clone(sourceRect, targetFormat); - // Make sure both images have the same resolution - newImage.SetResolution(sourceImage.HorizontalResolution, sourceImage.VerticalResolution); - } - // Clone property items (EXIF information etc) - if (sourceImage.PropertyItems != null) - { - foreach (var propertyItem in sourceImage.PropertyItems) - { - try - { - newImage.SetPropertyItem(propertyItem); - } - catch (Exception ex) - { - LOG.Warn("Problem cloning a propertyItem.", ex); - } - } - } - return newImage; - } - - /// - /// Rotate the bitmap - /// - /// - /// - /// - public static Image RotateFlip(Image sourceImage, RotateFlipType rotateFlipType) - { - Image returnImage = Clone(sourceImage); - returnImage.RotateFlip(rotateFlipType); - return returnImage; - } - - /// - /// A generic way to create an empty image - /// - /// the source bitmap as the specifications for the new bitmap - /// The color to fill with, or Color.Empty to take the default depending on the pixel format - /// - public static Bitmap CreateEmptyLike(Image sourceImage, Color backgroundColor) - { - PixelFormat pixelFormat = sourceImage.PixelFormat; - if (backgroundColor.A < 255) - { - pixelFormat = PixelFormat.Format32bppArgb; - } - return CreateEmpty(sourceImage.Width, sourceImage.Height, pixelFormat, backgroundColor, sourceImage.HorizontalResolution, sourceImage.VerticalResolution); - } - - /// - /// A generic way to create an empty image - /// - /// - /// - /// - /// The color to fill with, or Color.Empty to take the default depending on the pixel format - /// - /// - /// Bitmap - public static Bitmap CreateEmpty(int width, int height, PixelFormat format, Color backgroundColor, float horizontalResolution, float verticalResolution) - { - // Create a new "clean" image - Bitmap newImage = new Bitmap(width, height, format); - newImage.SetResolution(horizontalResolution, verticalResolution); - if (format != PixelFormat.Format8bppIndexed) - { - using (Graphics graphics = Graphics.FromImage(newImage)) - { - // Make sure the background color is what we want (transparent or white, depending on the pixel format) - if (!Color.Empty.Equals(backgroundColor)) - { - graphics.Clear(backgroundColor); - } - else if (Image.IsAlphaPixelFormat(format)) - { - graphics.Clear(Color.Transparent); - } - else - { - graphics.Clear(Color.White); - } - } - } - return newImage; - } - - /// - /// Get a scaled version of the sourceBitmap - /// - /// - /// 1-99 to make smaller, use 101 and more to make the picture bigger - /// - public static Bitmap ScaleByPercent(Bitmap sourceBitmap, int percent) - { - float nPercent = ((float)percent / 100); - - int sourceWidth = sourceBitmap.Width; - int sourceHeight = sourceBitmap.Height; - int destWidth = (int)(sourceWidth * nPercent); - int destHeight = (int)(sourceHeight * nPercent); - - Bitmap scaledBitmap = CreateEmpty(destWidth, destHeight, sourceBitmap.PixelFormat, Color.Empty, sourceBitmap.HorizontalResolution, sourceBitmap.VerticalResolution); - using (Graphics graphics = Graphics.FromImage(scaledBitmap)) - { - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - graphics.DrawImage(sourceBitmap, new Rectangle(0, 0, destWidth, destHeight), new Rectangle(0, 0, sourceWidth, sourceHeight), GraphicsUnit.Pixel); - } - return scaledBitmap; - } - - /// - /// Resize canvas with pixel to the left, right, top and bottom - /// - /// - /// The color to fill with, or Color.Empty to take the default depending on the pixel format - /// - /// - /// - /// - /// - /// a new bitmap with the source copied on it - public static Image ResizeCanvas(Image sourceImage, Color backgroundColor, int left, int right, int top, int bottom, Matrix matrix) - { - matrix.Translate(left, top, MatrixOrder.Append); - Bitmap newBitmap = CreateEmpty(sourceImage.Width + left + right, sourceImage.Height + top + bottom, sourceImage.PixelFormat, backgroundColor, sourceImage.HorizontalResolution, sourceImage.VerticalResolution); - using (Graphics graphics = Graphics.FromImage(newBitmap)) - { - graphics.DrawImageUnscaled(sourceImage, left, top); - } - return newBitmap; - } - - /// - /// Wrapper for the more complex Resize, this resize could be used for e.g. Thumbnails - /// - /// - /// true to maintain the aspect ratio - /// - /// - /// - /// - public static Image ResizeImage(Image sourceImage, bool maintainAspectRatio, int newWidth, int newHeight, Matrix matrix) - { - return ResizeImage(sourceImage, maintainAspectRatio, false, Color.Empty, newWidth, newHeight, matrix); - } - - /// - /// Count how many times the supplied color exists - /// - /// Image to count the pixels of - /// Color to count - /// true if Alpha needs to be checked - /// int with the number of pixels which have colorToCount - public static int CountColor(Image sourceImage, Color colorToCount, bool includeAlpha) - { - int colors = 0; - int toCount = colorToCount.ToArgb(); - if (!includeAlpha) - { - toCount = toCount & 0xffffff; - } - using (IFastBitmap bb = FastBitmap.Create((Bitmap)sourceImage)) - { - for (int y = 0; y < bb.Height; y++) - { - for (int x = 0; x < bb.Width; x++) - { - int bitmapcolor = bb.GetColorAt(x, y).ToArgb(); - if (!includeAlpha) - { - bitmapcolor = bitmapcolor & 0xffffff; - } - if (bitmapcolor == toCount) - { - colors++; - } - } - } - return colors; - } - } - - /// - /// Scale the bitmap, keeping aspect ratio, but the canvas will always have the specified size. - /// - /// Image to scale - /// true to maintain the aspect ratio - /// - /// The color to fill with, or Color.Empty to take the default depending on the pixel format - /// new width - /// new height - /// - /// a new bitmap with the specified size, the source-Image scaled to fit with aspect ratio locked - public static Image ResizeImage(Image sourceImage, bool maintainAspectRatio, bool canvasUseNewSize, Color backgroundColor, int newWidth, int newHeight, Matrix matrix) - { - int destX = 0; - int destY = 0; - - float nPercentW = 0; - float nPercentH = 0; - - nPercentW = (newWidth / (float)sourceImage.Width); - nPercentH = (newHeight / (float)sourceImage.Height); - if (maintainAspectRatio) - { - if (nPercentW == 1) - { - nPercentW = nPercentH; - if (canvasUseNewSize) - { - destX = Math.Max(0, Convert.ToInt32((newWidth - (sourceImage.Width * nPercentW)) / 2)); - } - } - else if (nPercentH == 1) - { - nPercentH = nPercentW; - if (canvasUseNewSize) - { - destY = Math.Max(0, Convert.ToInt32((newHeight - (sourceImage.Height * nPercentH)) / 2)); - } - } - else if (nPercentH != 0 && nPercentH < nPercentW) - { - nPercentW = nPercentH; - if (canvasUseNewSize) - { - destX = Math.Max(0, Convert.ToInt32((newWidth - (sourceImage.Width * nPercentW)) / 2)); - } - } - else - { - nPercentH = nPercentW; - if (canvasUseNewSize) - { - destY = Math.Max(0, Convert.ToInt32((newHeight - (sourceImage.Height * nPercentH)) / 2)); - } - } - } - - int destWidth = (int)(sourceImage.Width * nPercentW); - int destHeight = (int)(sourceImage.Height * nPercentH); - if (newWidth == 0) - { - newWidth = destWidth; - } - if (newHeight == 0) - { - newHeight = destHeight; - } - Image newImage = null; - if (maintainAspectRatio && canvasUseNewSize) - { - newImage = CreateEmpty(newWidth, newHeight, sourceImage.PixelFormat, backgroundColor, sourceImage.HorizontalResolution, sourceImage.VerticalResolution); - if (matrix != null) - { - matrix.Scale((float)newWidth / sourceImage.Width, (float)newHeight / sourceImage.Height, MatrixOrder.Append); - } - } - else - { - newImage = CreateEmpty(destWidth, destHeight, sourceImage.PixelFormat, backgroundColor, sourceImage.HorizontalResolution, sourceImage.VerticalResolution); - if (matrix != null) - { - matrix.Scale((float)destWidth / sourceImage.Width, (float)destHeight / sourceImage.Height, MatrixOrder.Append); - } - } - - using (Graphics graphics = Graphics.FromImage(newImage)) - { - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - using (ImageAttributes wrapMode = new ImageAttributes()) - { - wrapMode.SetWrapMode(WrapMode.TileFlipXY); - graphics.DrawImage(sourceImage, new Rectangle(destX, destY, destWidth, destHeight), 0, 0, sourceImage.Width, sourceImage.Height, GraphicsUnit.Pixel, wrapMode); - } - } - return newImage; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Core/ImageOutput.cs b/Greenshot.ImageEditor/Core/ImageOutput.cs deleted file mode 100644 index cda7a4bcb..000000000 --- a/Greenshot.ImageEditor/Core/ImageOutput.cs +++ /dev/null @@ -1,728 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.IniFile; -using Greenshot.Plugin; -using GreenshotPlugin.Controls; -using System; -using System.Diagnostics; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Imaging; -using System.IO; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Text; -using System.Text.RegularExpressions; -using System.Windows.Forms; -using Encoder = System.Drawing.Imaging.Encoder; - -namespace GreenshotPlugin.Core -{ - /// - /// Description of ImageOutput. - /// - public static class ImageOutput - { - private static readonly CoreConfiguration conf = IniConfig.GetIniSection(); - private static readonly int PROPERTY_TAG_SOFTWARE_USED = 0x0131; - private static readonly Cache tmpFileCache = new Cache(10 * 60 * 60, RemoveExpiredTmpFile); - - /// - /// Creates a PropertyItem (Metadata) to store with the image. - /// For the possible ID's see: http://msdn.microsoft.com/de-de/library/system.drawing.imaging.propertyitem.id(v=vs.80).aspx - /// This code uses Reflection to create a PropertyItem, although it's not adviced it's not as stupid as having a image in the project so we can read a PropertyItem from that! - /// - /// ID - /// Text - /// - private static PropertyItem CreatePropertyItem(int id, string text) - { - PropertyItem propertyItem = null; - try - { - ConstructorInfo ci = typeof(PropertyItem).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, new Type[] { }, null); - propertyItem = (PropertyItem)ci.Invoke(null); - // Make sure it's of type string - propertyItem.Type = 2; - // Set the ID - propertyItem.Id = id; - // Set the text - byte[] byteString = Encoding.ASCII.GetBytes(text + " "); - // Set Zero byte for String end. - byteString[byteString.Length - 1] = 0; - propertyItem.Value = byteString; - propertyItem.Len = text.Length + 1; - } - catch (Exception e) - { - LOG.WarnFormat("Error creating a PropertyItem: {0}", e.Message); - } - return propertyItem; - } - - #region save - - /// - /// Saves ISurface to stream with specified output settings - /// - /// ISurface to save - /// Stream to save to - /// SurfaceOutputSettings - public static void SaveToStream(ISurface surface, Stream stream, SurfaceOutputSettings outputSettings) - { - Image imageToSave; - bool disposeImage = CreateImageFromSurface(surface, outputSettings, out imageToSave); - SaveToStream(imageToSave, surface, stream, outputSettings); - // cleanup if needed - if (disposeImage && imageToSave != null) - { - imageToSave.Dispose(); - } - } - - /// - /// Saves image to stream with specified quality - /// To prevent problems with GDI version of before Windows 7: - /// the stream is checked if it's seekable and if needed a MemoryStream as "cache" is used. - /// - /// image to save - /// surface for the elements, needed if the greenshot format is used - /// Stream to save to - /// SurfaceOutputSettings - public static void SaveToStream(Image imageToSave, ISurface surface, Stream stream, SurfaceOutputSettings outputSettings) - { - ImageFormat imageFormat; - bool useMemoryStream = false; - MemoryStream memoryStream = null; - if (outputSettings.Format == OutputFormat.greenshot && surface == null) - { - throw new ArgumentException("Surface needs to be se when using OutputFormat.Greenshot"); - } - - try - { - switch (outputSettings.Format) - { - case OutputFormat.bmp: - imageFormat = ImageFormat.Bmp; - break; - case OutputFormat.gif: - imageFormat = ImageFormat.Gif; - break; - case OutputFormat.jpg: - imageFormat = ImageFormat.Jpeg; - break; - case OutputFormat.tiff: - imageFormat = ImageFormat.Tiff; - break; - default: - // Problem with non-seekable streams most likely doesn't happen with Windows 7 (OS Version 6.1 and later) - // http://stackoverflow.com/questions/8349260/generic-gdi-error-on-one-machine-but-not-the-other - if (!stream.CanSeek) - { - int majorVersion = Environment.OSVersion.Version.Major; - int minorVersion = Environment.OSVersion.Version.Minor; - if (majorVersion < 6 || (majorVersion == 6 && minorVersion == 0)) - { - useMemoryStream = true; - LOG.Warn("Using memorystream prevent an issue with saving to a non seekable stream."); - } - } - imageFormat = ImageFormat.Png; - break; - } - LOG.DebugFormat("Saving image to stream with Format {0} and PixelFormat {1}", imageFormat, imageToSave.PixelFormat); - - // Check if we want to use a memory stream, to prevent a issue which happens with Windows before "7". - // The save is made to the targetStream, this is directed to either the MemoryStream or the original - Stream targetStream = stream; - if (useMemoryStream) - { - memoryStream = new MemoryStream(); - targetStream = memoryStream; - } - - if (Equals(imageFormat, ImageFormat.Jpeg)) - { - bool foundEncoder = false; - foreach (ImageCodecInfo imageCodec in ImageCodecInfo.GetImageEncoders()) - { - if (imageCodec.FormatID == imageFormat.Guid) - { - EncoderParameters parameters = new EncoderParameters(1); - parameters.Param[0] = new EncoderParameter(Encoder.Quality, outputSettings.JPGQuality); - // Removing transparency if it's not supported in the output - if (Image.IsAlphaPixelFormat(imageToSave.PixelFormat)) - { - Image nonAlphaImage = ImageHelper.Clone(imageToSave, PixelFormat.Format24bppRgb); - AddTag(nonAlphaImage); - nonAlphaImage.Save(targetStream, imageCodec, parameters); - nonAlphaImage.Dispose(); - nonAlphaImage = null; - } - else - { - AddTag(imageToSave); - imageToSave.Save(targetStream, imageCodec, parameters); - } - foundEncoder = true; - break; - } - } - if (!foundEncoder) - { - throw new ApplicationException("No JPG encoder found, this should not happen."); - } - } - else - { - bool needsDispose = false; - // Removing transparency if it's not supported in the output - if (!Equals(imageFormat, ImageFormat.Png) && Image.IsAlphaPixelFormat(imageToSave.PixelFormat)) - { - imageToSave = ImageHelper.Clone(imageToSave, PixelFormat.Format24bppRgb); - needsDispose = true; - } - AddTag(imageToSave); - // Added for OptiPNG - bool processed = false; - if (Equals(imageFormat, ImageFormat.Png) && !string.IsNullOrEmpty(conf.OptimizePNGCommand)) - { - processed = ProcessPNGImageExternally(imageToSave, targetStream); - } - if (!processed) - { - imageToSave.Save(targetStream, imageFormat); - } - if (needsDispose) - { - imageToSave.Dispose(); - imageToSave = null; - } - } - - // If we used a memory stream, we need to stream the memory stream to the original stream. - if (useMemoryStream) - { - memoryStream.WriteTo(stream); - } - - // Output the surface elements, size and marker to the stream - if (outputSettings.Format == OutputFormat.greenshot) - { - using (MemoryStream tmpStream = new MemoryStream()) - { - long bytesWritten = surface.SaveElementsToStream(tmpStream); - using (BinaryWriter writer = new BinaryWriter(tmpStream)) - { - writer.Write(bytesWritten); - Version v = Assembly.GetExecutingAssembly().GetName().Version; - byte[] marker = Encoding.ASCII.GetBytes(String.Format("Greenshot{0:00}.{1:00}", v.Major, v.Minor)); - writer.Write(marker); - tmpStream.WriteTo(stream); - } - } - } - } - finally - { - if (memoryStream != null) - { - memoryStream.Dispose(); - } - } - } - - /// - /// Write the passed Image to a tmp-file and call an external process, than read the file back and write it to the targetStream - /// - /// Image to pass to the external process - /// stream to write the processed image to - /// - private static bool ProcessPNGImageExternally(Image imageToProcess, Stream targetStream) - { - if (string.IsNullOrEmpty(conf.OptimizePNGCommand)) - { - return false; - } - if (!File.Exists(conf.OptimizePNGCommand)) - { - LOG.WarnFormat("Can't find 'OptimizePNGCommand' {0}", conf.OptimizePNGCommand); - return false; - } - string tmpFileName = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName() + ".png"); - try - { - using (FileStream tmpStream = File.Create(tmpFileName)) - { - LOG.DebugFormat("Writing png to tmp file: {0}", tmpFileName); - imageToProcess.Save(tmpStream, ImageFormat.Png); - if (LOG.IsDebugEnabled) - { - LOG.DebugFormat("File size before processing {0}", new FileInfo(tmpFileName).Length); - } - } - if (LOG.IsDebugEnabled) - { - LOG.DebugFormat("Starting : {0}", conf.OptimizePNGCommand); - } - - ProcessStartInfo processStartInfo = new ProcessStartInfo(conf.OptimizePNGCommand); - processStartInfo.Arguments = string.Format(conf.OptimizePNGCommandArguments, tmpFileName); - processStartInfo.CreateNoWindow = true; - processStartInfo.RedirectStandardOutput = true; - processStartInfo.RedirectStandardError = true; - processStartInfo.UseShellExecute = false; - using (Process process = Process.Start(processStartInfo)) - { - if (process != null) - { - process.WaitForExit(); - if (process.ExitCode == 0) - { - if (LOG.IsDebugEnabled) - { - LOG.DebugFormat("File size after processing {0}", new FileInfo(tmpFileName).Length); - LOG.DebugFormat("Reading back tmp file: {0}", tmpFileName); - } - byte[] processedImage = File.ReadAllBytes(tmpFileName); - targetStream.Write(processedImage, 0, processedImage.Length); - return true; - } - LOG.ErrorFormat("Error while processing PNG image: {0}", process.ExitCode); - LOG.ErrorFormat("Output: {0}", process.StandardOutput.ReadToEnd()); - LOG.ErrorFormat("Error: {0}", process.StandardError.ReadToEnd()); - } - } - } - catch (Exception e) - { - LOG.Error("Error while processing PNG image: ", e); - } - finally - { - if (File.Exists(tmpFileName)) - { - LOG.DebugFormat("Cleaning up tmp file: {0}", tmpFileName); - File.Delete(tmpFileName); - } - } - return false; - } - - /// - /// Create an image from a surface with the settings from the output settings applied - /// - /// - /// - /// - /// true if the image must be disposed - public static bool CreateImageFromSurface(ISurface surface, SurfaceOutputSettings outputSettings, out Image imageToSave) - { - bool disposeImage = false; - - if (outputSettings.Format == OutputFormat.greenshot || outputSettings.SaveBackgroundOnly) - { - // We save the image of the surface, this should not be disposed - imageToSave = surface.Image; - } - else - { - // We create the export image of the surface to save - imageToSave = surface.GetImageForExport(); - disposeImage = true; - } - - // The following block of modifications should be skipped when saving the greenshot format, no effects or otherwise! - if (outputSettings.Format == OutputFormat.greenshot) - { - return disposeImage; - } - Image tmpImage; - if (outputSettings.Effects != null && outputSettings.Effects.Count > 0) - { - // apply effects, if there are any - using (Matrix matrix = new Matrix()) - { - tmpImage = ImageHelper.ApplyEffects(imageToSave, outputSettings.Effects, matrix); - } - if (tmpImage != null) - { - if (disposeImage) - { - imageToSave.Dispose(); - } - imageToSave = tmpImage; - disposeImage = true; - } - } - - // check for color reduction, forced or automatically, only when the DisableReduceColors is false - if (outputSettings.DisableReduceColors || (!conf.OutputFileAutoReduceColors && !outputSettings.ReduceColors)) - { - return disposeImage; - } - bool isAlpha = Image.IsAlphaPixelFormat(imageToSave.PixelFormat); - if (outputSettings.ReduceColors || (!isAlpha && conf.OutputFileAutoReduceColors)) - { - using (var quantizer = new WuQuantizer((Bitmap)imageToSave)) - { - int colorCount = quantizer.GetColorCount(); - LOG.InfoFormat("Image with format {0} has {1} colors", imageToSave.PixelFormat, colorCount); - if (!outputSettings.ReduceColors && colorCount >= 256) - { - return disposeImage; - } - try - { - LOG.Info("Reducing colors on bitmap to 256."); - tmpImage = quantizer.GetQuantizedImage(conf.OutputFileReduceColorsTo); - if (disposeImage) - { - imageToSave.Dispose(); - } - imageToSave = tmpImage; - // Make sure the "new" image is disposed - disposeImage = true; - } - catch (Exception e) - { - LOG.Warn("Error occurred while Quantizing the image, ignoring and using original. Error: ", e); - } - } - } - else if (isAlpha && !outputSettings.ReduceColors) - { - LOG.Info("Skipping 'optional' color reduction as the image has alpha"); - } - return disposeImage; - } - - /// - /// Add the greenshot property! - /// - /// - private static void AddTag(Image imageToSave) - { - // Create meta-data - PropertyItem softwareUsedPropertyItem = CreatePropertyItem(PROPERTY_TAG_SOFTWARE_USED, "Greenshot"); - if (softwareUsedPropertyItem != null) - { - try - { - imageToSave.SetPropertyItem(softwareUsedPropertyItem); - } - catch (Exception) - { - LOG.WarnFormat("Couldn't set property {0}", softwareUsedPropertyItem.Id); - } - } - } - - /// - /// Load a Greenshot surface - /// - /// - /// - /// - public static ISurface LoadGreenshotSurface(string fullPath, ISurface returnSurface) - { - if (string.IsNullOrEmpty(fullPath)) - { - return null; - } - Image fileImage; - LOG.InfoFormat("Loading image from file {0}", fullPath); - // Fixed lock problem Bug #3431881 - using (Stream surfaceFileStream = File.OpenRead(fullPath)) - { - // And fixed problem that the bitmap stream is disposed... by Cloning the image - // This also ensures the bitmap is correctly created - - // We create a copy of the bitmap, so everything else can be disposed - surfaceFileStream.Position = 0; - using (Image tmpImage = Image.FromStream(surfaceFileStream, true, true)) - { - LOG.DebugFormat("Loaded {0} with Size {1}x{2} and PixelFormat {3}", fullPath, tmpImage.Width, tmpImage.Height, tmpImage.PixelFormat); - fileImage = ImageHelper.Clone(tmpImage); - } - // Start at -14 read "GreenshotXX.YY" (XX=Major, YY=Minor) - const int markerSize = 14; - surfaceFileStream.Seek(-markerSize, SeekOrigin.End); - string greenshotMarker; - using (StreamReader streamReader = new StreamReader(surfaceFileStream)) - { - greenshotMarker = streamReader.ReadToEnd(); - if (!greenshotMarker.StartsWith("Greenshot")) - { - throw new ArgumentException(string.Format("{0} is not a Greenshot file!", fullPath)); - } - LOG.InfoFormat("Greenshot file format: {0}", greenshotMarker); - const int filesizeLocation = 8 + markerSize; - surfaceFileStream.Seek(-filesizeLocation, SeekOrigin.End); - using (BinaryReader reader = new BinaryReader(surfaceFileStream)) - { - long bytesWritten = reader.ReadInt64(); - surfaceFileStream.Seek(-(bytesWritten + filesizeLocation), SeekOrigin.End); - returnSurface.LoadElementsFromStream(surfaceFileStream); - } - } - } - if (fileImage != null) - { - returnSurface.Image = fileImage; - LOG.InfoFormat("Information about file {0}: {1}x{2}-{3} Resolution {4}x{5}", fullPath, fileImage.Width, fileImage.Height, fileImage.PixelFormat, fileImage.HorizontalResolution, fileImage.VerticalResolution); - } - return returnSurface; - } - - /// - /// Saves image to specific path with specified quality - /// - public static void Save(ISurface surface, string fullPath, bool allowOverwrite, SurfaceOutputSettings outputSettings, bool copyPathToClipboard) - { - fullPath = FilenameHelper.MakeFQFilenameSafe(fullPath); - string path = Path.GetDirectoryName(fullPath); - - // check whether path exists - if not create it - if (path != null) - { - DirectoryInfo di = new DirectoryInfo(path); - if (!di.Exists) - { - Directory.CreateDirectory(di.FullName); - } - } - - if (!allowOverwrite && File.Exists(fullPath)) - { - ArgumentException throwingException = new ArgumentException("File '" + fullPath + "' already exists."); - throwingException.Data.Add("fullPath", fullPath); - throw throwingException; - } - LOG.DebugFormat("Saving surface to {0}", fullPath); - // Create the stream and call SaveToStream - using (FileStream stream = new FileStream(fullPath, FileMode.Create, FileAccess.Write)) - { - SaveToStream(surface, stream, outputSettings); - } - - if (copyPathToClipboard) - { - ClipboardHelper.SetClipboardData(fullPath); - } - } - - /// - /// Get the OutputFormat for a filename - /// - /// filename (can be a complete path) - /// OutputFormat - public static OutputFormat FormatForFilename(string fullPath) - { - // Fix for bug 2912959 - string extension = fullPath.Substring(fullPath.LastIndexOf(".") + 1); - OutputFormat format = OutputFormat.png; - try - { - format = (OutputFormat)Enum.Parse(typeof(OutputFormat), extension.ToLower()); - } - catch (ArgumentException ae) - { - LOG.Warn("Couldn't parse extension: " + extension, ae); - } - return format; - } - - #endregion save - - #region save-as - - /// - /// Save with showing a dialog - /// - /// - /// - /// Path to filename - public static string SaveWithDialog(ISurface surface, ICaptureDetails captureDetails) - { - string returnValue = null; - using (SaveImageFileDialog saveImageFileDialog = new SaveImageFileDialog(captureDetails)) - { - DialogResult dialogResult = saveImageFileDialog.ShowDialog(); - if (dialogResult.Equals(DialogResult.OK)) - { - try - { - string fileNameWithExtension = saveImageFileDialog.FileNameWithExtension; - SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(FormatForFilename(fileNameWithExtension)); - if (conf.OutputFilePromptQuality) - { - QualityDialog qualityDialog = new QualityDialog(outputSettings); - qualityDialog.ShowDialog(); - } - // For now we always overwrite, should be changed - Save(surface, fileNameWithExtension, true, outputSettings, conf.OutputFileCopyPathToClipboard); - returnValue = fileNameWithExtension; - IniConfig.Save(); - } - catch (ExternalException) - { - MessageBox.Show(string.Format("Cannot save file to {0}.\r\nPlease check write accessibility of the selected storage location.", - saveImageFileDialog.FileName).Replace(@"\\", @"\"), "Error"); - } - } - } - return returnValue; - } - - #endregion save-as - - /// - /// Create a tmpfile which has the name like in the configured pattern. - /// Used e.g. by the email export - /// - /// - /// - /// - /// Path to image file - public static string SaveNamedTmpFile(ISurface surface, ICaptureDetails captureDetails, SurfaceOutputSettings outputSettings) - { - string pattern = conf.OutputFileFilenamePattern; - if (pattern == null || string.IsNullOrEmpty(pattern.Trim())) - { - pattern = "greenshot ${capturetime}"; - } - string filename = FilenameHelper.GetFilenameFromPattern(pattern, outputSettings.Format, captureDetails); - // Prevent problems with "other characters", which causes a problem in e.g. Outlook 2007 or break our HTML - filename = Regex.Replace(filename, @"[^\d\w\.]", "_"); - // Remove multiple "_" - filename = Regex.Replace(filename, @"_+", "_"); - string tmpFile = Path.Combine(Path.GetTempPath(), filename); - - LOG.Debug("Creating TMP File: " + tmpFile); - - // Catching any exception to prevent that the user can't write in the directory. - // This is done for e.g. bugs #2974608, #2963943, #2816163, #2795317, #2789218 - try - { - Save(surface, tmpFile, true, outputSettings, false); - tmpFileCache.Add(tmpFile, tmpFile); - } - catch (Exception e) - { - // Show the problem - MessageBox.Show(e.Message, "Error"); - // when save failed we present a SaveWithDialog - tmpFile = SaveWithDialog(surface, captureDetails); - } - return tmpFile; - } - - /// - /// Remove a tmpfile which was created by SaveNamedTmpFile - /// Used e.g. by the email export - /// - /// - /// true if it worked - public static bool DeleteNamedTmpFile(string tmpfile) - { - LOG.Debug("Deleting TMP File: " + tmpfile); - try - { - if (File.Exists(tmpfile)) - { - File.Delete(tmpfile); - tmpFileCache.Remove(tmpfile); - } - return true; - } - catch (Exception ex) - { - LOG.Warn("Error deleting tmp file: ", ex); - } - return false; - } - - /// - /// Helper method to create a temp image file - /// - /// - /// - /// - /// - public static string SaveToTmpFile(ISurface surface, SurfaceOutputSettings outputSettings, string destinationPath) - { - string tmpFile = Path.GetRandomFileName() + "." + outputSettings.Format.ToString(); - // Prevent problems with "other characters", which could cause problems - tmpFile = Regex.Replace(tmpFile, @"[^\d\w\.]", ""); - if (destinationPath == null) - { - destinationPath = Path.GetTempPath(); - } - string tmpPath = Path.Combine(destinationPath, tmpFile); - LOG.Debug("Creating TMP File : " + tmpPath); - - try - { - Save(surface, tmpPath, true, outputSettings, false); - tmpFileCache.Add(tmpPath, tmpPath); - } - catch (Exception) - { - return null; - } - return tmpPath; - } - - /// - /// Cleanup all created tmpfiles - /// - public static void RemoveTmpFiles() - { - foreach (string tmpFile in tmpFileCache.Elements) - { - if (File.Exists(tmpFile)) - { - LOG.DebugFormat("Removing old temp file {0}", tmpFile); - File.Delete(tmpFile); - } - tmpFileCache.Remove(tmpFile); - } - } - - /// - /// Cleanup handler for expired tempfiles - /// - /// - /// - private static void RemoveExpiredTmpFile(string filekey, object filename) - { - string path = filename as string; - if (path != null && File.Exists(path)) - { - LOG.DebugFormat("Removing expired file {0}", path); - File.Delete(path); - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Core/NetworkHelper.cs b/Greenshot.ImageEditor/Core/NetworkHelper.cs deleted file mode 100644 index eb5e6c641..000000000 --- a/Greenshot.ImageEditor/Core/NetworkHelper.cs +++ /dev/null @@ -1,907 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.IniFile; -using Greenshot.Plugin; -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Imaging; -using System.Globalization; -using System.IO; -using System.Net; -using System.Text; -using System.Text.RegularExpressions; - -namespace GreenshotPlugin.Core -{ - /// - /// HTTP Method to make sure we have the correct method - /// - public enum HTTPMethod - { - GET, - POST, - PUT, - DELETE, - HEAD - }; - - /// - /// Description of NetworkHelper. - /// - public static class NetworkHelper - { - private static readonly CoreConfiguration Config = IniConfig.GetIniSection(); - - static NetworkHelper() - { - try - { - // Disable certificate checking - ServicePointManager.ServerCertificateValidationCallback += delegate - { - return true; - }; - } - catch (Exception ex) - { - LOG.Warn("An error has occured while allowing self-signed certificates:", ex); - } - } - - /// - /// Download a uri response as string - /// - /// An Uri to specify the download location - /// string with the file content - public static string GetAsString(Uri uri) - { - return GetResponseAsString(CreateWebRequest(uri)); - } - - /// - /// Download the FavIcon as a Bitmap - /// - /// - /// Bitmap with the FavIcon - public static Bitmap DownloadFavIcon(Uri baseUri) - { - Uri url = new Uri(baseUri, new Uri("favicon.ico")); - try - { - HttpWebRequest request = CreateWebRequest(url); - using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) - { - if (request.HaveResponse) - { - using (Stream responseStream = response.GetResponseStream()) - { - if (responseStream != null) - { - using (Image image = Image.FromStream(responseStream)) - { - return (image.Height > 16 && image.Width > 16) ? new Bitmap(image, 16, 16) : new Bitmap(image); - } - } - } - } - } - } - catch (Exception e) - { - LOG.Error("Problem downloading the FavIcon from: " + baseUri, e); - } - return null; - } - - /// - /// Download the uri into a memorystream, without catching exceptions - /// - /// Of an image - /// MemoryStream which is already seeked to 0 - public static MemoryStream GetAsMemoryStream(string url) - { - HttpWebRequest request = CreateWebRequest(url); - using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) - { - MemoryStream memoryStream = new MemoryStream(); - using (Stream responseStream = response.GetResponseStream()) - { - if (responseStream != null) - { - responseStream.CopyTo(memoryStream); - } - // Make sure it can be used directly - memoryStream.Seek(0, SeekOrigin.Begin); - } - return memoryStream; - } - } - - /// - /// Download the uri to Bitmap - /// - /// Of an image - /// Bitmap - public static Image DownloadImage(string url) - { - try - { - string content; - using (MemoryStream memoryStream = GetAsMemoryStream(url)) - { - try - { - using (Image image = Image.FromStream(memoryStream)) - { - return ImageHelper.Clone(image, PixelFormat.Format32bppArgb); - } - } - catch (Exception) - { - // If we arrive here, the image loading didn't work, try to see if the response has a http(s) URL to an image and just take this instead. - using (StreamReader streamReader = new StreamReader(memoryStream, Encoding.UTF8, true)) - { - content = streamReader.ReadLine(); - } - if (!string.IsNullOrEmpty(content)) - { - Regex imageUrlRegex = new Regex(@"(http|https)://.*(\.png|\.gif|\.jpg|\.tiff|\.jpeg|\.bmp)"); - Match match = imageUrlRegex.Match(content); - if (match.Success) - { - using (MemoryStream memoryStream2 = GetAsMemoryStream(match.Value)) - { - using (Image image = Image.FromStream(memoryStream2)) - { - return ImageHelper.Clone(image, PixelFormat.Format32bppArgb); - } - } - } - } - throw; - } - } - } - catch (Exception e) - { - LOG.Error("Problem downloading the image from: " + url, e); - } - return null; - } - - /// - /// Helper method to create a web request with a lot of default settings - /// - /// string with uri to connect to - /// WebRequest - public static HttpWebRequest CreateWebRequest(string uri) - { - return CreateWebRequest(new Uri(uri)); - } - - /// - /// Helper method to create a web request with a lot of default settings - /// - /// string with uri to connect to - /// /// Method to use - /// WebRequest - public static HttpWebRequest CreateWebRequest(string uri, HTTPMethod method) - { - return CreateWebRequest(new Uri(uri), method); - } - - /// - /// Helper method to create a web request with a lot of default settings - /// - /// Uri with uri to connect to - /// Method to use - /// WebRequest - public static HttpWebRequest CreateWebRequest(Uri uri, HTTPMethod method) - { - HttpWebRequest webRequest = CreateWebRequest(uri); - webRequest.Method = method.ToString(); - return webRequest; - } - - /// - /// Helper method to create a web request, eventually with proxy - /// - /// Uri with uri to connect to - /// WebRequest - public static HttpWebRequest CreateWebRequest(Uri uri) - { - HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri); - webRequest.Proxy = Config.UseProxy ? CreateProxy(uri) : null; - // Make sure the default credentials are available - webRequest.Credentials = CredentialCache.DefaultCredentials; - - // Allow redirect, this is usually needed so that we don't get a problem when a service moves - webRequest.AllowAutoRedirect = true; - // Set default timeouts - webRequest.Timeout = Config.WebRequestTimeout * 1000; - webRequest.ReadWriteTimeout = Config.WebRequestReadWriteTimeout * 1000; - return webRequest; - } - - /// - /// Create a IWebProxy Object which can be used to access the Internet - /// This method will check the configuration if the proxy is allowed to be used. - /// Usages can be found in the DownloadFavIcon or Jira and Confluence plugins - /// - /// - /// IWebProxy filled with all the proxy details or null if none is set/wanted - public static IWebProxy CreateProxy(Uri uri) - { - IWebProxy proxyToUse = null; - if (Config.UseProxy) - { - proxyToUse = WebRequest.DefaultWebProxy; - if (proxyToUse != null) - { - proxyToUse.Credentials = CredentialCache.DefaultCredentials; - if (LOG.IsDebugEnabled) - { - // check the proxy for the Uri - if (!proxyToUse.IsBypassed(uri)) - { - Uri proxyUri = proxyToUse.GetProxy(uri); - if (proxyUri != null) - { - LOG.Debug("Using proxy: " + proxyUri + " for " + uri); - } - else - { - LOG.Debug("No proxy found!"); - } - } - else - { - LOG.Debug("Proxy bypass for: " + uri); - } - } - } - else - { - LOG.Debug("No proxy found!"); - } - } - return proxyToUse; - } - - /// - /// UrlEncodes a string without the requirement for System.Web - /// - /// - /// - // [Obsolete("Use System.Uri.EscapeDataString instead")] - public static string UrlEncode(string text) - { - if (!string.IsNullOrEmpty(text)) - { - // Sytem.Uri provides reliable parsing, but doesn't encode spaces. - return Uri.EscapeDataString(text).Replace("%20", "+"); - } - return null; - } - - /// - /// A wrapper around the EscapeDataString, as the limit is 32766 characters - /// See: http://msdn.microsoft.com/en-us/library/system.uri.escapedatastring%28v=vs.110%29.aspx - /// - /// - /// escaped data string - public static string EscapeDataString(string text) - { - if (!string.IsNullOrEmpty(text)) - { - StringBuilder result = new StringBuilder(); - int currentLocation = 0; - while (currentLocation < text.Length) - { - string process = text.Substring(currentLocation, Math.Min(16384, text.Length - currentLocation)); - result.Append(Uri.EscapeDataString(process)); - currentLocation = currentLocation + 16384; - } - return result.ToString(); - } - return null; - } - - /// - /// UrlDecodes a string without requiring System.Web - /// - /// String to decode. - /// decoded string - public static string UrlDecode(string text) - { - // pre-process for + sign space formatting since System.Uri doesn't handle it - // plus literals are encoded as %2b normally so this should be safe - text = text.Replace("+", " "); - return Uri.UnescapeDataString(text); - } - - /// - /// ParseQueryString without the requirement for System.Web - /// - /// - /// IDictionary string, string - public static IDictionary ParseQueryString(string queryString) - { - IDictionary parameters = new SortedDictionary(); - // remove anything other than query string from uri - if (queryString.Contains("?")) - { - queryString = queryString.Substring(queryString.IndexOf('?') + 1); - } - foreach (string vp in Regex.Split(queryString, "&")) - { - if (string.IsNullOrEmpty(vp)) - { - continue; - } - string[] singlePair = Regex.Split(vp, "="); - if (parameters.ContainsKey(singlePair[0])) - { - parameters.Remove(singlePair[0]); - } - parameters.Add(singlePair[0], singlePair.Length == 2 ? singlePair[1] : string.Empty); - } - return parameters; - } - - /// - /// Generate the query paramters - /// - /// the list of query parameters - /// a string with the query parameters - public static string GenerateQueryParameters(IDictionary queryParameters) - { - if (queryParameters == null || queryParameters.Count == 0) - { - return string.Empty; - } - - queryParameters = new SortedDictionary(queryParameters); - - StringBuilder sb = new StringBuilder(); - foreach (string key in queryParameters.Keys) - { - sb.AppendFormat(CultureInfo.InvariantCulture, "{0}={1}&", key, UrlEncode(string.Format("{0}", queryParameters[key]))); - } - sb.Remove(sb.Length - 1, 1); - - return sb.ToString(); - } - - /// - /// Write Multipart Form Data directly to the HttpWebRequest - /// - /// HttpWebRequest to write the multipart form data to - /// Parameters to include in the multipart form data - public static void WriteMultipartFormData(HttpWebRequest webRequest, IDictionary postParameters) - { - string boundary = String.Format("----------{0:N}", Guid.NewGuid()); - webRequest.ContentType = "multipart/form-data; boundary=" + boundary; - using (Stream formDataStream = webRequest.GetRequestStream()) - { - WriteMultipartFormData(formDataStream, boundary, postParameters); - } - } - - /// - /// Write Multipart Form Data to the HttpListenerResponse - /// - /// HttpListenerResponse - /// Parameters to include in the multipart form data - public static void WriteMultipartFormData(HttpListenerResponse response, IDictionary postParameters) - { - string boundary = String.Format("----------{0:N}", Guid.NewGuid()); - response.ContentType = "multipart/form-data; boundary=" + boundary; - WriteMultipartFormData(response.OutputStream, boundary, postParameters); - } - - /// - /// Write Multipart Form Data to a Stream, content-type should be set before this! - /// - /// Stream to write the multipart form data to - /// String boundary for the multipart/form-data - /// Parameters to include in the multipart form data - public static void WriteMultipartFormData(Stream formDataStream, string boundary, IDictionary postParameters) - { - bool needsClrf = false; - foreach (var param in postParameters) - { - // Add a CRLF to allow multiple parameters to be added. - // Skip it on the first parameter, add it to subsequent parameters. - if (needsClrf) - { - formDataStream.Write(Encoding.UTF8.GetBytes("\r\n"), 0, Encoding.UTF8.GetByteCount("\r\n")); - } - - needsClrf = true; - - if (param.Value is IBinaryContainer) - { - IBinaryContainer binaryParameter = (IBinaryContainer)param.Value; - binaryParameter.WriteFormDataToStream(boundary, param.Key, formDataStream); - } - else - { - string postData = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}", - boundary, - param.Key, - param.Value); - formDataStream.Write(Encoding.UTF8.GetBytes(postData), 0, Encoding.UTF8.GetByteCount(postData)); - } - } - - // Add the end of the request. Start with a newline - string footer = "\r\n--" + boundary + "--\r\n"; - formDataStream.Write(Encoding.UTF8.GetBytes(footer), 0, Encoding.UTF8.GetByteCount(footer)); - } - - /// - /// Post the parameters "x-www-form-urlencoded" - /// - /// - /// - public static void UploadFormUrlEncoded(HttpWebRequest webRequest, IDictionary parameters) - { - webRequest.ContentType = "application/x-www-form-urlencoded"; - string urlEncoded = GenerateQueryParameters(parameters); - - byte[] data = Encoding.UTF8.GetBytes(urlEncoded); - using (var requestStream = webRequest.GetRequestStream()) - { - requestStream.Write(data, 0, data.Length); - } - } - - /// - /// Log the headers of the WebResponse, if IsDebugEnabled - /// - /// WebResponse - private static void DebugHeaders(WebResponse response) - { - if (!LOG.IsDebugEnabled) - { - return; - } - LOG.DebugFormat("Debug information on the response from {0} :", response.ResponseUri); - foreach (string key in response.Headers.AllKeys) - { - LOG.DebugFormat("Reponse-header: {0}={1}", key, response.Headers[key]); - } - } - - /// - /// Process the web response. - /// - /// The request object. - /// The response data. - /// This method should handle the StatusCode better! - public static string GetResponseAsString(HttpWebRequest webRequest) - { - return GetResponseAsString(webRequest, false); - } - - /// - /// Read the response as string - /// - /// - /// string or null - private static string GetResponseAsString(HttpWebResponse response) - { - string responseData = null; - if (response == null) - { - return null; - } - using (response) - { - Stream responseStream = response.GetResponseStream(); - if (responseStream != null) - { - using (StreamReader reader = new StreamReader(responseStream, true)) - { - responseData = reader.ReadToEnd(); - } - } - } - return responseData; - } - - /// - /// - /// - /// - /// - /// - public static string GetResponseAsString(HttpWebRequest webRequest, bool alsoReturnContentOnError) - { - string responseData = null; - HttpWebResponse response = null; - bool isHttpError = false; - try - { - response = (HttpWebResponse)webRequest.GetResponse(); - LOG.InfoFormat("Response status: {0}", response.StatusCode); - isHttpError = (int)response.StatusCode >= 300; - if (isHttpError) - { - LOG.ErrorFormat("HTTP error {0}", response.StatusCode); - } - DebugHeaders(response); - responseData = GetResponseAsString(response); - if (isHttpError) - { - LOG.ErrorFormat("HTTP response {0}", responseData); - } - } - catch (WebException e) - { - response = (HttpWebResponse)e.Response; - HttpStatusCode statusCode = HttpStatusCode.Unused; - if (response != null) - { - statusCode = response.StatusCode; - LOG.ErrorFormat("HTTP error {0}", statusCode); - string errorContent = GetResponseAsString(response); - if (alsoReturnContentOnError) - { - return errorContent; - } - LOG.ErrorFormat("Content: {0}", errorContent); - } - LOG.Error("WebException: ", e); - if (statusCode == HttpStatusCode.Unauthorized) - { - throw new UnauthorizedAccessException(e.Message); - } - throw; - } - finally - { - if (response != null) - { - if (isHttpError) - { - LOG.ErrorFormat("HTTP error {0} with content: {1}", response.StatusCode, responseData); - } - response.Close(); - } - } - return responseData; - } - - /// - /// Get LastModified for a URI - /// - /// Uri - /// DateTime - public static DateTime GetLastModified(Uri uri) - { - try - { - HttpWebRequest webRequest = CreateWebRequest(uri); - webRequest.Method = HTTPMethod.HEAD.ToString(); - using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse()) - { - LOG.DebugFormat("RSS feed was updated at {0}", webResponse.LastModified); - return webResponse.LastModified; - } - } - catch (Exception wE) - { - LOG.WarnFormat("Problem requesting HTTP - HEAD on uri {0}", uri); - LOG.Warn(wE.Message); - // Pretend it is old - return DateTime.MinValue; - } - } - } - - /// - /// This interface can be used to pass binary information around, like byte[] or Image - /// - public interface IBinaryContainer - { - void WriteFormDataToStream(string boundary, string name, Stream formDataStream); - - void WriteToStream(Stream formDataStream); - - string ToBase64String(Base64FormattingOptions formattingOptions); - - byte[] ToByteArray(); - - void Upload(HttpWebRequest webRequest); - } - - /// - /// A container to supply files to a Multi-part form data upload - /// - public class ByteContainer : IBinaryContainer - { - private readonly byte[] _file; - private readonly string _fileName; - private readonly string _contentType; - private readonly int _fileSize; - - public ByteContainer(byte[] file) : this(file, null) - { - } - - public ByteContainer(byte[] file, string filename) : this(file, filename, null) - { - } - - public ByteContainer(byte[] file, string filename, string contenttype) : this(file, filename, contenttype, 0) - { - } - - public ByteContainer(byte[] file, string filename, string contenttype, int filesize) - { - _file = file; - _fileName = filename; - _contentType = contenttype; - _fileSize = filesize == 0 ? file.Length : filesize; - } - - /// - /// Create a Base64String from the byte[] - /// - /// string - public string ToBase64String(Base64FormattingOptions formattingOptions) - { - return Convert.ToBase64String(_file, 0, _fileSize, formattingOptions); - } - - /// - /// Returns the initial byte-array which was supplied when creating the FileParameter - /// - /// byte[] - public byte[] ToByteArray() - { - return _file; - } - - /// - /// Write Multipart Form Data directly to the HttpWebRequest response stream - /// - /// Separator - /// name - /// Stream to write to - public void WriteFormDataToStream(string boundary, string name, Stream formDataStream) - { - // Add just the first part of this param, since we will write the file data directly to the Stream - string header = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\";\r\nContent-Type: {3}\r\n\r\n", - boundary, - name, - _fileName ?? name, - _contentType ?? "application/octet-stream"); - - formDataStream.Write(Encoding.UTF8.GetBytes(header), 0, Encoding.UTF8.GetByteCount(header)); - - // Write the file data directly to the Stream, rather than serializing it to a string. - formDataStream.Write(_file, 0, _fileSize); - } - - /// - /// A plain "write data to stream" - /// - /// Stream to write to - public void WriteToStream(Stream dataStream) - { - // Write the file data directly to the Stream, rather than serializing it to a string. - dataStream.Write(_file, 0, _fileSize); - } - - /// - /// Upload the file to the webrequest - /// - /// - public void Upload(HttpWebRequest webRequest) - { - webRequest.ContentType = _contentType; - webRequest.ContentLength = _fileSize; - using (var requestStream = webRequest.GetRequestStream()) - { - WriteToStream(requestStream); - } - } - } - - /// - /// A container to supply images to a Multi-part form data upload - /// - public class BitmapContainer : IBinaryContainer - { - private readonly Bitmap _bitmap; - private readonly SurfaceOutputSettings _outputSettings; - private readonly string _fileName; - - public BitmapContainer(Bitmap bitmap, SurfaceOutputSettings outputSettings, string filename) - { - _bitmap = bitmap; - _outputSettings = outputSettings; - _fileName = filename; - } - - /// - /// Create a Base64String from the image by saving it to a memory stream and converting it. - /// Should be avoided if possible, as this uses a lot of memory. - /// - /// string - public string ToBase64String(Base64FormattingOptions formattingOptions) - { - using (MemoryStream stream = new MemoryStream()) - { - ImageOutput.SaveToStream(_bitmap, null, stream, _outputSettings); - return Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length, formattingOptions); - } - } - - /// - /// Create a byte[] from the image by saving it to a memory stream. - /// Should be avoided if possible, as this uses a lot of memory. - /// - /// byte[] - public byte[] ToByteArray() - { - using (MemoryStream stream = new MemoryStream()) - { - ImageOutput.SaveToStream(_bitmap, null, stream, _outputSettings); - return stream.ToArray(); - } - } - - /// - /// Write Multipart Form Data directly to the HttpWebRequest response stream - /// - /// Separator - /// Name of the thing/file - /// Stream to write to - public void WriteFormDataToStream(string boundary, string name, Stream formDataStream) - { - // Add just the first part of this param, since we will write the file data directly to the Stream - string header = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\";\r\nContent-Type: {3}\r\n\r\n", - boundary, - name, - _fileName ?? name, - "image/" + _outputSettings.Format); - - formDataStream.Write(Encoding.UTF8.GetBytes(header), 0, Encoding.UTF8.GetByteCount(header)); - ImageOutput.SaveToStream(_bitmap, null, formDataStream, _outputSettings); - } - - /// - /// A plain "write data to stream" - /// - /// - public void WriteToStream(Stream dataStream) - { - // Write the file data directly to the Stream, rather than serializing it to a string. - ImageOutput.SaveToStream(_bitmap, null, dataStream, _outputSettings); - } - - /// - /// Upload the image to the webrequest - /// - /// - public void Upload(HttpWebRequest webRequest) - { - webRequest.ContentType = "image/" + _outputSettings.Format; - using (var requestStream = webRequest.GetRequestStream()) - { - WriteToStream(requestStream); - } - } - } - - /// - /// A container to supply surfaces to a Multi-part form data upload - /// - public class SurfaceContainer : IBinaryContainer - { - private readonly ISurface _surface; - private readonly SurfaceOutputSettings _outputSettings; - private readonly string _fileName; - - public SurfaceContainer(ISurface surface, SurfaceOutputSettings outputSettings, string filename) - { - _surface = surface; - _outputSettings = outputSettings; - _fileName = filename; - } - - /// - /// Create a Base64String from the Surface by saving it to a memory stream and converting it. - /// Should be avoided if possible, as this uses a lot of memory. - /// - /// string - public string ToBase64String(Base64FormattingOptions formattingOptions) - { - using (MemoryStream stream = new MemoryStream()) - { - ImageOutput.SaveToStream(_surface, stream, _outputSettings); - return Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length, formattingOptions); - } - } - - /// - /// Create a byte[] from the image by saving it to a memory stream. - /// Should be avoided if possible, as this uses a lot of memory. - /// - /// byte[] - public byte[] ToByteArray() - { - using (MemoryStream stream = new MemoryStream()) - { - ImageOutput.SaveToStream(_surface, stream, _outputSettings); - return stream.ToArray(); - } - } - - /// - /// Write Multipart Form Data directly to the HttpWebRequest response stream - /// - /// Multipart separator - /// Name of the thing - /// Stream to write to - public void WriteFormDataToStream(string boundary, string name, Stream formDataStream) - { - // Add just the first part of this param, since we will write the file data directly to the Stream - string header = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\";\r\nContent-Type: {3}\r\n\r\n", - boundary, - name, - _fileName ?? name, - "image/" + _outputSettings.Format); - - formDataStream.Write(Encoding.UTF8.GetBytes(header), 0, Encoding.UTF8.GetByteCount(header)); - ImageOutput.SaveToStream(_surface, formDataStream, _outputSettings); - } - - /// - /// A plain "write data to stream" - /// - /// - public void WriteToStream(Stream dataStream) - { - // Write the file data directly to the Stream, rather than serializing it to a string. - ImageOutput.SaveToStream(_surface, dataStream, _outputSettings); - } - - /// - /// Upload the Surface as image to the webrequest - /// - /// - public void Upload(HttpWebRequest webRequest) - { - webRequest.ContentType = "image/" + _outputSettings.Format.ToString(); - using (var requestStream = webRequest.GetRequestStream()) - { - WriteToStream(requestStream); - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Core/Objects.cs b/Greenshot.ImageEditor/Core/Objects.cs deleted file mode 100644 index 828ef506e..000000000 --- a/Greenshot.ImageEditor/Core/Objects.cs +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Runtime.Serialization; -using System.Runtime.Serialization.Formatters.Binary; - -namespace GreenshotPlugin.Core -{ - public static class Objects - { - /// - /// Perform a deep Copy of the object. - /// - /// The type of object being copied. - /// The object instance to copy. - /// The copied object. - public static T Clone(this T source) - { - if (!typeof(T).IsSerializable) - { - throw new ArgumentException("The type must be serializable.", "source"); - } - - // Don't serialize a null object, simply return the default for that object - if (ReferenceEquals(source, null)) - { - return default(T); - } - - IFormatter formatter = new BinaryFormatter(); - Stream stream = new MemoryStream(); - using (stream) - { - formatter.Serialize(stream, source); - stream.Seek(0, SeekOrigin.Begin); - return (T)formatter.Deserialize(stream); - } - } - - public static void CloneTo(this T source, T destination) - { - Type type = typeof(T); - FieldInfo[] myObjectFields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); - - foreach (FieldInfo fi in myObjectFields) - { - fi.SetValue(destination, fi.GetValue(source)); - } - PropertyInfo[] myObjectProperties = type.GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); - - foreach (PropertyInfo pi in myObjectProperties) - { - if (pi.CanWrite) - { - pi.SetValue(destination, pi.GetValue(source, null), null); - } - } - } - - public static bool CompareLists(IList l1, IList l2) - { - if (l1.Count != l2.Count) - { - return false; - } - int matched = 0; - foreach (T item in l1) - { - if (!l2.Contains(item)) - { - return false; - } - matched++; - } - return matched == l1.Count; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Core/OperatingSystemExtensions.cs b/Greenshot.ImageEditor/Core/OperatingSystemExtensions.cs deleted file mode 100644 index 70a2495b6..000000000 --- a/Greenshot.ImageEditor/Core/OperatingSystemExtensions.cs +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub: https://github.com/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 . - */ - -using System; - -namespace GreenshotPlugin.Core -{ - /// - /// Extensions to help with querying the Operating System - /// - public static class OperatingSystemExtensions - { - /// - /// Test if the current OS is Windows 10 - /// - /// OperatingSystem from Environment.OSVersion - /// true if we are running on Windows 10 - public static bool IsWindows10(this OperatingSystem operatingSystem) - { - return operatingSystem.Version.Major == 10; - } - - /// - /// Test if the current OS is Windows 8(.1) - /// - /// OperatingSystem from Environment.OSVersion - /// true if we are running on Windows 8(.1) - public static bool IsWindows8(this OperatingSystem operatingSystem) - { - return operatingSystem.Version.Major == 6 && operatingSystem.Version.Minor >= 2; - } - - /// - /// Test if the current OS is Windows 8 or later - /// - /// OperatingSystem from Environment.OSVersion - /// true if we are running on Windows 8 or later - public static bool IsWindows8OrLater(this OperatingSystem operatingSystem) - { - return (operatingSystem.Version.Major == 6 && operatingSystem.Version.Minor >= 2) || operatingSystem.Version.Major >= 6; - } - - /// - /// Test if the current OS is Windows 7 or later - /// - /// OperatingSystem from Environment.OSVersion - /// true if we are running on Windows 7 or later - public static bool IsWindows7OrLater(this OperatingSystem operatingSystem) - { - return (operatingSystem.Version.Major == 6 && operatingSystem.Version.Minor >= 1) || operatingSystem.Version.Major >= 6; - } - - /// - /// Test if the current OS is Windows Vista or later - /// - /// OperatingSystem from Environment.OSVersion - /// true if we are running on Windows Vista or later - public static bool IsWindowsVistaOrLater(this OperatingSystem operatingSystem) - { - return operatingSystem.Version.Major >= 6; - } - - /// - /// Test if the current OS is Windows XP or later - /// - /// OperatingSystem from Environment.OSVersion - /// true if we are running on Windows XP or later - public static bool IsWindowsXpOrLater(this OperatingSystem operatingSystem) - { - // Windows 2000 is Major 5 minor 0 - return Environment.OSVersion.Version.Major > 5 || (Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1); - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Core/PluginUtils.cs b/Greenshot.ImageEditor/Core/PluginUtils.cs deleted file mode 100644 index 525fa0ffb..000000000 --- a/Greenshot.ImageEditor/Core/PluginUtils.cs +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.IniFile; -using Greenshot.Plugin; -using GreenshotPlugin.UnmanagedHelpers; -using Microsoft.Win32; -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Drawing; -using System.IO; -using System.Windows.Forms; - -namespace GreenshotPlugin.Core -{ - /// - /// Description of PluginUtils. - /// - public static class PluginUtils - { - private static readonly CoreConfiguration conf = IniConfig.GetIniSection(); - private const string PATH_KEY = @"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\"; - private static readonly IDictionary exeIconCache = new Dictionary(); - - static PluginUtils() - { - conf.PropertyChanged += OnIconSizeChanged; - } - - /// - /// Simple global property to get the Greenshot host - /// - public static IGreenshotHost Host - { - get; - set; - } - - /// - /// Clear icon cache - /// - /// - /// - private static void OnIconSizeChanged(object sender, PropertyChangedEventArgs e) - { - if (e.PropertyName == "IconSize") - { - List cachedImages = new List(); - lock (exeIconCache) - { - foreach (string key in exeIconCache.Keys) - { - cachedImages.Add(exeIconCache[key]); - } - exeIconCache.Clear(); - } - foreach (Image cachedImage in cachedImages) - { - if (cachedImage != null) - { - cachedImage.Dispose(); - } - } - } - } - - /// - /// Get the path of an executable - /// - /// e.g. cmd.exe - /// Path to file - public static string GetExePath(string exeName) - { - using (RegistryKey key = Registry.LocalMachine.OpenSubKey(PATH_KEY + exeName, false)) - { - if (key != null) - { - // "" is the default key, which should point to the requested location - return (string)key.GetValue(""); - } - } - foreach (string pathEntry in (Environment.GetEnvironmentVariable("PATH") ?? "").Split(';')) - { - try - { - string path = pathEntry.Trim(); - if (!String.IsNullOrEmpty(path) && File.Exists(path = Path.Combine(path, exeName))) - { - return Path.GetFullPath(path); - } - } - catch (Exception) - { - LOG.WarnFormat("Problem with path entry '{0}'.", pathEntry); - } - } - return null; - } - - /// - /// Get icon for executable, from the cache - /// - /// path to the exe or dll - /// index of the icon - /// Bitmap with the icon or null if something happended - public static Image GetCachedExeIcon(string path, int index) - { - string cacheKey = string.Format("{0}:{1}", path, index); - Image returnValue; - lock (exeIconCache) - { - if (!exeIconCache.TryGetValue(cacheKey, out returnValue)) - { - lock (exeIconCache) - { - if (!exeIconCache.TryGetValue(cacheKey, out returnValue)) - { - returnValue = GetExeIcon(path, index); - if (returnValue != null) - { - exeIconCache.Add(cacheKey, returnValue); - } - } - } - } - } - return returnValue; - } - - /// - /// Get icon for executable - /// - /// path to the exe or dll - /// index of the icon - /// Bitmap with the icon or null if something happended - private static Bitmap GetExeIcon(string path, int index) - { - if (!File.Exists(path)) - { - return null; - } - try - { - using (Icon appIcon = ImageHelper.ExtractAssociatedIcon(path, index, conf.UseLargeIcons)) - { - if (appIcon != null) - { - return appIcon.ToBitmap(); - } - } - using (Icon appIcon = Shell32.GetFileIcon(path, conf.UseLargeIcons ? Shell32.IconSize.Large : Shell32.IconSize.Small, false)) - { - if (appIcon != null) - { - return appIcon.ToBitmap(); - } - } - } - catch (Exception exIcon) - { - LOG.Error("error retrieving icon: ", exIcon); - } - return null; - } - - /// - /// Helper method to add a MenuItem to the File MenuItem of an ImageEditor - /// - /// Image to display in the menu - /// Text to display in the menu - /// The TAG value - /// Keys which can be used as shortcut - /// The onclick handler - public static void AddToFileMenu(IImageEditor imageEditor, Image image, string text, object tag, Keys? shortcutKeys, EventHandler handler) - { - ToolStripMenuItem item = new ToolStripMenuItem(); - item.Image = image; - item.Text = text; - item.Tag = tag; - if (shortcutKeys.HasValue) - { - item.ShortcutKeys = shortcutKeys.Value; - } - item.Click += handler; - AddToFileMenu(imageEditor, item); - } - - /// - /// Helper method to add a MenuItem to the File MenuItem of an ImageEditor - /// - /// - /// - public static void AddToFileMenu(IImageEditor imageEditor, ToolStripMenuItem item) - { - ToolStripMenuItem toolStripMenuItem = imageEditor.GetFileMenuItem(); - bool added = false; - for (int i = 0; i < toolStripMenuItem.DropDownItems.Count; i++) - { - if (toolStripMenuItem.DropDownItems[i].GetType() == typeof(ToolStripSeparator)) - { - toolStripMenuItem.DropDownItems.Insert(i, item); - added = true; - break; - } - } - if (!added) - { - toolStripMenuItem.DropDownItems.Add(item); - } - } - - /// - /// Helper method to add a MenuItem to the Plugin MenuItem of an ImageEditor - /// - /// - /// - public static void AddToPluginMenu(IImageEditor imageEditor, ToolStripMenuItem item) - { - ToolStripMenuItem toolStripMenuItem = imageEditor.GetPluginMenuItem(); - bool added = false; - for (int i = 0; i < toolStripMenuItem.DropDownItems.Count; i++) - { - if (toolStripMenuItem.DropDownItems[i].GetType() == typeof(ToolStripSeparator)) - { - toolStripMenuItem.DropDownItems.Insert(i, item); - added = true; - break; - } - } - if (!added) - { - toolStripMenuItem.DropDownItems.Add(item); - } - } - - /// - /// Helper method to add a plugin MenuItem to the Greenshot context menu - /// - /// - /// - public static void AddToContextMenu(IGreenshotHost host, ToolStripMenuItem item) - { - // Here we can hang ourselves to the main context menu! - ContextMenuStrip contextMenu = host.MainMenu; - bool addedItem = false; - - // Try to find a separator, so we insert ourselves after it - for (int i = 0; i < contextMenu.Items.Count; i++) - { - if (contextMenu.Items[i].GetType() == typeof(ToolStripSeparator)) - { - // Check if we need to add a new separator, which is done if the first found has a Tag with the value "PluginsAreAddedBefore" - if ("PluginsAreAddedBefore".Equals(contextMenu.Items[i].Tag)) - { - ToolStripSeparator separator = new ToolStripSeparator(); - separator.Tag = "PluginsAreAddedAfter"; - separator.Size = new Size(305, 6); - contextMenu.Items.Insert(i, separator); - } - else if (!"PluginsAreAddedAfter".Equals(contextMenu.Items[i].Tag)) - { - continue; - } - contextMenu.Items.Insert(i + 1, item); - addedItem = true; - break; - } - } - // If we didn't insert the item, we just add it... - if (!addedItem) - { - contextMenu.Items.Add(item); - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Core/QuantizerHelper.cs b/Greenshot.ImageEditor/Core/QuantizerHelper.cs deleted file mode 100644 index c5ca60e11..000000000 --- a/Greenshot.ImageEditor/Core/QuantizerHelper.cs +++ /dev/null @@ -1,770 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Imaging; - -namespace GreenshotPlugin.Core -{ - internal class WuColorCube - { - /// - /// Gets or sets the red minimum. - /// - /// The red minimum. - public Int32 RedMinimum { get; set; } - - /// - /// Gets or sets the red maximum. - /// - /// The red maximum. - public Int32 RedMaximum { get; set; } - - /// - /// Gets or sets the green minimum. - /// - /// The green minimum. - public Int32 GreenMinimum { get; set; } - - /// - /// Gets or sets the green maximum. - /// - /// The green maximum. - public Int32 GreenMaximum { get; set; } - - /// - /// Gets or sets the blue minimum. - /// - /// The blue minimum. - public Int32 BlueMinimum { get; set; } - - /// - /// Gets or sets the blue maximum. - /// - /// The blue maximum. - public Int32 BlueMaximum { get; set; } - - /// - /// Gets or sets the cube volume. - /// - /// The volume. - public Int32 Volume { get; set; } - } - - public class WuQuantizer : IDisposable - { - private const Int32 MAXCOLOR = 512; - private const Int32 RED = 2; - private const Int32 GREEN = 1; - private const Int32 BLUE = 0; - private const Int32 SIDESIZE = 33; - private const Int32 MAXSIDEINDEX = 32; - private const Int32 MAXVOLUME = SIDESIZE * SIDESIZE * SIDESIZE; - - // To count the colors - private readonly int colorCount; - - private Int32[] reds; - private Int32[] greens; - private Int32[] blues; - private Int32[] sums; - - private readonly Int64[,,] weights; - private readonly Int64[,,] momentsRed; - private readonly Int64[,,] momentsGreen; - private readonly Int64[,,] momentsBlue; - private readonly Single[,,] moments; - - private byte[] tag; - - private readonly WuColorCube[] cubes; - private readonly Bitmap sourceBitmap; - private Bitmap resultBitmap; - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - if (resultBitmap != null) - { - resultBitmap.Dispose(); - resultBitmap = null; - } - } - } - - /// - /// See for more details. - /// - public WuQuantizer(Bitmap sourceBitmap) - { - this.sourceBitmap = sourceBitmap; - // Make sure the color count variables are reset - BitArray bitArray = new BitArray((int)Math.Pow(2, 24)); - colorCount = 0; - - // creates all the cubes - cubes = new WuColorCube[MAXCOLOR]; - - // initializes all the cubes - for (Int32 cubeIndex = 0; cubeIndex < MAXCOLOR; cubeIndex++) - { - cubes[cubeIndex] = new WuColorCube(); - } - - // resets the reference minimums - cubes[0].RedMinimum = 0; - cubes[0].GreenMinimum = 0; - cubes[0].BlueMinimum = 0; - - // resets the reference maximums - cubes[0].RedMaximum = MAXSIDEINDEX; - cubes[0].GreenMaximum = MAXSIDEINDEX; - cubes[0].BlueMaximum = MAXSIDEINDEX; - - weights = new Int64[SIDESIZE, SIDESIZE, SIDESIZE]; - momentsRed = new Int64[SIDESIZE, SIDESIZE, SIDESIZE]; - momentsGreen = new Int64[SIDESIZE, SIDESIZE, SIDESIZE]; - momentsBlue = new Int64[SIDESIZE, SIDESIZE, SIDESIZE]; - moments = new Single[SIDESIZE, SIDESIZE, SIDESIZE]; - - Int32[] table = new Int32[256]; - - for (Int32 tableIndex = 0; tableIndex < 256; ++tableIndex) - { - table[tableIndex] = tableIndex * tableIndex; - } - - // Use a bitmap to store the initial match, which is just as good as an array and saves us 2x the storage - using (IFastBitmap sourceFastBitmap = FastBitmap.Create(sourceBitmap)) - { - IFastBitmapWithBlend sourceFastBitmapWithBlend = sourceFastBitmap as IFastBitmapWithBlend; - sourceFastBitmap.Lock(); - using (FastChunkyBitmap destinationFastBitmap = FastBitmap.CreateEmpty(sourceBitmap.Size, PixelFormat.Format8bppIndexed, Color.White) as FastChunkyBitmap) - { - destinationFastBitmap.Lock(); - for (int y = 0; y < sourceFastBitmap.Height; y++) - { - for (int x = 0; x < sourceFastBitmap.Width; x++) - { - Color color; - if (sourceFastBitmapWithBlend == null) - { - color = sourceFastBitmap.GetColorAt(x, y); - } - else - { - color = sourceFastBitmapWithBlend.GetBlendedColorAt(x, y); - } - // To count the colors - int index = color.ToArgb() & 0x00ffffff; - // Check if we already have this color - if (!bitArray.Get(index)) - { - // If not, add 1 to the single colors - colorCount++; - bitArray.Set(index, true); - } - - Int32 indexRed = (color.R >> 3) + 1; - Int32 indexGreen = (color.G >> 3) + 1; - Int32 indexBlue = (color.B >> 3) + 1; - - weights[indexRed, indexGreen, indexBlue]++; - momentsRed[indexRed, indexGreen, indexBlue] += color.R; - momentsGreen[indexRed, indexGreen, indexBlue] += color.G; - momentsBlue[indexRed, indexGreen, indexBlue] += color.B; - moments[indexRed, indexGreen, indexBlue] += table[color.R] + table[color.G] + table[color.B]; - - // Store the initial "match" - Int32 paletteIndex = (indexRed << 10) + (indexRed << 6) + indexRed + (indexGreen << 5) + indexGreen + indexBlue; - destinationFastBitmap.SetColorIndexAt(x, y, (byte)(paletteIndex & 0xff)); - } - } - resultBitmap = destinationFastBitmap.UnlockAndReturnBitmap(); - } - } - } - - /// - /// See for more details. - /// - public Int32 GetColorCount() - { - return colorCount; - } - - /// - /// Reindex the 24/32 BPP (A)RGB image to a 8BPP - /// - /// Bitmap - public Bitmap SimpleReindex() - { - List colors = new List(); - Dictionary lookup = new Dictionary(); - using (FastChunkyBitmap bbbDest = FastBitmap.Create(resultBitmap) as FastChunkyBitmap) - { - bbbDest.Lock(); - using (IFastBitmap bbbSrc = FastBitmap.Create(sourceBitmap)) - { - IFastBitmapWithBlend bbbSrcBlend = bbbSrc as IFastBitmapWithBlend; - - bbbSrc.Lock(); - byte index; - for (int y = 0; y < bbbSrc.Height; y++) - { - for (int x = 0; x < bbbSrc.Width; x++) - { - Color color; - if (bbbSrcBlend != null) - { - color = bbbSrcBlend.GetBlendedColorAt(x, y); - } - else - { - color = bbbSrc.GetColorAt(x, y); - } - if (lookup.ContainsKey(color)) - { - index = lookup[color]; - } - else - { - colors.Add(color); - index = (byte)(colors.Count - 1); - lookup.Add(color, index); - } - bbbDest.SetColorIndexAt(x, y, index); - } - } - } - } - - // generates palette - ColorPalette imagePalette = resultBitmap.Palette; - Color[] entries = imagePalette.Entries; - for (Int32 paletteIndex = 0; paletteIndex < 256; paletteIndex++) - { - if (paletteIndex < colorCount) - { - entries[paletteIndex] = colors[paletteIndex]; - } - else - { - entries[paletteIndex] = Color.Black; - } - } - resultBitmap.Palette = imagePalette; - - // Make sure the bitmap is not disposed, as we return it. - Bitmap tmpBitmap = resultBitmap; - resultBitmap = null; - return tmpBitmap; - } - - /// - /// Get the image - /// - public Bitmap GetQuantizedImage(int allowedColorCount) - { - if (allowedColorCount > 256) - { - throw new ArgumentOutOfRangeException("Quantizing muss be done to get less than 256 colors"); - } - if (colorCount < allowedColorCount) - { - // Simple logic to reduce to 8 bit - LOG.Info("Colors in the image are already less as whished for, using simple copy to indexed image, no quantizing needed!"); - return SimpleReindex(); - } - // preprocess the colors - CalculateMoments(); - LOG.Info("Calculated the moments..."); - Int32 next = 0; - Single[] volumeVariance = new Single[MAXCOLOR]; - - // processes the cubes - for (Int32 cubeIndex = 1; cubeIndex < allowedColorCount; ++cubeIndex) - { - // if cut is possible; make it - if (Cut(cubes[next], cubes[cubeIndex])) - { - volumeVariance[next] = cubes[next].Volume > 1 ? CalculateVariance(cubes[next]) : 0.0f; - volumeVariance[cubeIndex] = cubes[cubeIndex].Volume > 1 ? CalculateVariance(cubes[cubeIndex]) : 0.0f; - } - else - { - // the cut was not possible, revert the index - volumeVariance[next] = 0.0f; - cubeIndex--; - } - - next = 0; - Single temp = volumeVariance[0]; - - for (Int32 index = 1; index <= cubeIndex; ++index) - { - if (volumeVariance[index] > temp) - { - temp = volumeVariance[index]; - next = index; - } - } - - if (temp <= 0.0) - { - allowedColorCount = cubeIndex + 1; - break; - } - } - - Int32[] lookupRed = new Int32[MAXCOLOR]; - Int32[] lookupGreen = new Int32[MAXCOLOR]; - Int32[] lookupBlue = new Int32[MAXCOLOR]; - - tag = new byte[MAXVOLUME]; - - // precalculates lookup tables - for (int k = 0; k < allowedColorCount; ++k) - { - Mark(cubes[k], k, tag); - - long weight = Volume(cubes[k], weights); - - if (weight > 0) - { - lookupRed[k] = (int)(Volume(cubes[k], momentsRed) / weight); - lookupGreen[k] = (int)(Volume(cubes[k], momentsGreen) / weight); - lookupBlue[k] = (int)(Volume(cubes[k], momentsBlue) / weight); - } - else - { - lookupRed[k] = 0; - lookupGreen[k] = 0; - lookupBlue[k] = 0; - } - } - - reds = new Int32[allowedColorCount + 1]; - greens = new Int32[allowedColorCount + 1]; - blues = new Int32[allowedColorCount + 1]; - sums = new Int32[allowedColorCount + 1]; - - LOG.Info("Starting bitmap reconstruction..."); - - using (FastChunkyBitmap dest = FastBitmap.Create(resultBitmap) as FastChunkyBitmap) - { - using (IFastBitmap src = FastBitmap.Create(sourceBitmap)) - { - IFastBitmapWithBlend srcBlend = src as IFastBitmapWithBlend; - Dictionary lookup = new Dictionary(); - byte bestMatch; - for (int y = 0; y < src.Height; y++) - { - for (int x = 0; x < src.Width; x++) - { - Color color; - if (srcBlend != null) - { - // WithoutAlpha, this makes it possible to ignore the alpha - color = srcBlend.GetBlendedColorAt(x, y); - } - else - { - color = src.GetColorAt(x, y); - } - - // Check if we already matched the color - if (!lookup.ContainsKey(color)) - { - // If not we need to find the best match - - // First get initial match - bestMatch = dest.GetColorIndexAt(x, y); - bestMatch = tag[bestMatch]; - - Int32 bestDistance = 100000000; - for (int lookupIndex = 0; lookupIndex < allowedColorCount; lookupIndex++) - { - Int32 foundRed = lookupRed[lookupIndex]; - Int32 foundGreen = lookupGreen[lookupIndex]; - Int32 foundBlue = lookupBlue[lookupIndex]; - Int32 deltaRed = color.R - foundRed; - Int32 deltaGreen = color.G - foundGreen; - Int32 deltaBlue = color.B - foundBlue; - - Int32 distance = deltaRed * deltaRed + deltaGreen * deltaGreen + deltaBlue * deltaBlue; - - if (distance < bestDistance) - { - bestDistance = distance; - bestMatch = (byte)lookupIndex; - } - } - lookup.Add(color, bestMatch); - } - else - { - // Already matched, so we just use the lookup - bestMatch = lookup[color]; - } - - reds[bestMatch] += color.R; - greens[bestMatch] += color.G; - blues[bestMatch] += color.B; - sums[bestMatch]++; - - dest.SetColorIndexAt(x, y, bestMatch); - } - } - } - } - - // generates palette - ColorPalette imagePalette = resultBitmap.Palette; - Color[] entries = imagePalette.Entries; - for (Int32 paletteIndex = 0; paletteIndex < allowedColorCount; paletteIndex++) - { - if (sums[paletteIndex] > 0) - { - reds[paletteIndex] /= sums[paletteIndex]; - greens[paletteIndex] /= sums[paletteIndex]; - blues[paletteIndex] /= sums[paletteIndex]; - } - - entries[paletteIndex] = Color.FromArgb(255, reds[paletteIndex], greens[paletteIndex], blues[paletteIndex]); - } - resultBitmap.Palette = imagePalette; - - // Make sure the bitmap is not disposed, as we return it. - Bitmap tmpBitmap = resultBitmap; - resultBitmap = null; - return tmpBitmap; - } - - /// - /// Converts the histogram to a series of moments. - /// - private void CalculateMoments() - { - Int64[] area = new Int64[SIDESIZE]; - Int64[] areaRed = new Int64[SIDESIZE]; - Int64[] areaGreen = new Int64[SIDESIZE]; - Int64[] areaBlue = new Int64[SIDESIZE]; - Single[] area2 = new Single[SIDESIZE]; - - for (Int32 redIndex = 1; redIndex <= MAXSIDEINDEX; ++redIndex) - { - for (Int32 index = 0; index <= MAXSIDEINDEX; ++index) - { - area[index] = 0; - areaRed[index] = 0; - areaGreen[index] = 0; - areaBlue[index] = 0; - area2[index] = 0; - } - - for (Int32 greenIndex = 1; greenIndex <= MAXSIDEINDEX; ++greenIndex) - { - Int64 line = 0; - Int64 lineRed = 0; - Int64 lineGreen = 0; - Int64 lineBlue = 0; - Single line2 = 0.0f; - - for (Int32 blueIndex = 1; blueIndex <= MAXSIDEINDEX; ++blueIndex) - { - line += weights[redIndex, greenIndex, blueIndex]; - lineRed += momentsRed[redIndex, greenIndex, blueIndex]; - lineGreen += momentsGreen[redIndex, greenIndex, blueIndex]; - lineBlue += momentsBlue[redIndex, greenIndex, blueIndex]; - line2 += moments[redIndex, greenIndex, blueIndex]; - - area[blueIndex] += line; - areaRed[blueIndex] += lineRed; - areaGreen[blueIndex] += lineGreen; - areaBlue[blueIndex] += lineBlue; - area2[blueIndex] += line2; - - weights[redIndex, greenIndex, blueIndex] = weights[redIndex - 1, greenIndex, blueIndex] + area[blueIndex]; - momentsRed[redIndex, greenIndex, blueIndex] = momentsRed[redIndex - 1, greenIndex, blueIndex] + areaRed[blueIndex]; - momentsGreen[redIndex, greenIndex, blueIndex] = momentsGreen[redIndex - 1, greenIndex, blueIndex] + areaGreen[blueIndex]; - momentsBlue[redIndex, greenIndex, blueIndex] = momentsBlue[redIndex - 1, greenIndex, blueIndex] + areaBlue[blueIndex]; - moments[redIndex, greenIndex, blueIndex] = moments[redIndex - 1, greenIndex, blueIndex] + area2[blueIndex]; - } - } - } - } - - /// - /// Computes the volume of the cube in a specific moment. - /// - private static Int64 Volume(WuColorCube cube, Int64[,,] moment) - { - return moment[cube.RedMaximum, cube.GreenMaximum, cube.BlueMaximum] - - moment[cube.RedMaximum, cube.GreenMaximum, cube.BlueMinimum] - - moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMaximum] + - moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMinimum] - - moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMaximum] + - moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMinimum] + - moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMaximum] - - moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMinimum]; - } - - /// - /// Computes the volume of the cube in a specific moment. For the floating-point values. - /// - private static Single VolumeFloat(WuColorCube cube, Single[,,] moment) - { - return moment[cube.RedMaximum, cube.GreenMaximum, cube.BlueMaximum] - - moment[cube.RedMaximum, cube.GreenMaximum, cube.BlueMinimum] - - moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMaximum] + - moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMinimum] - - moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMaximum] + - moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMinimum] + - moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMaximum] - - moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMinimum]; - } - - /// - /// Splits the cube in given position, and color direction. - /// - private static Int64 Top(WuColorCube cube, Int32 direction, Int32 position, Int64[,,] moment) - { - switch (direction) - { - case RED: - return (moment[position, cube.GreenMaximum, cube.BlueMaximum] - - moment[position, cube.GreenMaximum, cube.BlueMinimum] - - moment[position, cube.GreenMinimum, cube.BlueMaximum] + - moment[position, cube.GreenMinimum, cube.BlueMinimum]); - - case GREEN: - return (moment[cube.RedMaximum, position, cube.BlueMaximum] - - moment[cube.RedMaximum, position, cube.BlueMinimum] - - moment[cube.RedMinimum, position, cube.BlueMaximum] + - moment[cube.RedMinimum, position, cube.BlueMinimum]); - - case BLUE: - return (moment[cube.RedMaximum, cube.GreenMaximum, position] - - moment[cube.RedMaximum, cube.GreenMinimum, position] - - moment[cube.RedMinimum, cube.GreenMaximum, position] + - moment[cube.RedMinimum, cube.GreenMinimum, position]); - - default: - return 0; - } - } - - /// - /// Splits the cube in a given color direction at its minimum. - /// - private static Int64 Bottom(WuColorCube cube, Int32 direction, Int64[,,] moment) - { - switch (direction) - { - case RED: - return (-moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMaximum] + - moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMinimum] + - moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMaximum] - - moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMinimum]); - - case GREEN: - return (-moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMaximum] + - moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMinimum] + - moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMaximum] - - moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMinimum]); - - case BLUE: - return (-moment[cube.RedMaximum, cube.GreenMaximum, cube.BlueMinimum] + - moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMinimum] + - moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMinimum] - - moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMinimum]); - default: - return 0; - } - } - - /// - /// Calculates statistical variance for a given cube. - /// - private Single CalculateVariance(WuColorCube cube) - { - Single volumeRed = Volume(cube, momentsRed); - Single volumeGreen = Volume(cube, momentsGreen); - Single volumeBlue = Volume(cube, momentsBlue); - Single volumeMoment = VolumeFloat(cube, moments); - Single volumeWeight = Volume(cube, weights); - - Single distance = volumeRed * volumeRed + volumeGreen * volumeGreen + volumeBlue * volumeBlue; - - return volumeMoment - (distance / volumeWeight); - } - - /// - /// Finds the optimal (maximal) position for the cut. - /// - private Single Maximize(WuColorCube cube, Int32 direction, Int32 first, Int32 last, Int32[] cut, Int64 wholeRed, Int64 wholeGreen, Int64 wholeBlue, Int64 wholeWeight) - { - Int64 bottomRed = Bottom(cube, direction, momentsRed); - Int64 bottomGreen = Bottom(cube, direction, momentsGreen); - Int64 bottomBlue = Bottom(cube, direction, momentsBlue); - Int64 bottomWeight = Bottom(cube, direction, weights); - - Single result = 0.0f; - cut[0] = -1; - - for (Int32 position = first; position < last; ++position) - { - // determines the cube cut at a certain position - Int64 halfRed = bottomRed + Top(cube, direction, position, momentsRed); - Int64 halfGreen = bottomGreen + Top(cube, direction, position, momentsGreen); - Int64 halfBlue = bottomBlue + Top(cube, direction, position, momentsBlue); - Int64 halfWeight = bottomWeight + Top(cube, direction, position, weights); - - // the cube cannot be cut at bottom (this would lead to empty cube) - if (halfWeight != 0) - { - Single halfDistance = (Single)halfRed * halfRed + (Single)halfGreen * halfGreen + (Single)halfBlue * halfBlue; - Single temp = halfDistance / halfWeight; - - halfRed = wholeRed - halfRed; - halfGreen = wholeGreen - halfGreen; - halfBlue = wholeBlue - halfBlue; - halfWeight = wholeWeight - halfWeight; - - if (halfWeight != 0) - { - halfDistance = (Single)halfRed * halfRed + (Single)halfGreen * halfGreen + (Single)halfBlue * halfBlue; - temp += halfDistance / halfWeight; - - if (temp > result) - { - result = temp; - cut[0] = position; - } - } - } - } - - return result; - } - - /// - /// Cuts a cube with another one. - /// - private Boolean Cut(WuColorCube first, WuColorCube second) - { - Int32 direction; - - Int32[] cutRed = { 0 }; - Int32[] cutGreen = { 0 }; - Int32[] cutBlue = { 0 }; - - Int64 wholeRed = Volume(first, momentsRed); - Int64 wholeGreen = Volume(first, momentsGreen); - Int64 wholeBlue = Volume(first, momentsBlue); - Int64 wholeWeight = Volume(first, weights); - - Single maxRed = Maximize(first, RED, first.RedMinimum + 1, first.RedMaximum, cutRed, wholeRed, wholeGreen, wholeBlue, wholeWeight); - Single maxGreen = Maximize(first, GREEN, first.GreenMinimum + 1, first.GreenMaximum, cutGreen, wholeRed, wholeGreen, wholeBlue, wholeWeight); - Single maxBlue = Maximize(first, BLUE, first.BlueMinimum + 1, first.BlueMaximum, cutBlue, wholeRed, wholeGreen, wholeBlue, wholeWeight); - - if ((maxRed >= maxGreen) && (maxRed >= maxBlue)) - { - direction = RED; - - // cannot split empty cube - if (cutRed[0] < 0) return false; - } - else - { - if ((maxGreen >= maxRed) && (maxGreen >= maxBlue)) - { - direction = GREEN; - } - else - { - direction = BLUE; - } - } - - second.RedMaximum = first.RedMaximum; - second.GreenMaximum = first.GreenMaximum; - second.BlueMaximum = first.BlueMaximum; - - // cuts in a certain direction - switch (direction) - { - case RED: - second.RedMinimum = first.RedMaximum = cutRed[0]; - second.GreenMinimum = first.GreenMinimum; - second.BlueMinimum = first.BlueMinimum; - break; - - case GREEN: - second.GreenMinimum = first.GreenMaximum = cutGreen[0]; - second.RedMinimum = first.RedMinimum; - second.BlueMinimum = first.BlueMinimum; - break; - - case BLUE: - second.BlueMinimum = first.BlueMaximum = cutBlue[0]; - second.RedMinimum = first.RedMinimum; - second.GreenMinimum = first.GreenMinimum; - break; - } - - // determines the volumes after cut - first.Volume = (first.RedMaximum - first.RedMinimum) * (first.GreenMaximum - first.GreenMinimum) * (first.BlueMaximum - first.BlueMinimum); - second.Volume = (second.RedMaximum - second.RedMinimum) * (second.GreenMaximum - second.GreenMinimum) * (second.BlueMaximum - second.BlueMinimum); - - // the cut was successfull - return true; - } - - /// - /// Marks all the tags with a given label. - /// - private void Mark(WuColorCube cube, Int32 label, byte[] tag) - { - for (Int32 redIndex = cube.RedMinimum + 1; redIndex <= cube.RedMaximum; ++redIndex) - { - for (Int32 greenIndex = cube.GreenMinimum + 1; greenIndex <= cube.GreenMaximum; ++greenIndex) - { - for (Int32 blueIndex = cube.BlueMinimum + 1; blueIndex <= cube.BlueMaximum; ++blueIndex) - { - tag[(redIndex << 10) + (redIndex << 6) + redIndex + (greenIndex << 5) + greenIndex + blueIndex] = (byte)label; - } - } - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Core/StringExtensions.cs b/Greenshot.ImageEditor/Core/StringExtensions.cs deleted file mode 100644 index d1eb031a3..000000000 --- a/Greenshot.ImageEditor/Core/StringExtensions.cs +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Security.Cryptography; -using System.Text; -using System.Text.RegularExpressions; - -namespace GreenshotPlugin.Core -{ - public static class StringExtensions - { - private const string RGBIV = "dlgjowejgogkklwj"; - private const string KEY = "lsjvkwhvwujkagfauguwcsjgu2wueuff"; - - /// - /// Format a string with the specified object - /// - /// String with formatting, like {name} - /// Object used for the formatting - /// Formatted string - public static string FormatWith(this string format, object source) - { - return FormatWith(format, null, source); - } - - /// - /// Format the string "format" with the source - /// - /// - /// - /// object with properties, if a property has the type IDictionary string,string it can used these parameters too - /// Formatted string - public static string FormatWith(this string format, IFormatProvider provider, object source) - { - if (format == null) - { - throw new ArgumentNullException("format"); - } - - IDictionary properties = new Dictionary(); - foreach (var propertyInfo in source.GetType().GetProperties()) - { - if (propertyInfo.CanRead && propertyInfo.CanWrite) - { - object value = propertyInfo.GetValue(source, null); - if (propertyInfo.PropertyType != typeof(IDictionary)) - { - properties.Add(propertyInfo.Name, value); - } - else - { - IDictionary dictionary = (IDictionary)value; - foreach (var propertyKey in dictionary.Keys) - { - properties.Add(propertyKey, dictionary[propertyKey]); - } - } - } - } - - Regex r = new Regex(@"(?\{)+(?[\w\.\[\]]+)(?:[^}]+)?(?\})+", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase); - - List values = new List(); - string rewrittenFormat = r.Replace(format, delegate (Match m) - { - Group startGroup = m.Groups["start"]; - Group propertyGroup = m.Groups["property"]; - Group formatGroup = m.Groups["format"]; - Group endGroup = m.Groups["end"]; - - object value; - if (properties.TryGetValue(propertyGroup.Value, out value)) - { - values.Add(value); - } - else - { - values.Add(source); - } - return new string('{', startGroup.Captures.Count) + (values.Count - 1) + formatGroup.Value + new string('}', endGroup.Captures.Count); - }); - - return string.Format(provider, rewrittenFormat, values.ToArray()); - } - - /// - /// A simply rijndael aes encryption, can be used to store passwords - /// - /// the string to call upon - /// an encryped string in base64 form - public static string Encrypt(this string ClearText) - { - string returnValue = ClearText; - try - { - byte[] clearTextBytes = Encoding.ASCII.GetBytes(ClearText); - SymmetricAlgorithm rijn = SymmetricAlgorithm.Create(); - - using (MemoryStream ms = new MemoryStream()) - { - byte[] rgbIV = Encoding.ASCII.GetBytes(RGBIV); - byte[] key = Encoding.ASCII.GetBytes(KEY); - using (CryptoStream cs = new CryptoStream(ms, rijn.CreateEncryptor(key, rgbIV), CryptoStreamMode.Write)) - { - cs.Write(clearTextBytes, 0, clearTextBytes.Length); - cs.FlushFinalBlock(); - - returnValue = Convert.ToBase64String(ms.ToArray()); - } - } - } - catch (Exception ex) - { - LOG.ErrorFormat("Error encrypting, error: ", ex.Message); - } - return returnValue; - } - - /// - /// A simply rijndael aes decryption, can be used to store passwords - /// - /// a base64 encoded rijndael encrypted string - /// Decrypeted text - public static string Decrypt(this string EncryptedText) - { - string returnValue = EncryptedText; - try - { - byte[] encryptedTextBytes = Convert.FromBase64String(EncryptedText); - using (MemoryStream ms = new MemoryStream()) - { - SymmetricAlgorithm rijn = SymmetricAlgorithm.Create(); - - byte[] rgbIV = Encoding.ASCII.GetBytes(RGBIV); - byte[] key = Encoding.ASCII.GetBytes(KEY); - - using (CryptoStream cs = new CryptoStream(ms, rijn.CreateDecryptor(key, rgbIV), CryptoStreamMode.Write)) - { - cs.Write(encryptedTextBytes, 0, encryptedTextBytes.Length); - cs.FlushFinalBlock(); - returnValue = Encoding.ASCII.GetString(ms.ToArray()); - } - } - } - catch (Exception ex) - { - LOG.ErrorFormat("Error decrypting {0}, error: ", EncryptedText, ex.Message); - } - - return returnValue; - } - - /// - /// Read "streamextensions" :) - /// - /// Stream - /// Stream - public static void CopyTo(this Stream input, Stream output) - { - byte[] buffer = new byte[16 * 1024]; // Fairly arbitrary size - int bytesRead; - - while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0) - { - output.Write(buffer, 0, bytesRead); - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Core/WindowCapture.cs b/Greenshot.ImageEditor/Core/WindowCapture.cs deleted file mode 100644 index 384936323..000000000 --- a/Greenshot.ImageEditor/Core/WindowCapture.cs +++ /dev/null @@ -1,901 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.IniFile; -using Greenshot.Plugin; -using GreenshotPlugin.UnmanagedHelpers; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Drawing; -using System.Drawing.Imaging; -using System.Runtime.InteropServices; -using System.Windows.Forms; - -namespace GreenshotPlugin.Core -{ - /// - /// This Class is used to pass details about the capture around. - /// The time the Capture was taken and the Title of the window (or a region of) that is captured - /// - public class CaptureDetails : ICaptureDetails - { - public string Title - { - get; - set; - } - - public string Filename - { - get; - set; - } - - public DateTime DateTime - { - get; - set; - } - - public float DpiX - { - get; - set; - } - - public float DpiY - { - get; - set; - } - - private readonly Dictionary metaData = new Dictionary(); - public Dictionary MetaData - { - get { return metaData; } - } - - public void AddMetaData(string key, string value) - { - if (metaData.ContainsKey(key)) - { - metaData[key] = value; - } - else - { - metaData.Add(key, value); - } - } - - public CaptureMode CaptureMode - { - get; - set; - } - - private List _captureDestinations = new List(); - public List CaptureDestinations - { - get { return _captureDestinations; } - set { _captureDestinations = value; } - } - - public void ClearDestinations() - { - _captureDestinations.Clear(); - } - - public void RemoveDestination(IDestination destination) - { - if (_captureDestinations.Contains(destination)) - { - _captureDestinations.Remove(destination); - } - } - - public void AddDestination(IDestination captureDestination) - { - if (!_captureDestinations.Contains(captureDestination)) - { - _captureDestinations.Add(captureDestination); - } - } - - public bool HasDestination(string designation) - { - foreach (IDestination destination in _captureDestinations) - { - if (designation.Equals(destination.Designation)) - { - return true; - } - } - return false; - } - - public CaptureDetails() - { - DateTime = DateTime.Now; - } - } - - /// - /// This class is used to pass an instance of the "Capture" around - /// Having the Bitmap, eventually the Windows Title and cursor all together. - /// - public class Capture : ICapture - { - private List _elements = new List(); - - private Rectangle _screenBounds = Rectangle.Empty; - /// - /// Get/Set the Screenbounds - /// - public Rectangle ScreenBounds - { - get - { - if (_screenBounds == Rectangle.Empty) - { - _screenBounds = WindowCapture.GetScreenBounds(); - } - return _screenBounds; - } - set - { - _screenBounds = value; - } - } - - private Image _image; - /// - /// Get/Set the Image - /// - public Image Image - { - get - { - return _image; - } - set - { - if (_image != null) - { - _image.Dispose(); - } - _image = value; - if (value != null) - { - if (value.PixelFormat.Equals(PixelFormat.Format8bppIndexed) || value.PixelFormat.Equals(PixelFormat.Format1bppIndexed) || value.PixelFormat.Equals(PixelFormat.Format4bppIndexed)) - { - LOG.Debug("Converting Bitmap to PixelFormat.Format32bppArgb as we don't support: " + value.PixelFormat); - try - { - // Default Bitmap PixelFormat is Format32bppArgb - _image = new Bitmap(value); - } - finally - { - // Always dispose, even when a exception occured - value.Dispose(); - } - } - LOG.DebugFormat("Image is set with the following specifications: {0} - {1}", _image.Size, _image.PixelFormat); - } - else - { - LOG.Debug("Image is removed."); - } - } - } - - public void NullImage() - { - _image = null; - } - - private Icon _cursor; - /// - /// Get/Set the image for the Cursor - /// - public Icon Cursor - { - get - { - return _cursor; - } - set - { - if (_cursor != null) - { - _cursor.Dispose(); - } - _cursor = (Icon)value.Clone(); - } - } - - private bool _cursorVisible; - /// - /// Set if the cursor is visible - /// - public bool CursorVisible - { - get { return _cursorVisible; } - set { _cursorVisible = value; } - } - - private Point _cursorLocation = Point.Empty; - /// - /// Get/Set the CursorLocation - /// - public Point CursorLocation - { - get { return _cursorLocation; } - set { _cursorLocation = value; } - } - - private Point _location = Point.Empty; - /// - /// Get/set the Location - /// - public Point Location - { - get { return _location; } - set { _location = value; } - } - - private CaptureDetails _captureDetails; - /// - /// Get/set the CaptureDetails - /// - public ICaptureDetails CaptureDetails - { - get { return _captureDetails; } - set { _captureDetails = (CaptureDetails)value; } - } - - /// - /// Default Constructor - /// - public Capture() - { - _screenBounds = WindowCapture.GetScreenBounds(); - _captureDetails = new CaptureDetails(); - } - - /// - /// Constructor with Image - /// Note: the supplied bitmap can be disposed immediately or when constructor is called. - /// - /// Image - public Capture(Image newImage) : this() - { - Image = newImage; - } - - /// - /// Destructor - /// - ~Capture() - { - Dispose(false); - } - - /// - /// The public accessible Dispose - /// Will call the GarbageCollector to SuppressFinalize, preventing being cleaned twice - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// This Dispose is called from the Dispose and the Destructor. - /// When disposing==true all non-managed resources should be freed too! - /// - /// - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - if (_image != null) - { - _image.Dispose(); - } - if (_cursor != null) - { - _cursor.Dispose(); - } - } - _image = null; - _cursor = null; - } - - /// - /// Crops the capture to the specified rectangle (with Bitmap coordinates!) - /// - /// Rectangle with bitmap coordinates - public bool Crop(Rectangle cropRectangle) - { - LOG.Debug("Cropping to: " + cropRectangle.ToString()); - if (ImageHelper.Crop(ref _image, ref cropRectangle)) - { - _location = cropRectangle.Location; - // Change mouse location according to the cropRegtangle (including screenbounds) offset - MoveMouseLocation(-cropRectangle.Location.X, -cropRectangle.Location.Y); - // Move all the elements - // Enable when the elements are usable again. - // MoveElements(-cropRectangle.Location.X, -cropRectangle.Location.Y); - - // Remove invisible elements - List newElements = new List(); - foreach (ICaptureElement captureElement in _elements) - { - if (captureElement.Bounds.IntersectsWith(cropRectangle)) - { - newElements.Add(captureElement); - } - } - _elements = newElements; - - return true; - } - return false; - } - - /// - /// Apply a translate to the mouse location. - /// e.g. needed for crop - /// - /// x coordinates to move the mouse - /// y coordinates to move the mouse - public void MoveMouseLocation(int x, int y) - { - _cursorLocation.Offset(x, y); - } - - // Enable when the elements are usable again. - ///// - ///// Apply a translate to the elements - ///// e.g. needed for crop - ///// - ///// x coordinates to move the elements - ///// y coordinates to move the elements - //public void MoveElements(int x, int y) { - // MoveElements(elements, x, y); - //} - - //private void MoveElements(List listOfElements, int x, int y) { - // foreach(ICaptureElement childElement in listOfElements) { - // Rectangle bounds = childElement.Bounds; - // bounds.Offset(x, y); - // childElement.Bounds = bounds; - // MoveElements(childElement.Children, x, y); - // } - //} - - ///// - ///// Add a new element to the capture - ///// - ///// CaptureElement - //public void AddElement(ICaptureElement element) { - // int match = elements.IndexOf(element); - // if (match >= 0) { - // if (elements[match].Children.Count < element.Children.Count) { - // elements.RemoveAt(match); - // elements.Add(element); - // } - // } else { - // elements.Add(element); - // } - //} - - ///// - ///// Returns a list of rectangles which represent object that are on the capture - ///// - //public List Elements { - // get { - // return elements; - // } - // set { - // elements = value; - // } - //} - } - - /// - /// A class representing an element in the capture - /// - public class CaptureElement : ICaptureElement - { - public CaptureElement(Rectangle bounds) - { - Bounds = bounds; - } - - public CaptureElement(string name) - { - Name = name; - } - - public CaptureElement(string name, Rectangle bounds) - { - Name = name; - Bounds = bounds; - } - - private List _children = new List(); - public List Children - { - get - { - return _children; - } - set - { - _children = value; - } - } - - public string Name - { - get; - set; - } - public Rectangle Bounds - { - get; - set; - } - - // CaptureElements are regarded equal if their bounds are equal. this should be sufficient. - public override bool Equals(object obj) - { - bool ret = false; - if (obj != null && GetType() == obj.GetType()) - { - CaptureElement other = obj as CaptureElement; - if (other != null && Bounds.Equals(other.Bounds)) - { - ret = true; - } - } - return ret; - } - - public override int GetHashCode() - { - return Bounds.GetHashCode(); - } - } - - /// - /// The Window Capture code - /// - public class WindowCapture - { - private static readonly CoreConfiguration Configuration = IniConfig.GetIniSection(); - - /// - /// Used to cleanup the unmanged resource in the iconInfo for the CaptureCursor method - /// - /// - /// - [DllImport("gdi32", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool DeleteObject(IntPtr hObject); - - private WindowCapture() - { - } - - /// - /// Get the bounds of all screens combined. - /// - /// A Rectangle of the bounds of the entire display area. - public static Rectangle GetScreenBounds() - { - int left = 0, top = 0, bottom = 0, right = 0; - foreach (Screen screen in Screen.AllScreens) - { - left = Math.Min(left, screen.Bounds.X); - top = Math.Min(top, screen.Bounds.Y); - int screenAbsRight = screen.Bounds.X + screen.Bounds.Width; - int screenAbsBottom = screen.Bounds.Y + screen.Bounds.Height; - right = Math.Max(right, screenAbsRight); - bottom = Math.Max(bottom, screenAbsBottom); - } - return new Rectangle(left, top, (right + Math.Abs(left)), (bottom + Math.Abs(top))); - } - - /// - /// Retrieves the cursor location safely, accounting for DPI settings in Vista/Windows 7. This implementation - /// can conveniently be used when the cursor location is needed to deal with a fullscreen bitmap. - /// - /// - /// Point with cursor location, relative to the top left corner of the monitor setup (which itself might actually not be on any screen) - /// - public static Point GetCursorLocationRelativeToScreenBounds() - { - return GetLocationRelativeToScreenBounds(User32.GetCursorLocation()); - } - - /// - /// Converts locationRelativeToScreenOrigin to be relative to top left corner of all screen bounds, which might - /// be different in multiscreen setups. This implementation - /// can conveniently be used when the cursor location is needed to deal with a fullscreen bitmap. - /// - /// - /// - public static Point GetLocationRelativeToScreenBounds(Point locationRelativeToScreenOrigin) - { - Point ret = locationRelativeToScreenOrigin; - Rectangle bounds = GetScreenBounds(); - ret.Offset(-bounds.X, -bounds.Y); - return ret; - } - - /// - /// This method will capture the current Cursor by using User32 Code - /// - /// A Capture Object with the Mouse Cursor information in it. - public static ICapture CaptureCursor(ICapture capture) - { - LOG.Debug("Capturing the mouse cursor."); - if (capture == null) - { - capture = new Capture(); - } - int x, y; - CursorInfo cursorInfo = new CursorInfo(); - IconInfo iconInfo; - cursorInfo.cbSize = Marshal.SizeOf(cursorInfo); - if (User32.GetCursorInfo(out cursorInfo)) - { - if (cursorInfo.flags == User32.CURSOR_SHOWING) - { - using (SafeIconHandle safeIcon = User32.CopyIcon(cursorInfo.hCursor)) - { - if (User32.GetIconInfo(safeIcon, out iconInfo)) - { - Point cursorLocation = User32.GetCursorLocation(); - // Allign cursor location to Bitmap coordinates (instead of Screen coordinates) - x = cursorLocation.X - iconInfo.xHotspot - capture.ScreenBounds.X; - y = cursorLocation.Y - iconInfo.yHotspot - capture.ScreenBounds.Y; - // Set the location - capture.CursorLocation = new Point(x, y); - - using (Icon icon = Icon.FromHandle(safeIcon.DangerousGetHandle())) - { - capture.Cursor = icon; - } - - if (iconInfo.hbmMask != IntPtr.Zero) - { - DeleteObject(iconInfo.hbmMask); - } - if (iconInfo.hbmColor != IntPtr.Zero) - { - DeleteObject(iconInfo.hbmColor); - } - } - } - } - } - return capture; - } - - /// - /// This method will call the CaptureRectangle with the screenbounds, therefor Capturing the whole screen. - /// - /// A Capture Object with the Screen as an Image - public static ICapture CaptureScreen(ICapture capture) - { - if (capture == null) - { - capture = new Capture(); - } - return CaptureRectangle(capture, capture.ScreenBounds); - } - - /// - /// Helper method to create an exception that might explain what is wrong while capturing - /// - /// string with current method - /// Rectangle of what we want to capture - /// - private static Exception CreateCaptureException(string method, Rectangle captureBounds) - { - Exception exceptionToThrow = User32.CreateWin32Exception(method); - if (!captureBounds.IsEmpty) - { - exceptionToThrow.Data.Add("Height", captureBounds.Height); - exceptionToThrow.Data.Add("Width", captureBounds.Width); - } - return exceptionToThrow; - } - - /// - /// Helper method to check if it is allowed to capture the process using DWM - /// - /// Process owning the window - /// true if it's allowed - public static bool IsDwmAllowed(Process process) - { - if (process != null) - { - if (Configuration.NoDWMCaptureForProduct != null && Configuration.NoDWMCaptureForProduct.Count > 0) - { - try - { - string productName = process.MainModule.FileVersionInfo.ProductName; - if (productName != null && Configuration.NoDWMCaptureForProduct.Contains(productName.ToLower())) - { - return false; - } - } - catch (Exception ex) - { - LOG.Warn(ex.Message); - } - } - } - return true; - } - - /// - /// Helper method to check if it is allowed to capture the process using GDI - /// - /// Process owning the window - /// true if it's allowed - public static bool IsGdiAllowed(Process process) - { - if (process != null) - { - if (Configuration.NoGDICaptureForProduct != null && Configuration.NoGDICaptureForProduct.Count > 0) - { - try - { - string productName = process.MainModule.FileVersionInfo.ProductName; - if (productName != null && Configuration.NoGDICaptureForProduct.Contains(productName.ToLower())) - { - return false; - } - } - catch (Exception ex) - { - LOG.Warn(ex.Message); - } - } - } - return true; - } - - /// - /// This method will use User32 code to capture the specified captureBounds from the screen - /// - /// ICapture where the captured Bitmap will be stored - /// Rectangle with the bounds to capture - /// A Capture Object with a part of the Screen as an Image - public static ICapture CaptureRectangle(ICapture capture, Rectangle captureBounds) - { - if (capture == null) - { - capture = new Capture(); - } - Image capturedImage = null; - // If the CaptureHandler has a handle use this, otherwise use the CaptureRectangle here - if (CaptureHandler.CaptureScreenRectangle != null) - { - try - { - capturedImage = CaptureHandler.CaptureScreenRectangle(captureBounds); - } - catch - { - } - } - // If no capture, use the normal screen capture - if (capturedImage == null) - { - capturedImage = CaptureRectangle(captureBounds); - } - capture.Image = capturedImage; - capture.Location = captureBounds.Location; - return capture.Image == null ? null : capture; - } - - /// - /// This method will use User32 code to capture the specified captureBounds from the screen - /// - /// ICapture where the captured Bitmap will be stored - /// Rectangle with the bounds to capture - /// A Capture Object with a part of the Screen as an Image - public static ICapture CaptureRectangleFromDesktopScreen(ICapture capture, Rectangle captureBounds) - { - if (capture == null) - { - capture = new Capture(); - } - capture.Image = CaptureRectangle(captureBounds); - capture.Location = captureBounds.Location; - return capture.Image == null ? null : capture; - } - - /// - /// This method will use User32 code to capture the specified captureBounds from the screen - /// - /// Rectangle with the bounds to capture - /// Bitmap which is captured from the screen at the location specified by the captureBounds - public static Bitmap CaptureRectangle(Rectangle captureBounds) - { - Bitmap returnBitmap = null; - if (captureBounds.Height <= 0 || captureBounds.Width <= 0) - { - LOG.Warn("Nothing to capture, ignoring!"); - return null; - } - LOG.Debug("CaptureRectangle Called!"); - - // .NET GDI+ Solution, according to some post this has a GDI+ leak... - // See http://connect.microsoft.com/VisualStudio/feedback/details/344752/gdi-object-leak-when-calling-graphics-copyfromscreen - // Bitmap capturedBitmap = new Bitmap(captureBounds.Width, captureBounds.Height); - // using (Graphics graphics = Graphics.FromImage(capturedBitmap)) { - // graphics.CopyFromScreen(captureBounds.Location, Point.Empty, captureBounds.Size, CopyPixelOperation.CaptureBlt); - // } - // capture.Image = capturedBitmap; - // capture.Location = captureBounds.Location; - - using (SafeWindowDCHandle desktopDCHandle = SafeWindowDCHandle.FromDesktop()) - { - if (desktopDCHandle.IsInvalid) - { - // Get Exception before the error is lost - Exception exceptionToThrow = CreateCaptureException("desktopDCHandle", captureBounds); - // throw exception - throw exceptionToThrow; - } - - // create a device context we can copy to - using (SafeCompatibleDCHandle safeCompatibleDCHandle = GDI32.CreateCompatibleDC(desktopDCHandle)) - { - // Check if the device context is there, if not throw an error with as much info as possible! - if (safeCompatibleDCHandle.IsInvalid) - { - // Get Exception before the error is lost - Exception exceptionToThrow = CreateCaptureException("CreateCompatibleDC", captureBounds); - // throw exception - throw exceptionToThrow; - } - // Create BITMAPINFOHEADER for CreateDIBSection - BITMAPINFOHEADER bmi = new BITMAPINFOHEADER(captureBounds.Width, captureBounds.Height, 24); - - // Make sure the last error is set to 0 - Win32.SetLastError(0); - - // create a bitmap we can copy it to, using GetDeviceCaps to get the width/height - IntPtr bits0; // not used for our purposes. It returns a pointer to the raw bits that make up the bitmap. - using (SafeDibSectionHandle safeDibSectionHandle = GDI32.CreateDIBSection(desktopDCHandle, ref bmi, BITMAPINFOHEADER.DIB_RGB_COLORS, out bits0, IntPtr.Zero, 0)) - { - if (safeDibSectionHandle.IsInvalid) - { - // Get Exception before the error is lost - Exception exceptionToThrow = CreateCaptureException("CreateDIBSection", captureBounds); - exceptionToThrow.Data.Add("hdcDest", safeCompatibleDCHandle.DangerousGetHandle().ToInt32()); - exceptionToThrow.Data.Add("hdcSrc", desktopDCHandle.DangerousGetHandle().ToInt32()); - - // Throw so people can report the problem - throw exceptionToThrow; - } - // select the bitmap object and store the old handle - using (safeCompatibleDCHandle.SelectObject(safeDibSectionHandle)) - { - // bitblt over (make copy) - GDI32.BitBlt(safeCompatibleDCHandle, 0, 0, captureBounds.Width, captureBounds.Height, desktopDCHandle, captureBounds.X, captureBounds.Y, CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt); - } - - // get a .NET image object for it - // A suggestion for the "A generic error occurred in GDI+." E_FAIL/0×80004005 error is to re-try... - bool success = false; - ExternalException exception = null; - for (int i = 0; i < 3; i++) - { - try - { - // Collect all screens inside this capture - List screensInsideCapture = new List(); - foreach (Screen screen in Screen.AllScreens) - { - if (screen.Bounds.IntersectsWith(captureBounds)) - { - screensInsideCapture.Add(screen); - } - } - // Check all all screens are of an equal size - bool offscreenContent; - using (Region captureRegion = new Region(captureBounds)) - { - // Exclude every visible part - foreach (Screen screen in screensInsideCapture) - { - captureRegion.Exclude(screen.Bounds); - } - // If the region is not empty, we have "offscreenContent" - using (Graphics screenGraphics = Graphics.FromHwnd(User32.GetDesktopWindow())) - { - offscreenContent = !captureRegion.IsEmpty(screenGraphics); - } - } - // Check if we need to have a transparent background, needed for offscreen content - if (offscreenContent) - { - using (Bitmap tmpBitmap = Image.FromHbitmap(safeDibSectionHandle.DangerousGetHandle())) - { - // Create a new bitmap which has a transparent background - returnBitmap = ImageHelper.CreateEmpty(tmpBitmap.Width, tmpBitmap.Height, PixelFormat.Format32bppArgb, Color.Transparent, tmpBitmap.HorizontalResolution, tmpBitmap.VerticalResolution); - // Content will be copied here - using (Graphics graphics = Graphics.FromImage(returnBitmap)) - { - // For all screens copy the content to the new bitmap - foreach (Screen screen in Screen.AllScreens) - { - Rectangle screenBounds = screen.Bounds; - // Make sure the bounds are offsetted to the capture bounds - screenBounds.Offset(-captureBounds.X, -captureBounds.Y); - graphics.DrawImage(tmpBitmap, screenBounds, screenBounds.X, screenBounds.Y, screenBounds.Width, screenBounds.Height, GraphicsUnit.Pixel); - } - } - } - } - else - { - // All screens, which are inside the capture, are of equal size - // assign image to Capture, the image will be disposed there.. - returnBitmap = Image.FromHbitmap(safeDibSectionHandle.DangerousGetHandle()); - } - // We got through the capture without exception - success = true; - break; - } - catch (ExternalException ee) - { - LOG.Warn("Problem getting bitmap at try " + i + " : ", ee); - exception = ee; - } - } - if (!success) - { - LOG.Error("Still couldn't create Bitmap!"); - if (exception != null) - { - throw exception; - } - } - } - } - } - return returnBitmap; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Core/WindowsHelper.cs b/Greenshot.ImageEditor/Core/WindowsHelper.cs deleted file mode 100644 index 7f1f6bd9a..000000000 --- a/Greenshot.ImageEditor/Core/WindowsHelper.cs +++ /dev/null @@ -1,2111 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.IniFile; -using Greenshot.Interop; -using Greenshot.Plugin; -using GreenshotPlugin.UnmanagedHelpers; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Drawing; -using System.Drawing.Imaging; -using System.Runtime.InteropServices; -using System.Text; -using System.Text.RegularExpressions; -using System.Windows.Forms; - -namespace GreenshotPlugin.Core -{ - #region EnumWindows - - /// - /// EnumWindows wrapper for .NET - /// - public class WindowsEnumerator - { - #region Member Variables - - private List items; - - #endregion Member Variables - - /// - /// Returns the collection of windows returned by - /// GetWindows - /// - public List Items - { - get - { - return items; - } - } - - /// - /// Gets all top level windows on the system. - /// - public WindowsEnumerator GetWindows() - { - GetWindows(IntPtr.Zero, null); - return this; - } - - /// - /// Gets all child windows of the specified window - /// - /// Window Handle to get children for - public WindowsEnumerator GetWindows(WindowDetails parent) - { - if (parent != null) - { - GetWindows(parent.Handle, null); - } - else - { - GetWindows(IntPtr.Zero, null); - } - return this; - } - - /// - /// Gets all child windows of the specified window - /// - /// Window Handle to get children for - /// Window Classname to copy, use null to copy all - public WindowsEnumerator GetWindows(IntPtr hWndParent, string classname) - { - items = new List(); - List windows = new List(); - User32.EnumChildWindows(hWndParent, WindowEnum, IntPtr.Zero); - - bool hasParent = !IntPtr.Zero.Equals(hWndParent); - string parentText = null; - if (hasParent) - { - StringBuilder title = new StringBuilder(260, 260); - User32.GetWindowText(hWndParent, title, title.Capacity); - parentText = title.ToString(); - } - - foreach (WindowDetails window in items) - { - if (hasParent) - { - window.Text = parentText; - window.ParentHandle = hWndParent; - } - if (classname == null || window.ClassName.Equals(classname)) - { - windows.Add(window); - } - } - items = windows; - return this; - } - - #region EnumWindows callback - - /// - /// The enum Windows callback. - /// - /// Window Handle - /// Application defined value - /// 1 to continue enumeration, 0 to stop - private int WindowEnum(IntPtr hWnd, int lParam) - { - if (OnWindowEnum(hWnd)) - { - return 1; - } - else - { - return 0; - } - } - - #endregion EnumWindows callback - - /// - /// Called whenever a new window is about to be added - /// by the Window enumeration called from GetWindows. - /// If overriding this function, return true to continue - /// enumeration or false to stop. If you do not call - /// the base implementation the Items collection will - /// be empty. - /// - /// Window handle to add - /// True to continue enumeration, False to stop - protected virtual bool OnWindowEnum(IntPtr hWnd) - { - if (!WindowDetails.IsIgnoreHandle(hWnd)) - { - items.Add(new WindowDetails(hWnd)); - } - return true; - } - - #region Constructor, Dispose - - public WindowsEnumerator() - { - // nothing to do - } - - #endregion Constructor, Dispose - } - - #endregion EnumWindows - - /// - - #region WindowDetails - - /// - /// Code for handling with "windows" - /// Main code is taken from vbAccelerator, location: - /// http://www.vbaccelerator.com/home/NET/Code/Libraries/Windows/Enumerating_Windows/article.asp - /// but a LOT of changes/enhancements were made to adapt it for Greenshot. - /// - /// Provides details about a Window returned by the - /// enumeration - /// - public class WindowDetails : IEquatable - { - private const string METRO_WINDOWS_CLASS = "Windows.UI.Core.CoreWindow"; // Windows 10 uses ApplicationFrameWindow - private const string METRO_APPLAUNCHER_CLASS = "ImmersiveLauncher"; - private const string METRO_GUTTER_CLASS = "ImmersiveGutter"; - - private static readonly CoreConfiguration Conf = IniConfig.GetIniSection(); - private static readonly List IgnoreHandles = new List(); - private static readonly List ExcludeProcessesFromFreeze = new List(); - private static readonly IAppVisibility appVisibility; - - static WindowDetails() - { - try - { - // Only try to instantiate when Windows 8 or later. - if (Environment.OSVersion.Version.Major >= 6 && Environment.OSVersion.Version.Minor >= 2) - { - appVisibility = COMWrapper.CreateInstance(); - } - } - catch { } - } - - public static void AddProcessToExcludeFromFreeze(string processname) - { - if (!ExcludeProcessesFromFreeze.Contains(processname)) - { - ExcludeProcessesFromFreeze.Add(processname); - } - } - - internal static bool IsIgnoreHandle(IntPtr handle) - { - return IgnoreHandles.Contains(handle); - } - - private List _childWindows; - private IntPtr _parentHandle = IntPtr.Zero; - private WindowDetails _parent; - private bool _frozen; - - /// - /// This checks if the window is a Windows 8 App - /// For Windows 10 most normal code works, as it's hosted inside "ApplicationFrameWindow" - /// - public bool IsApp - { - get - { - return METRO_WINDOWS_CLASS.Equals(ClassName); - } - } - - public bool IsGutter - { - get - { - return METRO_GUTTER_CLASS.Equals(ClassName); - } - } - - public bool IsAppLauncher - { - get - { - return METRO_APPLAUNCHER_CLASS.Equals(ClassName); - } - } - - /// - /// Check if this window is the window of a metro app - /// - public bool IsMetroApp - { - get - { - return IsAppLauncher || IsApp; - } - } - - /// - /// The window handle. - /// - private IntPtr _hWnd = IntPtr.Zero; - - /// - /// To allow items to be compared, the hash code - /// is set to the Window handle, so two EnumWindowsItem - /// objects for the same Window will be equal. - /// - /// The Window Handle for this window - public override int GetHashCode() - { - return Handle.ToInt32(); - } - - public override bool Equals(object right) - { - return Equals(right as WindowDetails); - } - - public bool Equals(WindowDetails other) - { - if (ReferenceEquals(other, null)) - { - return false; - } - - if (ReferenceEquals(this, other)) - { - return true; - } - - if (GetType() != other.GetType()) - { - return false; - } - return other.Handle == Handle; - } - - public bool HasChildren - { - get - { - return (_childWindows != null) && (_childWindows.Count > 0); - } - } - - public void FreezeDetails() - { - _frozen = true; - } - - public void UnfreezeDetails() - { - _frozen = false; - } - - public string ProcessPath - { - get - { - if (Handle == IntPtr.Zero) - { - // not a valid window handle - return string.Empty; - } - // Get the process id - int processid; - User32.GetWindowThreadProcessId(Handle, out processid); - return Kernel32.GetProcessPath(processid); - } - } - - /// - /// Get the icon belonging to the process - /// - public Image DisplayIcon - { - get - { - try - { - using (Icon appIcon = GetAppIcon(Handle)) - { - if (appIcon != null) - { - return appIcon.ToBitmap(); - } - } - } - catch (Exception ex) - { - LOG.WarnFormat("Couldn't get icon for window {0} due to: {1}", Text, ex.Message); - LOG.Warn(ex); - } - if (IsMetroApp) - { - // No method yet to get the metro icon - return null; - } - try - { - return PluginUtils.GetCachedExeIcon(ProcessPath, 0); - } - catch (Exception ex) - { - LOG.WarnFormat("Couldn't get icon for window {0} due to: {1}", Text, ex.Message); - LOG.Warn(ex); - } - return null; - } - } - - /// - /// Get the icon for a hWnd - /// - /// - /// - private static Icon GetAppIcon(IntPtr hwnd) - { - IntPtr ICON_SMALL = IntPtr.Zero; - IntPtr ICON_BIG = new IntPtr(1); - IntPtr ICON_SMALL2 = new IntPtr(2); - - IntPtr iconHandle; - if (Conf.UseLargeIcons) - { - iconHandle = User32.SendMessage(hwnd, (int)WindowsMessages.WM_GETICON, ICON_BIG, IntPtr.Zero); - if (iconHandle == IntPtr.Zero) - { - iconHandle = User32.GetClassLongWrapper(hwnd, (int)ClassLongIndex.GCL_HICON); - } - } - else - { - iconHandle = User32.SendMessage(hwnd, (int)WindowsMessages.WM_GETICON, ICON_SMALL2, IntPtr.Zero); - } - if (iconHandle == IntPtr.Zero) - { - iconHandle = User32.SendMessage(hwnd, (int)WindowsMessages.WM_GETICON, ICON_SMALL, IntPtr.Zero); - } - if (iconHandle == IntPtr.Zero) - { - iconHandle = User32.GetClassLongWrapper(hwnd, (int)ClassLongIndex.GCL_HICONSM); - } - if (iconHandle == IntPtr.Zero) - { - iconHandle = User32.SendMessage(hwnd, (int)WindowsMessages.WM_GETICON, ICON_BIG, IntPtr.Zero); - } - if (iconHandle == IntPtr.Zero) - { - iconHandle = User32.GetClassLongWrapper(hwnd, (int)ClassLongIndex.GCL_HICON); - } - - if (iconHandle == IntPtr.Zero) - { - return null; - } - - Icon icon = Icon.FromHandle(iconHandle); - - return icon; - } - - /// - /// Use this to make remove internal windows, like the mainform and the captureforms, invisible - /// - /// - public static void RegisterIgnoreHandle(IntPtr ignoreHandle) - { - IgnoreHandles.Add(ignoreHandle); - } - - /// - /// Use this to remove the with RegisterIgnoreHandle registered handle - /// - /// - public static void UnregisterIgnoreHandle(IntPtr ignoreHandle) - { - IgnoreHandles.Remove(ignoreHandle); - } - - public List Children - { - get - { - if (_childWindows == null) - { - GetChildren(); - } - return _childWindows; - } - } - - /// - /// Retrieve all windows with a certain title or classname - /// - /// - /// The regexp to look for in the title - /// The regexp to look for in the classname - /// List with all the found windows - private static List FindWindow(List windows, string titlePattern, string classnamePattern) - { - List foundWindows = new List(); - Regex titleRegexp = null; - Regex classnameRegexp = null; - - if (titlePattern != null && titlePattern.Trim().Length > 0) - { - titleRegexp = new Regex(titlePattern); - } - if (classnamePattern != null && classnamePattern.Trim().Length > 0) - { - classnameRegexp = new Regex(classnamePattern); - } - - foreach (WindowDetails window in windows) - { - if (titleRegexp != null && titleRegexp.IsMatch(window.Text)) - { - foundWindows.Add(window); - } - else if (classnameRegexp != null && classnameRegexp.IsMatch(window.ClassName)) - { - foundWindows.Add(window); - } - } - return foundWindows; - } - - /// - /// Retrieve the child with matching classname - /// - public WindowDetails GetChild(string childClassname) - { - foreach (WindowDetails child in Children) - { - if (childClassname.Equals(child.ClassName)) - { - return child; - } - } - return null; - } - - /// - /// Retrieve the children with matching classname - /// - public IEnumerable GetChilden(string childClassname) - { - foreach (WindowDetails child in Children) - { - if (childClassname.Equals(child.ClassName)) - { - yield return child; - } - } - } - - public IntPtr ParentHandle - { - get - { - if (_parentHandle == IntPtr.Zero) - { - _parentHandle = User32.GetParent(Handle); - _parent = null; - } - return _parentHandle; - } - set - { - if (_parentHandle != value) - { - _parentHandle = value; - _parent = null; - } - } - } - - /// - /// Get the parent of the current window - /// - /// WindowDetails of the parent, or null if none - public WindowDetails GetParent() - { - if (_parent == null) - { - if (_parentHandle == IntPtr.Zero) - { - _parentHandle = User32.GetParent(Handle); - } - if (_parentHandle != IntPtr.Zero) - { - _parent = new WindowDetails(_parentHandle); - } - } - return _parent; - } - - /// - /// Retrieve all the children, this only stores the children internally. - /// One should normally use the getter "Children" - /// - public List GetChildren() - { - if (_childWindows == null) - { - return GetChildren(0); - } - return _childWindows; - } - - /// - /// Retrieve all the children, this only stores the children internally, use the "Children" property for the value - /// - /// Specify how many levels we go in - public List GetChildren(int levelsToGo) - { - if (_childWindows == null) - { - _childWindows = new List(); - foreach (WindowDetails childWindow in new WindowsEnumerator().GetWindows(_hWnd, null).Items) - { - _childWindows.Add(childWindow); - if (levelsToGo > 0) - { - childWindow.GetChildren(levelsToGo - 1); - } - } - } - return _childWindows; - } - - /// - /// Retrieve children with a certain title or classname - /// - /// The regexp to look for in the title - /// The regexp to look for in the classname - /// List WindowDetails with all the found windows, or an empty list - public List FindChildren(string titlePattern, string classnamePattern) - { - return FindWindow(Children, titlePattern, classnamePattern); - } - - /// - /// Recursing helper method for the FindPath - /// - /// List with classnames - /// The index in the list to look for - /// WindowDetails if a match was found - private WindowDetails FindPath(List classnames, int index) - { - WindowDetails resultWindow = null; - List foundWindows = FindChildren(null, classnames[index]); - if (index == classnames.Count - 1) - { - if (foundWindows.Count > 0) - { - resultWindow = foundWindows[0]; - } - } - else - { - foreach (WindowDetails foundWindow in foundWindows) - { - resultWindow = foundWindow.FindPath(classnames, index + 1); - if (resultWindow != null) - { - break; - } - } - } - return resultWindow; - } - - /// - /// This method will find the child window according to a path of classnames. - /// Usually used for finding a certain "content" window like for the IE Browser - /// - /// List string with classname "path" - /// true allows the search to skip a classname of the path - /// WindowDetails if found - public WindowDetails FindPath(List classnames, bool allowSkip) - { - int index = 0; - WindowDetails resultWindow = FindPath(classnames, index++); - if (resultWindow == null && allowSkip) - { - while (resultWindow == null && index < classnames.Count) - { - resultWindow = FindPath(classnames, index); - } - } - return resultWindow; - } - - /// - /// Deep scan for a certain classname pattern - /// - /// Classname regexp pattern - /// The first WindowDetails found - public static WindowDetails DeepScan(WindowDetails windowDetails, Regex classnamePattern) - { - if (classnamePattern.IsMatch(windowDetails.ClassName)) - { - return windowDetails; - } - // First loop through this level - foreach (WindowDetails child in windowDetails.Children) - { - if (classnamePattern.IsMatch(child.ClassName)) - { - return child; - } - } - // Go into all children - foreach (WindowDetails child in windowDetails.Children) - { - WindowDetails deepWindow = DeepScan(child, classnamePattern); - if (deepWindow != null) - { - return deepWindow; - } - } - return null; - } - - /// - /// GetWindow - /// - /// The GetWindowCommand to use - /// null if nothing found, otherwise the WindowDetails instance of the "child" - public WindowDetails GetWindow(GetWindowCommand gwCommand) - { - IntPtr tmphWnd = User32.GetWindow(Handle, gwCommand); - if (IntPtr.Zero == tmphWnd) - { - return null; - } - WindowDetails windowDetails = new WindowDetails(tmphWnd); - windowDetails._parent = this; - return windowDetails; - } - - /// - /// Gets the window's handle - /// - public IntPtr Handle - { - get - { - return _hWnd; - } - } - - private string _text; - /// - /// Gets the window's title (caption) - /// - public string Text - { - set - { - _text = value; - } - get - { - if (_text == null) - { - StringBuilder title = new StringBuilder(260, 260); - User32.GetWindowText(_hWnd, title, title.Capacity); - _text = title.ToString(); - } - return _text; - } - } - - private string _className; - /// - /// Gets the window's class name. - /// - public string ClassName - { - get - { - if (_className == null) - { - _className = GetClassName(_hWnd); - } - return _className; - } - } - - /// - /// Gets/Sets whether the window is iconic (mimimized) or not. - /// - public bool Iconic - { - get - { - if (IsMetroApp) - { - return !Visible; - } - return User32.IsIconic(_hWnd) || Location.X <= -32000; - } - set - { - if (value) - { - User32.SendMessage(_hWnd, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)User32.SC_MINIMIZE, IntPtr.Zero); - } - else - { - User32.SendMessage(_hWnd, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)User32.SC_RESTORE, IntPtr.Zero); - } - } - } - - /// - /// Gets/Sets whether the window is maximised or not. - /// - public bool Maximised - { - get - { - if (IsApp) - { - if (Visible) - { - Rectangle windowRectangle = WindowRectangle; - foreach (Screen screen in Screen.AllScreens) - { - if (screen.Bounds.Contains(windowRectangle)) - { - if (windowRectangle.Equals(screen.Bounds)) - { - return true; - } - } - } - } - return false; - } - return User32.IsZoomed(_hWnd); - } - set - { - if (value) - { - User32.SendMessage(_hWnd, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)User32.SC_MAXIMIZE, IntPtr.Zero); - } - else - { - User32.SendMessage(_hWnd, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)User32.SC_MINIMIZE, IntPtr.Zero); - } - } - } - - /// - /// This doesn't work as good as is should, but does move the App out of the way... - /// - public void HideApp() - { - User32.ShowWindow(Handle, ShowWindowCommand.Hide); - } - - /// - /// Gets whether the window is visible. - /// - public bool Visible - { - get - { - if (IsApp) - { - Rectangle windowRectangle = WindowRectangle; - foreach (Screen screen in Screen.AllScreens) - { - if (screen.Bounds.Contains(windowRectangle)) - { - if (windowRectangle.Equals(screen.Bounds)) - { - // Fullscreen, it's "visible" when AppVisibilityOnMonitor says yes - // Although it might be the other App, this is not "very" important - RECT rect = new RECT(screen.Bounds); - IntPtr monitor = User32.MonitorFromRect(ref rect, User32.MONITOR_DEFAULTTONULL); - if (monitor != IntPtr.Zero) - { - if (appVisibility != null) - { - MONITOR_APP_VISIBILITY monitorAppVisibility = appVisibility.GetAppVisibilityOnMonitor(monitor); - //LOG.DebugFormat("App {0} visible: {1} on {2}", Text, monitorAppVisibility, screen.Bounds); - if (monitorAppVisibility == MONITOR_APP_VISIBILITY.MAV_APP_VISIBLE) - { - return true; - } - } - } - } - else - { - // Is only partly on the screen, when this happens the app is always visible! - return true; - } - } - } - return false; - } - if (IsGutter) - { - // gutter is only made available when it's visible - return true; - } - if (IsAppLauncher) - { - return IsAppLauncherVisible; - } - return User32.IsWindowVisible(_hWnd); - } - } - - public bool HasParent - { - get - { - GetParent(); - return _parentHandle != IntPtr.Zero; - } - } - - public int ProcessId - { - get - { - int processId; - User32.GetWindowThreadProcessId(Handle, out processId); - return processId; - } - } - - public Process Process - { - get - { - try - { - int processId; - User32.GetWindowThreadProcessId(Handle, out processId); - Process process = Process.GetProcessById(processId); - if (process != null) - { - return process; - } - } - catch (Exception ex) - { - LOG.Warn(ex); - } - return null; - } - } - - /// - /// Make sure the next call of a cached value is guaranteed the real value - /// - public void Reset() - { - _previousWindowRectangle = Rectangle.Empty; - } - - private Rectangle _previousWindowRectangle = Rectangle.Empty; - private long _lastWindowRectangleRetrieveTime; - private const long CacheTime = TimeSpan.TicksPerSecond * 2; - /// - /// Gets the bounding rectangle of the window - /// - public Rectangle WindowRectangle - { - get - { - // Try to return a cached value - long now = DateTime.Now.Ticks; - if (_previousWindowRectangle.IsEmpty || !_frozen) - { - if (_previousWindowRectangle.IsEmpty || now - _lastWindowRectangleRetrieveTime > CacheTime) - { - Rectangle windowRect = Rectangle.Empty; - if (DWM.IsDwmEnabled()) - { - bool gotFrameBounds = GetExtendedFrameBounds(out windowRect); - if (IsApp) - { - // Pre-Cache for Maximised call, this is only on Windows 8 apps (full screen) - if (gotFrameBounds) - { - _previousWindowRectangle = windowRect; - _lastWindowRectangleRetrieveTime = now; - } - } - if (gotFrameBounds && Environment.OSVersion.IsWindows10() && !Maximised) - { - // Somehow DWM doesn't calculate it corectly, there is a 1 pixel border around the capture - // Remove this border, currently it's fixed but TODO: Make it depend on the OS? - windowRect.Inflate(-1, -1); - _previousWindowRectangle = windowRect; - _lastWindowRectangleRetrieveTime = now; - return windowRect; - } - } - - if (windowRect.IsEmpty) - { - if (GetWindowRect(out windowRect)) - { - Win32Error error = Win32.GetLastErrorCode(); - LOG.WarnFormat("Couldn't retrieve the windows rectangle: {0}", Win32.GetMessage(error)); - } - } - - // Correction for maximized windows, only if it's not an app - if (!HasParent && !IsApp && Maximised) - { - Size size; - // Only if the border size can be retrieved - if (GetBorderSize(out size)) - { - windowRect = new Rectangle(windowRect.X + size.Width, windowRect.Y + size.Height, windowRect.Width - (2 * size.Width), windowRect.Height - (2 * size.Height)); - } - } - _lastWindowRectangleRetrieveTime = now; - // Try to return something valid, by getting returning the previous size if the window doesn't have a Rectangle anymore - if (windowRect.IsEmpty) - { - return _previousWindowRectangle; - } - _previousWindowRectangle = windowRect; - return windowRect; - } - } - return _previousWindowRectangle; - } - } - - /// - /// Gets the location of the window relative to the screen. - /// - public Point Location - { - get - { - Rectangle tmpRectangle = WindowRectangle; - return new Point(tmpRectangle.Left, tmpRectangle.Top); - } - } - - /// - /// Gets the size of the window. - /// - public Size Size - { - get - { - Rectangle tmpRectangle = WindowRectangle; - return new Size(tmpRectangle.Right - tmpRectangle.Left, tmpRectangle.Bottom - tmpRectangle.Top); - } - } - - /// - /// Get the client rectangle, this is the part of the window inside the borders (drawable area) - /// - public Rectangle ClientRectangle - { - get - { - Rectangle clientRect; - if (GetClientRect(out clientRect)) - { - Win32Error error = Win32.GetLastErrorCode(); - LOG.WarnFormat("Couldn't retrieve the client rectangle: {0}", Win32.GetMessage(error)); - } - return clientRect; - } - } - - /// - /// Check if the supplied point lies in the window - /// - /// Point with the coordinates to check - /// true if the point lies within - public bool Contains(Point p) - { - return WindowRectangle.Contains(Cursor.Position); - } - - /// - /// Restores and Brings the window to the front, - /// assuming it is a visible application window. - /// - public void Restore() - { - if (Iconic) - { - User32.SendMessage(_hWnd, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)User32.SC_RESTORE, IntPtr.Zero); - } - User32.BringWindowToTop(_hWnd); - User32.SetForegroundWindow(_hWnd); - // Make sure windows has time to perform the action - while (Iconic) - { - Application.DoEvents(); - } - } - - /// - /// Get / Set the WindowStyle - /// - public WindowStyleFlags WindowStyle - { - get - { - return (WindowStyleFlags)User32.GetWindowLongWrapper(_hWnd, (int)WindowLongIndex.GWL_STYLE); - } - set - { - User32.SetWindowLongWrapper(_hWnd, (int)WindowLongIndex.GWL_STYLE, new IntPtr((long)value)); - } - } - - /// - /// Get/Set the WindowPlacement - /// - public WindowPlacement WindowPlacement - { - get - { - WindowPlacement placement = WindowPlacement.Default; - User32.GetWindowPlacement(Handle, ref placement); - return placement; - } - set - { - User32.SetWindowPlacement(Handle, ref value); - } - } - - /// - /// Get/Set the Extended WindowStyle - /// - public ExtendedWindowStyleFlags ExtendedWindowStyle - { - get - { - return (ExtendedWindowStyleFlags)User32.GetWindowLongWrapper(_hWnd, (int)WindowLongIndex.GWL_EXSTYLE); - } - set - { - User32.SetWindowLongWrapper(_hWnd, (int)WindowLongIndex.GWL_EXSTYLE, new IntPtr((uint)value)); - } - } - - /// - /// Capture Window with GDI+ - /// - /// The capture to fill - /// ICapture - public ICapture CaptureGdiWindow(ICapture capture) - { - Image capturedImage = PrintWindow(); - if (capturedImage != null) - { - capture.Image = capturedImage; - capture.Location = Location; - return capture; - } - return null; - } - - /// - /// Capture DWM Window - /// - /// Capture to fill - /// Wanted WindowCaptureMode - /// True if auto modus is used - /// ICapture with the capture - public ICapture CaptureDwmWindow(ICapture capture, WindowCaptureMode windowCaptureMode, bool autoMode) - { - IntPtr thumbnailHandle = IntPtr.Zero; - Form tempForm = null; - bool tempFormShown = false; - try - { - tempForm = new Form - { - ShowInTaskbar = false, - FormBorderStyle = FormBorderStyle.None, - TopMost = true - }; - - // Register the Thumbnail - DWM.DwmRegisterThumbnail(tempForm.Handle, Handle, out thumbnailHandle); - - // Get the original size - SIZE sourceSize; - DWM.DwmQueryThumbnailSourceSize(thumbnailHandle, out sourceSize); - - if (sourceSize.Width <= 0 || sourceSize.Height <= 0) - { - return null; - } - - // Calculate the location of the temp form - Rectangle windowRectangle = WindowRectangle; - Point formLocation = windowRectangle.Location; - Size borderSize = new Size(); - bool doesCaptureFit = false; - if (!Maximised) - { - // Assume using it's own location - formLocation = windowRectangle.Location; - using (Region workingArea = new Region(Screen.PrimaryScreen.Bounds)) - { - // Find the screen where the window is and check if it fits - foreach (Screen screen in Screen.AllScreens) - { - if (!Equals(screen, Screen.PrimaryScreen)) - { - workingArea.Union(screen.Bounds); - } - } - - // If the formLocation is not inside the visible area - if (!workingArea.AreRectangleCornersVisisble(windowRectangle)) - { - // If none found we find the biggest screen - foreach (Screen screen in Screen.AllScreens) - { - Rectangle newWindowRectangle = new Rectangle(screen.WorkingArea.Location, windowRectangle.Size); - if (workingArea.AreRectangleCornersVisisble(newWindowRectangle)) - { - formLocation = screen.Bounds.Location; - doesCaptureFit = true; - break; - } - } - } - else - { - doesCaptureFit = true; - } - } - } - else if (!Environment.OSVersion.IsWindows8OrLater()) - { - //GetClientRect(out windowRectangle); - GetBorderSize(out borderSize); - formLocation = new Point(windowRectangle.X - borderSize.Width, windowRectangle.Y - borderSize.Height); - } - - tempForm.Location = formLocation; - tempForm.Size = sourceSize.ToSize(); - - // Prepare rectangle to capture from the screen. - Rectangle captureRectangle = new Rectangle(formLocation.X, formLocation.Y, sourceSize.Width, sourceSize.Height); - if (Maximised) - { - // Correct capture size for maximized window by offsetting the X,Y with the border size - // and subtracting the border from the size (2 times, as we move right/down for the capture without resizing) - captureRectangle.Inflate(borderSize.Width, borderSize.Height); - } - else - { - captureRectangle.Inflate(-1, -1); - - if (autoMode) - { - // check if the capture fits - if (!doesCaptureFit) - { - // if GDI is allowed.. (a screenshot won't be better than we comes if we continue) - using (Process thisWindowProcess = Process) - { - if (!IsMetroApp && WindowCapture.IsGdiAllowed(thisWindowProcess)) - { - // we return null which causes the capturing code to try another method. - return null; - } - } - } - } - } - - // Prepare the displaying of the Thumbnail - DWM_THUMBNAIL_PROPERTIES props = new DWM_THUMBNAIL_PROPERTIES - { - Opacity = 255, - Visible = true, - Destination = new RECT(0, 0, sourceSize.Width, sourceSize.Height) - }; - DWM.DwmUpdateThumbnailProperties(thumbnailHandle, ref props); - tempForm.Show(); - tempFormShown = true; - - // Intersect with screen - captureRectangle.Intersect(capture.ScreenBounds); - - // Destination bitmap for the capture - Bitmap capturedBitmap = null; - bool frozen = false; - try - { - // Check if we make a transparent capture - if (windowCaptureMode == WindowCaptureMode.AeroTransparent) - { - frozen = FreezeWindow(); - // Use white, later black to capture transparent - tempForm.BackColor = Color.White; - // Make sure everything is visible - tempForm.Refresh(); - Application.DoEvents(); - - try - { - using (Bitmap whiteBitmap = WindowCapture.CaptureRectangle(captureRectangle)) - { - // Apply a white color - tempForm.BackColor = Color.Black; - // Make sure everything is visible - tempForm.Refresh(); - if (!IsMetroApp) - { - // Make sure the application window is active, so the colors & buttons are right - ToForeground(); - } - // Make sure all changes are processed and visible - Application.DoEvents(); - using (Bitmap blackBitmap = WindowCapture.CaptureRectangle(captureRectangle)) - { - capturedBitmap = ApplyTransparency(blackBitmap, whiteBitmap); - } - } - } - catch (Exception e) - { - LOG.Debug("Exception: ", e); - // Some problem occurred, cleanup and make a normal capture - if (capturedBitmap != null) - { - capturedBitmap.Dispose(); - capturedBitmap = null; - } - } - } - // If no capture up till now, create a normal capture. - if (capturedBitmap == null) - { - // Remove transparency, this will break the capturing - if (!autoMode) - { - tempForm.BackColor = Color.FromArgb(255, Conf.DWMBackgroundColor.R, Conf.DWMBackgroundColor.G, Conf.DWMBackgroundColor.B); - } - else - { - Color colorizationColor = DWM.ColorizationColor; - // Modify by losing the transparency and increasing the intensity (as if the background color is white) - colorizationColor = Color.FromArgb(255, (colorizationColor.R + 255) >> 1, (colorizationColor.G + 255) >> 1, (colorizationColor.B + 255) >> 1); - tempForm.BackColor = colorizationColor; - } - // Make sure everything is visible - tempForm.Refresh(); - if (!IsMetroApp) - { - // Make sure the application window is active, so the colors & buttons are right - ToForeground(); - } - // Make sure all changes are processed and visible - Application.DoEvents(); - // Capture from the screen - capturedBitmap = WindowCapture.CaptureRectangle(captureRectangle); - } - if (capturedBitmap != null) - { - // Not needed for Windows 8 - if (!Environment.OSVersion.IsWindows8OrLater()) - { - // Only if the Inivalue is set, not maximized and it's not a tool window. - if (Conf.WindowCaptureRemoveCorners && !Maximised && (ExtendedWindowStyle & ExtendedWindowStyleFlags.WS_EX_TOOLWINDOW) == 0) - { - // Remove corners - if (!Image.IsAlphaPixelFormat(capturedBitmap.PixelFormat)) - { - LOG.Debug("Changing pixelformat to Alpha for the RemoveCorners"); - Bitmap tmpBitmap = ImageHelper.Clone(capturedBitmap, PixelFormat.Format32bppArgb); - capturedBitmap.Dispose(); - capturedBitmap = tmpBitmap; - } - RemoveCorners(capturedBitmap); - } - } - } - } - finally - { - // Make sure to ALWAYS unfreeze!! - if (frozen) - { - UnfreezeWindow(); - } - } - - capture.Image = capturedBitmap; - // Make sure the capture location is the location of the window, not the copy - capture.Location = Location; - } - finally - { - if (thumbnailHandle != IntPtr.Zero) - { - // Unregister (cleanup), as we are finished we don't need the form or the thumbnail anymore - DWM.DwmUnregisterThumbnail(thumbnailHandle); - } - if (tempForm != null) - { - if (tempFormShown) - { - tempForm.Close(); - } - tempForm.Dispose(); - tempForm = null; - } - } - - return capture; - } - - /// - /// Helper method to remove the corners from a DMW capture - /// - /// The bitmap to remove the corners from. - private void RemoveCorners(Bitmap image) - { - using (IFastBitmap fastBitmap = FastBitmap.Create(image)) - { - for (int y = 0; y < Conf.WindowCornerCutShape.Count; y++) - { - for (int x = 0; x < Conf.WindowCornerCutShape[y]; x++) - { - fastBitmap.SetColorAt(x, y, Color.Transparent); - fastBitmap.SetColorAt(image.Width - 1 - x, y, Color.Transparent); - fastBitmap.SetColorAt(image.Width - 1 - x, image.Height - 1 - y, Color.Transparent); - fastBitmap.SetColorAt(x, image.Height - 1 - y, Color.Transparent); - } - } - } - } - - /// - /// Apply transparency by comparing a transparent capture with a black and white background - /// A "Math.min" makes sure there is no overflow, but this could cause the picture to have shifted colors. - /// The pictures should have been taken without differency, except for the colors. - /// - /// Bitmap with the black image - /// Bitmap with the black image - /// Bitmap with transparency - private Bitmap ApplyTransparency(Bitmap blackBitmap, Bitmap whiteBitmap) - { - using (IFastBitmap targetBuffer = FastBitmap.CreateEmpty(blackBitmap.Size, PixelFormat.Format32bppArgb, Color.Transparent)) - { - targetBuffer.SetResolution(blackBitmap.HorizontalResolution, blackBitmap.VerticalResolution); - using (IFastBitmap blackBuffer = FastBitmap.Create(blackBitmap)) - { - using (IFastBitmap whiteBuffer = FastBitmap.Create(whiteBitmap)) - { - for (int y = 0; y < blackBuffer.Height; y++) - { - for (int x = 0; x < blackBuffer.Width; x++) - { - Color c0 = blackBuffer.GetColorAt(x, y); - Color c1 = whiteBuffer.GetColorAt(x, y); - // Calculate alpha as double in range 0-1 - double alpha = (c0.R - c1.R + 255) / 255d; - if (alpha == 1) - { - // Alpha == 1 means no change! - targetBuffer.SetColorAt(x, y, c0); - } - else if (alpha == 0) - { - // Complete transparency, use transparent pixel - targetBuffer.SetColorAt(x, y, Color.Transparent); - } - else - { - // Calculate original color - byte originalAlpha = (byte)Math.Min(255, alpha * 255); - //LOG.DebugFormat("Alpha {0} & c0 {1} & c1 {2}", alpha, c0, c1); - byte originalRed = (byte)Math.Min(255, c0.R / alpha); - byte originalGreen = (byte)Math.Min(255, c0.G / alpha); - byte originalBlue = (byte)Math.Min(255, c0.B / alpha); - Color originalColor = Color.FromArgb(originalAlpha, originalRed, originalGreen, originalBlue); - //Color originalColor = Color.FromArgb(originalAlpha, originalRed, c0.G, c0.B); - targetBuffer.SetColorAt(x, y, originalColor); - } - } - } - } - } - return targetBuffer.UnlockAndReturnBitmap(); - } - } - - /// - /// Helper method to get the window size for DWM Windows - /// - /// out Rectangle - /// bool true if it worked - private bool GetExtendedFrameBounds(out Rectangle rectangle) - { - RECT rect; - int result = DWM.DwmGetWindowAttribute(Handle, (int)DWMWINDOWATTRIBUTE.DWMWA_EXTENDED_FRAME_BOUNDS, out rect, Marshal.SizeOf(typeof(RECT))); - if (result >= 0) - { - rectangle = rect.ToRectangle(); - return true; - } - rectangle = Rectangle.Empty; - return false; - } - - /// - /// Helper method to get the window size for GDI Windows - /// - /// out Rectangle - /// bool true if it worked - private bool GetClientRect(out Rectangle rectangle) - { - WindowInfo windowInfo = new WindowInfo(); - // Get the Window Info for this window - bool result = User32.GetWindowInfo(Handle, ref windowInfo); - if (result) - { - rectangle = windowInfo.rcClient.ToRectangle(); - } - else - { - rectangle = Rectangle.Empty; - } - return result; - } - - /// - /// Helper method to get the window size for GDI Windows - /// - /// out Rectangle - /// bool true if it worked - private bool GetWindowRect(out Rectangle rectangle) - { - WindowInfo windowInfo = new WindowInfo(); - // Get the Window Info for this window - bool result = User32.GetWindowInfo(Handle, ref windowInfo); - if (result) - { - rectangle = windowInfo.rcWindow.ToRectangle(); - } - else - { - rectangle = Rectangle.Empty; - } - return result; - } - - /// - /// Helper method to get the Border size for GDI Windows - /// - /// out Size - /// bool true if it worked - private bool GetBorderSize(out Size size) - { - WindowInfo windowInfo = new WindowInfo(); - // Get the Window Info for this window - bool result = User32.GetWindowInfo(Handle, ref windowInfo); - if (result) - { - size = new Size((int)windowInfo.cxWindowBorders, (int)windowInfo.cyWindowBorders); - } - else - { - size = Size.Empty; - } - return result; - } - - /// - /// Set the window as foreground window - /// - public static void ToForeground(IntPtr handle) - { - User32.SetForegroundWindow(handle); - } - - /// - /// Set the window as foreground window - /// - public void ToForeground() - { - ToForeground(Handle); - } - - /// - /// Get the region for a window - /// - private Region GetRegion() - { - using (SafeRegionHandle region = GDI32.CreateRectRgn(0, 0, 0, 0)) - { - if (!region.IsInvalid) - { - RegionResult result = User32.GetWindowRgn(Handle, region); - if (result != RegionResult.REGION_ERROR && result != RegionResult.REGION_NULLREGION) - { - return Region.FromHrgn(region.DangerousGetHandle()); - } - } - } - return null; - } - - private bool CanFreezeOrUnfreeze(string titleOrProcessname) - { - if (string.IsNullOrEmpty(titleOrProcessname)) - { - return false; - } - if (titleOrProcessname.ToLower().Contains("greenshot")) - { - return false; - } - - foreach (string excludeProcess in ExcludeProcessesFromFreeze) - { - if (titleOrProcessname.ToLower().Contains(excludeProcess)) - { - return false; - } - } - return true; - } - - /// - /// Freezes the process belonging to the window - /// Warning: Use only if no other way!! - /// - private bool FreezeWindow() - { - bool frozen = false; - using (Process proc = Process.GetProcessById(ProcessId)) - { - string processName = proc.ProcessName; - if (!CanFreezeOrUnfreeze(processName)) - { - LOG.DebugFormat("Not freezing {0}", processName); - return false; - } - if (!CanFreezeOrUnfreeze(Text)) - { - LOG.DebugFormat("Not freezing {0}", processName); - return false; - } - LOG.DebugFormat("Freezing process: {0}", processName); - - foreach (ProcessThread pT in proc.Threads) - { - IntPtr pOpenThread = Kernel32.OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id); - - if (pOpenThread == IntPtr.Zero) - { - break; - } - frozen = true; - Kernel32.SuspendThread(pOpenThread); - pT.Dispose(); - } - } - return frozen; - } - - /// - /// Unfreeze the process belonging to the window - /// - public void UnfreezeWindow() - { - using (Process proc = Process.GetProcessById(ProcessId)) - { - string processName = proc.ProcessName; - if (!CanFreezeOrUnfreeze(processName)) - { - LOG.DebugFormat("Not unfreezing {0}", processName); - return; - } - if (!CanFreezeOrUnfreeze(Text)) - { - LOG.DebugFormat("Not unfreezing {0}", processName); - return; - } - LOG.DebugFormat("Unfreezing process: {0}", processName); - - foreach (ProcessThread pT in proc.Threads) - { - IntPtr pOpenThread = Kernel32.OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id); - - if (pOpenThread == IntPtr.Zero) - { - break; - } - - Kernel32.ResumeThread(pOpenThread); - } - } - } - - /// - /// Return an Image representing the Window! - /// As GDI+ draws it, it will be without Aero borders! - /// - public Image PrintWindow() - { - Rectangle windowRect = WindowRectangle; - // Start the capture - Exception exceptionOccured = null; - Image returnImage = null; - using (Region region = GetRegion()) - { - PixelFormat pixelFormat = PixelFormat.Format24bppRgb; - // Only use 32 bpp ARGB when the window has a region - if (region != null) - { - pixelFormat = PixelFormat.Format32bppArgb; - } - returnImage = new Bitmap(windowRect.Width, windowRect.Height, pixelFormat); - using (Graphics graphics = Graphics.FromImage(returnImage)) - { - using (SafeDeviceContextHandle graphicsDC = graphics.GetSafeDeviceContext()) - { - bool printSucceeded = User32.PrintWindow(Handle, graphicsDC.DangerousGetHandle(), 0x0); - if (!printSucceeded) - { - // something went wrong, most likely a "0x80004005" (Acess Denied) when using UAC - exceptionOccured = User32.CreateWin32Exception("PrintWindow"); - } - } - - // Apply the region "transparency" - if (region != null && !region.IsEmpty(graphics)) - { - graphics.ExcludeClip(region); - graphics.Clear(Color.Transparent); - } - - graphics.Flush(); - } - } - - // Return null if error - if (exceptionOccured != null) - { - LOG.ErrorFormat("Error calling print window: {0}", exceptionOccured.Message); - if (returnImage != null) - { - returnImage.Dispose(); - } - return null; - } - if (!HasParent && Maximised) - { - LOG.Debug("Correcting for maximalization"); - Size borderSize = Size.Empty; - GetBorderSize(out borderSize); - Rectangle borderRectangle = new Rectangle(borderSize.Width, borderSize.Height, windowRect.Width - (2 * borderSize.Width), windowRect.Height - (2 * borderSize.Height)); - ImageHelper.Crop(ref returnImage, ref borderRectangle); - } - return returnImage; - } - - /// - /// Constructs a new instance of this class for - /// the specified Window Handle. - /// - /// The Window Handle - public WindowDetails(IntPtr hWnd) - { - this._hWnd = hWnd; - } - - /// - /// Gets an instance of the current active foreground window - /// - /// WindowDetails of the current window - public static WindowDetails GetActiveWindow() - { - IntPtr hWnd = User32.GetForegroundWindow(); - if (hWnd != null && hWnd != IntPtr.Zero) - { - if (IgnoreHandles.Contains(hWnd)) - { - return GetDesktopWindow(); - } - - WindowDetails activeWindow = new WindowDetails(hWnd); - // Invisible Windows should not be active - if (!activeWindow.Visible) - { - return GetDesktopWindow(); - } - return activeWindow; - } - return null; - } - - /// - /// Check if this window is Greenshot - /// - public bool IsGreenshot - { - get - { - try - { - if (!IsMetroApp) - { - using (Process thisWindowProcess = Process) - { - return "Greenshot".Equals(thisWindowProcess.MainModule.FileVersionInfo.ProductName); - } - } - } - catch (Exception ex) - { - LOG.Warn(ex); - } - return false; - } - } - - /// - /// Gets the Desktop window - /// - /// WindowDetails for the desktop window - public static WindowDetails GetDesktopWindow() - { - return new WindowDetails(User32.GetDesktopWindow()); - } - - /// - /// Get all the top level windows - /// - /// List with all the top level windows - public static List GetAllWindows() - { - return GetAllWindows(null); - } - - /// - /// Get all the top level windows, with matching classname - /// - /// List WindowDetails with all the top level windows - public static List GetAllWindows(string classname) - { - return new WindowsEnumerator().GetWindows(IntPtr.Zero, classname).Items; - } - - /// - /// Recursive "find children which" - /// - /// point to check for - /// - public WindowDetails FindChildUnderPoint(Point point) - { - if (!Contains(point)) - { - return null; - } - foreach (WindowDetails childWindow in Children) - { - if (childWindow.Contains(point)) - { - return childWindow.FindChildUnderPoint(point); - } - } - return this; - } - - /// - /// Retrieves the classname for a hWnd - /// - /// IntPtr with the windows handle - /// String with ClassName - public static string GetClassName(IntPtr hWnd) - { - StringBuilder classNameBuilder = new StringBuilder(260, 260); - User32.GetClassName(hWnd, classNameBuilder, classNameBuilder.Capacity); - return classNameBuilder.ToString(); - } - - /// - /// Get all the visible top level windows - /// - /// List WindowDetails with all the visible top level windows - public static List GetVisibleWindows() - { - List windows = new List(); - Rectangle screenBounds = WindowCapture.GetScreenBounds(); - List allWindows = GetMetroApps(); - allWindows.AddRange(GetAllWindows()); - foreach (WindowDetails window in allWindows) - { - // Ignore windows without title - if (window.Text.Length == 0) - { - continue; - } - // Ignore invisible - if (!window.Visible) - { - continue; - } - // Ignore some classes - List ignoreClasses = new List(new[] { "Progman", "XLMAIN", "Button", "Dwm" }); //"MS-SDIa" - if (ignoreClasses.Contains(window.ClassName)) - { - continue; - } - // Windows without size - Rectangle windowRect = window.WindowRectangle; - windowRect.Intersect(screenBounds); - if (windowRect.Size.IsEmpty) - { - continue; - } - windows.Add(window); - } - return windows; - } - - /// - /// Get the WindowDetails for all Metro Apps - /// These are all Windows with Classname "Windows.UI.Core.CoreWindow" - /// - /// List WindowDetails with visible metro apps - public static List GetMetroApps() - { - List metroApps = new List(); - // if the appVisibility != null we have Windows 8. - if (appVisibility == null) - { - return metroApps; - } - //string[] wcs = {"ImmersiveGutter", "Snapped Desktop", "ImmersiveBackgroundWindow","ImmersiveLauncher","Windows.UI.Core.CoreWindow","ApplicationManager_ImmersiveShellWindow","SearchPane","MetroGhostWindow","EdgeUiInputWndClass", "NativeHWNDHost", "Shell_CharmWindow"}; - //List specials = new List(); - //foreach(string wc in wcs) { - // IntPtr wcHandle = User32.FindWindow(null, null); - // while (wcHandle != IntPtr.Zero) { - // WindowDetails special = new WindowDetails(wcHandle); - // if (special.WindowRectangle.Left >= 1920 && special.WindowRectangle.Size != Size.Empty) { - // specials.Add(special); - // LOG.DebugFormat("Found special {0} : {1} at {2} visible: {3} {4} {5}", special.ClassName, special.Text, special.WindowRectangle, special.Visible, special.ExtendedWindowStyle, special.WindowStyle); - // } - // wcHandle = User32.FindWindowEx(IntPtr.Zero, wcHandle, null, null); - // }; - //} - IntPtr nextHandle = User32.FindWindow(METRO_WINDOWS_CLASS, null); - while (nextHandle != IntPtr.Zero) - { - WindowDetails metroApp = new WindowDetails(nextHandle); - metroApps.Add(metroApp); - // Check if we have a gutter! - if (metroApp.Visible && !metroApp.Maximised) - { - IntPtr gutterHandle = User32.FindWindow(METRO_GUTTER_CLASS, null); - if (gutterHandle != IntPtr.Zero) - { - metroApps.Add(new WindowDetails(gutterHandle)); - } - } - nextHandle = User32.FindWindowEx(IntPtr.Zero, nextHandle, METRO_WINDOWS_CLASS, null); - }; - - return metroApps; - } - - /// - /// Get all the top level windows - /// - /// List with all the top level windows - public static List GetTopLevelWindows() - { - List windows = new List(); - var possibleTopLevelWindows = GetMetroApps(); - possibleTopLevelWindows.AddRange(GetAllWindows()); - foreach (WindowDetails window in possibleTopLevelWindows) - { - // Ignore windows without title - if (window.Text.Length == 0) - { - continue; - } - // Ignore some classes - List ignoreClasses = new List(new[] { "Progman", "XLMAIN", "Button", "Dwm" }); //"MS-SDIa" - if (ignoreClasses.Contains(window.ClassName)) - { - continue; - } - // Windows without size - if (window.WindowRectangle.Size.IsEmpty) - { - continue; - } - if (window.HasParent) - { - continue; - } - if ((window.ExtendedWindowStyle & ExtendedWindowStyleFlags.WS_EX_TOOLWINDOW) != 0) - { - continue; - } - // Skip preview windows, like the one from Firefox - if ((window.WindowStyle & WindowStyleFlags.WS_VISIBLE) == 0) - { - continue; - } - if (!window.Visible && !window.Iconic) - { - continue; - } - windows.Add(window); - } - return windows; - } - - /// - /// Find a window belonging to the same process as the supplied window. - /// - /// - /// - public static WindowDetails GetLinkedWindow(WindowDetails windowToLinkTo) - { - int processIdSelectedWindow = windowToLinkTo.ProcessId; - foreach (WindowDetails window in GetAllWindows()) - { - // Ignore windows without title - if (window.Text.Length == 0) - { - continue; - } - // Ignore invisible - if (!window.Visible) - { - continue; - } - if (window.Handle == windowToLinkTo.Handle) - { - continue; - } - if (window.Iconic) - { - continue; - } - - // Windows without size - Size windowSize = window.WindowRectangle.Size; - if (windowSize.Width == 0 || windowSize.Height == 0) - { - continue; - } - - if (window.ProcessId == processIdSelectedWindow) - { - LOG.InfoFormat("Found window {0} belonging to same process as the window {1}", window.Text, windowToLinkTo.Text); - return window; - } - } - return null; - } - - /// - /// Helper method to "active" all windows that are not in the supplied list. - /// One should preferably call "GetVisibleWindows" for the oldWindows. - /// - /// List WindowDetails with old windows - public static void ActiveNewerWindows(List oldWindows) - { - List windowsAfter = GetVisibleWindows(); - foreach (WindowDetails window in windowsAfter) - { - if (!oldWindows.Contains(window)) - { - window.ToForeground(); - } - } - } - - /// - /// Get the AppLauncher - /// - /// - public static WindowDetails GetAppLauncher() - { - // Only if Windows 8 (or higher) - if (appVisibility == null) - { - return null; - } - IntPtr appLauncher = User32.FindWindow(METRO_APPLAUNCHER_CLASS, null); - if (appLauncher != IntPtr.Zero) - { - return new WindowDetails(appLauncher); - } - return null; - } - - /// - /// Return true if the metro-app-launcher is visible - /// - /// - public static bool IsAppLauncherVisible - { - get - { - if (appVisibility != null) - { - return appVisibility.IsLauncherVisible; - } - return false; - } - } - } - - #endregion WindowDetails -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/ArrowContainer.cs b/Greenshot.ImageEditor/Drawing/ArrowContainer.cs deleted file mode 100644 index 72818108c..000000000 --- a/Greenshot.ImageEditor/Drawing/ArrowContainer.cs +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Drawing.Fields; -using Greenshot.Plugin.Drawing; -using System; -using System.Drawing; -using System.Drawing.Drawing2D; - -namespace Greenshot.Drawing -{ - /// - /// Description of LineContainer. - /// - [Serializable()] - public class ArrowContainer : LineContainer - { - public enum ArrowHeadCombination { NONE, START_POINT, END_POINT, BOTH }; - - private static readonly AdjustableArrowCap ARROW_CAP = new AdjustableArrowCap(4, 6); - - public ArrowContainer(Surface parent) : base(parent) - { - } - - /// - /// Do not use the base, just override so we have our own defaults - /// - protected override void InitializeFields() - { - AddField(GetType(), FieldType.LINE_THICKNESS, 2); - AddField(GetType(), FieldType.ARROWHEADS, 2); - AddField(GetType(), FieldType.LINE_COLOR, DefaultLineColor); - AddField(GetType(), FieldType.FILL_COLOR, Color.Transparent); - AddField(GetType(), FieldType.SHADOW, true); - AddField(GetType(), FieldType.ARROWHEADS, ArrowHeadCombination.END_POINT); - } - - public override void Draw(Graphics graphics, RenderMode rm) - { - int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); - bool shadow = GetFieldValueAsBool(FieldType.SHADOW); - - if (lineThickness > 0) - { - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.PixelOffsetMode = PixelOffsetMode.None; - Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR); - ArrowHeadCombination heads = (ArrowHeadCombination)GetFieldValue(FieldType.ARROWHEADS); - if (shadow) - { - //draw shadow first - int basealpha = 100; - int alpha = basealpha; - int steps = 5; - int currentStep = 1; - while (currentStep <= steps) - { - using (Pen shadowCapPen = new Pen(Color.FromArgb(alpha, 100, 100, 100), lineThickness)) - { - SetArrowHeads(heads, shadowCapPen); - - graphics.DrawLine(shadowCapPen, - Left + currentStep, - Top + currentStep, - Left + currentStep + Width, - Top + currentStep + Height); - - currentStep++; - alpha = alpha - basealpha / steps; - } - } - } - using (Pen pen = new Pen(lineColor, lineThickness)) - { - SetArrowHeads(heads, pen); - graphics.DrawLine(pen, Left, Top, Left + Width, Top + Height); - } - } - } - - private void SetArrowHeads(ArrowHeadCombination heads, Pen pen) - { - if (heads == ArrowHeadCombination.BOTH || heads == ArrowHeadCombination.START_POINT) - { - pen.CustomStartCap = ARROW_CAP; - } - if (heads == ArrowHeadCombination.BOTH || heads == ArrowHeadCombination.END_POINT) - { - pen.CustomEndCap = ARROW_CAP; - } - } - - public override Rectangle DrawingBounds - { - get - { - int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); - if (lineThickness > 0) - { - using (Pen pen = new Pen(Color.White)) - { - pen.Width = lineThickness; - SetArrowHeads((ArrowHeadCombination)GetFieldValue(FieldType.ARROWHEADS), pen); - using (GraphicsPath path = new GraphicsPath()) - { - path.AddLine(Left, Top, Left + Width, Top + Height); - using (Matrix matrix = new Matrix()) - { - Rectangle drawingBounds = Rectangle.Round(path.GetBounds(matrix, pen)); - drawingBounds.Inflate(2, 2); - return drawingBounds; - } - } - } - } - return Rectangle.Empty; - } - } - - public override bool ClickableAt(int x, int y) - { - int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS) + 10; - if (lineThickness > 0) - { - using (Pen pen = new Pen(Color.White)) - { - pen.Width = lineThickness; - SetArrowHeads((ArrowHeadCombination)GetFieldValue(FieldType.ARROWHEADS), pen); - using (GraphicsPath path = new GraphicsPath()) - { - path.AddLine(Left, Top, Left + Width, Top + Height); - return path.IsOutlineVisible(x, y, pen); - } - } - } - return false; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/CropContainer.cs b/Greenshot.ImageEditor/Drawing/CropContainer.cs deleted file mode 100644 index 9a1ea563c..000000000 --- a/Greenshot.ImageEditor/Drawing/CropContainer.cs +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Drawing.Fields; -using Greenshot.Helpers; -using Greenshot.Plugin.Drawing; -using System.Drawing; - -namespace Greenshot.Drawing -{ - /// - /// Description of CropContainer. - /// - public class CropContainer : DrawableContainer - { - public CropContainer(Surface parent) : base(parent) - { - } - - protected override void InitializeFields() - { - AddField(GetType(), FieldType.FLAGS, FieldType.Flag.CONFIRMABLE); - } - - public override void Invalidate() - { - _parent.Invalidate(); - } - - /// - /// We need to override the DrawingBound, return a rectangle in the size of the image, to make sure this element is always draw - /// (we create a transparent brown over the complete picture) - /// - public override Rectangle DrawingBounds - { - get - { - return new Rectangle(0, 0, _parent.Width, _parent.Height); - } - } - - public override void Draw(Graphics g, RenderMode rm) - { - using (Brush cropBrush = new SolidBrush(Color.FromArgb(100, 150, 150, 100))) - { - Rectangle cropRectangle = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); - Rectangle selectionRect = new Rectangle(cropRectangle.Left - 1, cropRectangle.Top - 1, cropRectangle.Width + 1, cropRectangle.Height + 1); - - DrawSelectionBorder(g, selectionRect); - - // top - g.FillRectangle(cropBrush, new Rectangle(0, 0, _parent.Width, cropRectangle.Top)); - // left - g.FillRectangle(cropBrush, new Rectangle(0, cropRectangle.Top, cropRectangle.Left, cropRectangle.Height)); - // right - g.FillRectangle(cropBrush, new Rectangle(cropRectangle.Left + cropRectangle.Width, cropRectangle.Top, _parent.Width - (cropRectangle.Left + cropRectangle.Width), cropRectangle.Height)); - // bottom - g.FillRectangle(cropBrush, new Rectangle(0, cropRectangle.Top + cropRectangle.Height, _parent.Width, _parent.Height - (cropRectangle.Top + cropRectangle.Height))); - } - } - - public override bool HasContextMenu - { - get - { - // No context menu for the CropContainer - return false; - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/CursorContainer.cs b/Greenshot.ImageEditor/Drawing/CursorContainer.cs deleted file mode 100644 index 68170331b..000000000 --- a/Greenshot.ImageEditor/Drawing/CursorContainer.cs +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Plugin.Drawing; -using GreenshotPlugin; -using System; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.IO; -using System.Windows.Forms; - -namespace Greenshot.Drawing -{ - /// - /// Description of CursorContainer. - /// - [Serializable] - public class CursorContainer : DrawableContainer, ICursorContainer - { - protected Cursor cursor; - - public CursorContainer(Surface parent) : base(parent) - { - } - - public CursorContainer(Surface parent, string filename) : base(parent) - { - Load(filename); - } - - public Cursor Cursor - { - set - { - if (cursor != null) - { - cursor.Dispose(); - } - // Clone cursor (is this correct??) - cursor = new Cursor(value.CopyHandle()); - Width = value.Size.Width; - Height = value.Size.Height; - } - get - { - return cursor; - } - } - - /// - /// This Dispose is called from the Dispose and the Destructor. - /// When disposing==true all non-managed resources should be freed too! - /// - /// - protected override void Dispose(bool disposing) - { - if (disposing) - { - if (cursor != null) - { - cursor.Dispose(); - } - } - cursor = null; - base.Dispose(disposing); - } - - public void Load(string filename) - { - if (!File.Exists(filename)) - { - return; - } - using (Cursor fileCursor = new Cursor(filename)) - { - Cursor = fileCursor; - LOG.Debug("Loaded file: " + filename + " with resolution: " + Height + "," + Width); - } - } - - public override void Draw(Graphics graphics, RenderMode rm) - { - if (cursor == null) - { - return; - } - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.InterpolationMode = InterpolationMode.NearestNeighbor; - graphics.CompositingQuality = CompositingQuality.Default; - graphics.PixelOffsetMode = PixelOffsetMode.None; - cursor.DrawStretched(graphics, Bounds); - } - - public override Size DefaultSize - { - get - { - return cursor.Size; - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/DrawableContainer.cs b/Greenshot.ImageEditor/Drawing/DrawableContainer.cs deleted file mode 100644 index a17fa54bb..000000000 --- a/Greenshot.ImageEditor/Drawing/DrawableContainer.cs +++ /dev/null @@ -1,1021 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Configuration; -using Greenshot.Drawing.Fields; -using Greenshot.Drawing.Filters; -using Greenshot.Helpers; -using Greenshot.IniFile; -using Greenshot.Memento; -using Greenshot.Plugin; -using Greenshot.Plugin.Drawing; -using GreenshotPlugin; -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Windows.Forms; - -namespace Greenshot.Drawing -{ - /// - /// represents a rectangle, ellipse, label or whatever. Can contain filters, too. - /// serializable for clipboard support - /// Subclasses should fulfill INotifyPropertyChanged contract, i.e. call - /// OnPropertyChanged whenever a public property has been changed. - /// - [Serializable] - public abstract class DrawableContainer : AbstractFieldHolderWithChildren, IDrawableContainer - { - protected static readonly EditorConfiguration EditorConfig = IniConfig.GetIniSection(); - - protected static readonly Color DefaultLineColor = Color.FromArgb(0, 150, 255); - - private bool _isMadeUndoable; - private const int M11 = 0; - private const int M22 = 3; - - protected EditStatus _defaultEditMode = EditStatus.DRAWING; - public EditStatus DefaultEditMode - { - get - { - return _defaultEditMode; - } - } - - /// - /// The public accessible Dispose - /// Will call the GarbageCollector to SuppressFinalize, preventing being cleaned twice - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (!disposing) - { - return; - } - if (_grippers != null) - { - for (int i = 0; i < _grippers.Length; i++) - { - if (_grippers[i] == null) - { - continue; - } - _grippers[i].Dispose(); - _grippers[i] = null; - } - _grippers = null; - } - - FieldAggregator aggProps = _parent.FieldAggregator; - aggProps.UnbindElement(this); - } - - ~DrawableContainer() - { - Dispose(false); - } - - [NonSerialized] - private PropertyChangedEventHandler _propertyChanged; - public event PropertyChangedEventHandler PropertyChanged - { - add { _propertyChanged += value; } - remove { _propertyChanged -= value; } - } - - public List Filters - { - get - { - List ret = new List(); - foreach (IFieldHolder c in Children) - { - if (c is IFilter) - { - ret.Add(c as IFilter); - } - } - return ret; - } - } - - [NonSerialized] - internal Surface _parent; - public ISurface Parent - { - get { return _parent; } - set { SwitchParent((Surface)value); } - } - [NonSerialized] - protected Gripper[] _grippers; - private bool layoutSuspended; - - [NonSerialized] - private Gripper _targetGripper; - - public Gripper TargetGripper - { - get - { - return _targetGripper; - } - } - - [NonSerialized] - private bool _selected; - public bool Selected - { - get - { - return _selected; - } - set - { - _selected = value; - OnPropertyChanged("Selected"); - } - } - - [NonSerialized] - private EditStatus _status = EditStatus.UNDRAWN; - public EditStatus Status - { - get - { - return _status; - } - set - { - _status = value; - } - } - - private int left; - public int Left - { - get - { - return left; - } - set - { - if (value == left) - { - return; - } - left = value; - DoLayout(); - } - } - - private int top; - public int Top - { - get - { - return top; - } - set - { - if (value == top) - { - return; - } - top = value; - DoLayout(); - } - } - - private int width; - public int Width - { - get - { - return width; - } - set - { - if (value == width) - { - return; - } - width = value; - DoLayout(); - } - } - - private int height; - public int Height - { - get - { - return height; - } - set - { - if (value == height) - { - return; - } - height = value; - DoLayout(); - } - } - - public Point Location - { - get - { - return new Point(left, top); - } - set - { - left = value.X; - top = value.Y; - } - } - - public Size Size - { - get - { - return new Size(width, height); - } - set - { - width = value.Width; - height = value.Height; - } - } - - [NonSerialized] - // will store current bounds of this DrawableContainer before starting a resize - protected Rectangle _boundsBeforeResize = Rectangle.Empty; - - [NonSerialized] - // "workbench" rectangle - used for calculating bounds during resizing (to be applied to this DrawableContainer afterwards) - protected RectangleF _boundsAfterResize = RectangleF.Empty; - - public Rectangle Bounds - { - get - { - return GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); - } - set - { - Left = Round(value.Left); - Top = Round(value.Top); - Width = Round(value.Width); - Height = Round(value.Height); - } - } - - public virtual void ApplyBounds(RectangleF newBounds) - { - Left = Round(newBounds.Left); - Top = Round(newBounds.Top); - Width = Round(newBounds.Width); - Height = Round(newBounds.Height); - } - - public DrawableContainer(Surface parent) - { - InitializeFields(); - _parent = parent; - InitControls(); - } - - public void Add(IFilter filter) - { - AddChild(filter); - } - - public void Remove(IFilter filter) - { - RemoveChild(filter); - } - - private static int Round(float f) - { - if (float.IsPositiveInfinity(f) || f > int.MaxValue / 2) return int.MaxValue / 2; - if (float.IsNegativeInfinity(f) || f < int.MinValue / 2) return int.MinValue / 2; - return (int)Math.Round(f); - } - - private bool accountForShadowChange; - public virtual Rectangle DrawingBounds - { - get - { - foreach (IFilter filter in Filters) - { - if (filter.Invert) - { - return new Rectangle(Point.Empty, _parent.Image.Size); - } - } - // Take a base safetymargin - int lineThickness = 5; - if (HasField(FieldType.LINE_THICKNESS)) - { - lineThickness += GetFieldValueAsInt(FieldType.LINE_THICKNESS); - } - int offset = lineThickness / 2; - - int shadow = 0; - if (accountForShadowChange || (HasField(FieldType.SHADOW) && GetFieldValueAsBool(FieldType.SHADOW))) - { - accountForShadowChange = false; - shadow += 10; - } - return new Rectangle(Bounds.Left - offset, Bounds.Top - offset, Bounds.Width + lineThickness + shadow, Bounds.Height + lineThickness + shadow); - } - } - - public virtual void Invalidate() - { - if (Status != EditStatus.UNDRAWN) - { - _parent.Invalidate(DrawingBounds); - } - } - - public void AlignToParent(HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment) - { - int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); - if (horizontalAlignment == HorizontalAlignment.Left) - { - Left = lineThickness / 2; - } - if (horizontalAlignment == HorizontalAlignment.Right) - { - Left = _parent.Width - Width - lineThickness / 2; - } - if (horizontalAlignment == HorizontalAlignment.Center) - { - Left = _parent.Width / 2 - Width / 2 - lineThickness / 2; - } - - if (verticalAlignment == VerticalAlignment.TOP) - { - Top = lineThickness / 2; - } - if (verticalAlignment == VerticalAlignment.BOTTOM) - { - Top = _parent.Height - Height - lineThickness / 2; - } - if (verticalAlignment == VerticalAlignment.CENTER) - { - Top = _parent.Height / 2 - Height / 2 - lineThickness / 2; - } - } - - public virtual bool InitContent() - { - return true; - } - - public virtual void OnDoubleClick() - { - } - - private void InitControls() - { - InitGrippers(); - - DoLayout(); - } - - /// - /// Move the TargetGripper around, confined to the surface to solve BUG-1682 - /// - /// - /// - protected virtual void TargetGripperMove(int newX, int newY) - { - Point newGripperLocation = new Point(newX, newY); - Rectangle surfaceBounds = new Rectangle(0, 0, _parent.Width, _parent.Height); - // Check if gripper inside the parent (surface), if not we need to move it inside - // This was made for BUG-1682 - if (!surfaceBounds.Contains(newGripperLocation)) - { - if (newGripperLocation.X > surfaceBounds.Right) - { - newGripperLocation.X = surfaceBounds.Right - 5; - } - if (newGripperLocation.X < surfaceBounds.Left) - { - newGripperLocation.X = surfaceBounds.Left; - } - if (newGripperLocation.Y > surfaceBounds.Bottom) - { - newGripperLocation.Y = surfaceBounds.Bottom - 5; - } - if (newGripperLocation.Y < surfaceBounds.Top) - { - newGripperLocation.Y = surfaceBounds.Top; - } - } - - _targetGripper.Left = newGripperLocation.X; - _targetGripper.Top = newGripperLocation.Y; - } - - /// - /// Initialize a target gripper - /// - protected void InitTargetGripper(Color gripperColor, Point location) - { - _targetGripper = new Gripper - { - Cursor = Cursors.SizeAll, - BackColor = gripperColor, - Visible = false, - Parent = _parent, - Location = location - }; - _targetGripper.MouseDown += GripperMouseDown; - _targetGripper.MouseUp += GripperMouseUp; - _targetGripper.MouseMove += GripperMouseMove; - if (_parent != null) - { - _parent.Controls.Add(_targetGripper); // otherwise we'll attach them in switchParent - } - } - - protected void InitGrippers() - { - _grippers = new Gripper[8]; - for (int i = 0; i < _grippers.Length; i++) - { - _grippers[i] = new Gripper(); - _grippers[i].Position = i; - _grippers[i].MouseDown += GripperMouseDown; - _grippers[i].MouseUp += GripperMouseUp; - _grippers[i].MouseMove += GripperMouseMove; - _grippers[i].Visible = false; - _grippers[i].Parent = _parent; - } - _grippers[Gripper.POSITION_TOP_CENTER].Cursor = Cursors.SizeNS; - _grippers[Gripper.POSITION_MIDDLE_RIGHT].Cursor = Cursors.SizeWE; - _grippers[Gripper.POSITION_BOTTOM_CENTER].Cursor = Cursors.SizeNS; - _grippers[Gripper.POSITION_MIDDLE_LEFT].Cursor = Cursors.SizeWE; - if (_parent != null) - { - _parent.Controls.AddRange(_grippers); // otherwise we'll attach them in switchParent - } - } - - public void SuspendLayout() - { - layoutSuspended = true; - } - - public void ResumeLayout() - { - layoutSuspended = false; - DoLayout(); - } - - protected virtual void DoLayout() - { - if (_grippers == null) - { - return; - } - if (!layoutSuspended) - { - int[] xChoords = { Left - 2, Left + Width / 2 - 2, Left + Width - 2 }; - int[] yChoords = { Top - 2, Top + Height / 2 - 2, Top + Height - 2 }; - - _grippers[Gripper.POSITION_TOP_LEFT].Left = xChoords[0]; _grippers[Gripper.POSITION_TOP_LEFT].Top = yChoords[0]; - _grippers[Gripper.POSITION_TOP_CENTER].Left = xChoords[1]; _grippers[Gripper.POSITION_TOP_CENTER].Top = yChoords[0]; - _grippers[Gripper.POSITION_TOP_RIGHT].Left = xChoords[2]; _grippers[Gripper.POSITION_TOP_RIGHT].Top = yChoords[0]; - _grippers[Gripper.POSITION_MIDDLE_RIGHT].Left = xChoords[2]; _grippers[Gripper.POSITION_MIDDLE_RIGHT].Top = yChoords[1]; - _grippers[Gripper.POSITION_BOTTOM_RIGHT].Left = xChoords[2]; _grippers[Gripper.POSITION_BOTTOM_RIGHT].Top = yChoords[2]; - _grippers[Gripper.POSITION_BOTTOM_CENTER].Left = xChoords[1]; _grippers[Gripper.POSITION_BOTTOM_CENTER].Top = yChoords[2]; - _grippers[Gripper.POSITION_BOTTOM_LEFT].Left = xChoords[0]; _grippers[Gripper.POSITION_BOTTOM_LEFT].Top = yChoords[2]; - _grippers[Gripper.POSITION_MIDDLE_LEFT].Left = xChoords[0]; _grippers[Gripper.POSITION_MIDDLE_LEFT].Top = yChoords[1]; - - if ((_grippers[Gripper.POSITION_TOP_LEFT].Left < _grippers[Gripper.POSITION_BOTTOM_RIGHT].Left && _grippers[Gripper.POSITION_TOP_LEFT].Top < _grippers[Gripper.POSITION_BOTTOM_RIGHT].Top) || - _grippers[Gripper.POSITION_TOP_LEFT].Left > _grippers[Gripper.POSITION_BOTTOM_RIGHT].Left && _grippers[Gripper.POSITION_TOP_LEFT].Top > _grippers[Gripper.POSITION_BOTTOM_RIGHT].Top) - { - _grippers[Gripper.POSITION_TOP_LEFT].Cursor = Cursors.SizeNWSE; - _grippers[Gripper.POSITION_TOP_RIGHT].Cursor = Cursors.SizeNESW; - _grippers[Gripper.POSITION_BOTTOM_RIGHT].Cursor = Cursors.SizeNWSE; - _grippers[Gripper.POSITION_BOTTOM_LEFT].Cursor = Cursors.SizeNESW; - } - else if ((_grippers[Gripper.POSITION_TOP_LEFT].Left > _grippers[Gripper.POSITION_BOTTOM_RIGHT].Left && _grippers[Gripper.POSITION_TOP_LEFT].Top < _grippers[Gripper.POSITION_BOTTOM_RIGHT].Top) || - _grippers[Gripper.POSITION_TOP_LEFT].Left < _grippers[Gripper.POSITION_BOTTOM_RIGHT].Left && _grippers[Gripper.POSITION_TOP_LEFT].Top > _grippers[Gripper.POSITION_BOTTOM_RIGHT].Top) - { - _grippers[Gripper.POSITION_TOP_LEFT].Cursor = Cursors.SizeNESW; - _grippers[Gripper.POSITION_TOP_RIGHT].Cursor = Cursors.SizeNWSE; - _grippers[Gripper.POSITION_BOTTOM_RIGHT].Cursor = Cursors.SizeNESW; - _grippers[Gripper.POSITION_BOTTOM_LEFT].Cursor = Cursors.SizeNWSE; - } - else if (_grippers[Gripper.POSITION_TOP_LEFT].Left == _grippers[Gripper.POSITION_BOTTOM_RIGHT].Left) - { - _grippers[Gripper.POSITION_TOP_LEFT].Cursor = Cursors.SizeNS; - _grippers[Gripper.POSITION_BOTTOM_RIGHT].Cursor = Cursors.SizeNS; - } - else if (_grippers[Gripper.POSITION_TOP_LEFT].Top == _grippers[Gripper.POSITION_BOTTOM_RIGHT].Top) - { - _grippers[Gripper.POSITION_TOP_LEFT].Cursor = Cursors.SizeWE; - _grippers[Gripper.POSITION_BOTTOM_RIGHT].Cursor = Cursors.SizeWE; - } - } - } - - private void GripperMouseDown(object sender, MouseEventArgs e) - { - Gripper originatingGripper = (Gripper)sender; - if (originatingGripper != _targetGripper) - { - Status = EditStatus.RESIZING; - _boundsBeforeResize = new Rectangle(left, top, width, height); - _boundsAfterResize = new RectangleF(_boundsBeforeResize.Left, _boundsBeforeResize.Top, _boundsBeforeResize.Width, _boundsBeforeResize.Height); - } - else - { - Status = EditStatus.MOVING; - } - _isMadeUndoable = false; - } - - private void GripperMouseUp(object sender, MouseEventArgs e) - { - Gripper originatingGripper = (Gripper)sender; - if (originatingGripper != _targetGripper) - { - _boundsBeforeResize = Rectangle.Empty; - _boundsAfterResize = RectangleF.Empty; - _isMadeUndoable = false; - } - Status = EditStatus.IDLE; - Invalidate(); - } - - private void GripperMouseMove(object sender, MouseEventArgs e) - { - Invalidate(); - Gripper originatingGripper = (Gripper)sender; - int absX = originatingGripper.Left + e.X; - int absY = originatingGripper.Top + e.Y; - if (originatingGripper == _targetGripper && Status.Equals(EditStatus.MOVING)) - { - TargetGripperMove(absX, absY); - } - else if (Status.Equals(EditStatus.RESIZING)) - { - // check if we already made this undoable - if (!_isMadeUndoable) - { - // don't allow another undo until we are finished with this move - _isMadeUndoable = true; - // Make undo-able - MakeBoundsChangeUndoable(false); - } - - SuspendLayout(); - - // reset "workbench" rectangle to current bounds - _boundsAfterResize.X = _boundsBeforeResize.X; - _boundsAfterResize.Y = _boundsBeforeResize.Y; - _boundsAfterResize.Width = _boundsBeforeResize.Width; - _boundsAfterResize.Height = _boundsBeforeResize.Height; - - // calculate scaled rectangle - ScaleHelper.Scale(ref _boundsAfterResize, originatingGripper.Position, new PointF(absX, absY), ScaleHelper.GetScaleOptions()); - - // apply scaled bounds to this DrawableContainer - ApplyBounds(_boundsAfterResize); - - ResumeLayout(); - } - Invalidate(); - } - - public bool hasFilters - { - get - { - return Filters.Count > 0; - } - } - - public abstract void Draw(Graphics graphics, RenderMode renderMode); - - public virtual void DrawContent(Graphics graphics, Bitmap bmp, RenderMode renderMode, Rectangle clipRectangle) - { - if (Children.Count > 0) - { - if (Status != EditStatus.IDLE) - { - DrawSelectionBorder(graphics, Bounds); - } - else - { - if (clipRectangle.Width != 0 && clipRectangle.Height != 0) - { - foreach (IFilter filter in Filters) - { - if (filter.Invert) - { - filter.Apply(graphics, bmp, Bounds, renderMode); - } - else - { - Rectangle drawingRect = new Rectangle(Bounds.Location, Bounds.Size); - drawingRect.Intersect(clipRectangle); - if (filter is MagnifierFilter) - { - // quick&dirty bugfix, because MagnifierFilter behaves differently when drawn only partially - // what we should actually do to resolve this is add a better magnifier which is not that special - filter.Apply(graphics, bmp, Bounds, renderMode); - } - else - { - filter.Apply(graphics, bmp, drawingRect, renderMode); - } - } - } - } - } - } - Draw(graphics, renderMode); - } - - public virtual bool Contains(int x, int y) - { - return Bounds.Contains(x, y); - } - - public virtual bool ClickableAt(int x, int y) - { - Rectangle r = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); - r.Inflate(5, 5); - return r.Contains(x, y); - } - - protected void DrawSelectionBorder(Graphics g, Rectangle rect) - { - using (Pen pen = new Pen(Color.MediumSeaGreen)) - { - pen.DashPattern = new float[] { 1, 2 }; - pen.Width = 1; - g.DrawRectangle(pen, rect); - } - } - - public virtual void ShowGrippers() - { - if (_grippers != null) - { - for (int i = 0; i < _grippers.Length; i++) - { - if (_grippers[i].Enabled) - { - _grippers[i].Show(); - } - else - { - _grippers[i].Hide(); - } - } - } - if (_targetGripper != null) - { - if (_targetGripper.Enabled) - { - _targetGripper.Show(); - } - else - { - _targetGripper.Hide(); - } - } - ResumeLayout(); - } - - public virtual void HideGrippers() - { - SuspendLayout(); - if (_grippers != null) - { - for (int i = 0; i < _grippers.Length; i++) - { - _grippers[i].Hide(); - } - } - if (_targetGripper != null) - { - _targetGripper.Hide(); - } - } - - public void ResizeTo(int width, int height, int anchorPosition) - { - SuspendLayout(); - Width = width; - Height = height; - ResumeLayout(); - } - - /// - /// Make a following bounds change on this drawablecontainer undoable! - /// - /// true means allow the moves to be merged - public void MakeBoundsChangeUndoable(bool allowMerge) - { - _parent.MakeUndoable(new DrawableContainerBoundsChangeMemento(this), allowMerge); - } - - public void MoveBy(int dx, int dy) - { - SuspendLayout(); - Left += dx; - Top += dy; - ResumeLayout(); - } - - /// - /// A handler for the MouseDown, used if you don't want the surface to handle this for you - /// - /// current mouse x - /// current mouse y - /// true if the event is handled, false if the surface needs to handle it - public virtual bool HandleMouseDown(int x, int y) - { - Left = _boundsBeforeResize.X = x; - Top = _boundsBeforeResize.Y = y; - return true; - } - - /// - /// A handler for the MouseMove, used if you don't want the surface to handle this for you - /// - /// current mouse x - /// current mouse y - /// true if the event is handled, false if the surface needs to handle it - public virtual bool HandleMouseMove(int x, int y) - { - Invalidate(); - SuspendLayout(); - - // reset "workrbench" rectangle to current bounds - _boundsAfterResize.X = _boundsBeforeResize.Left; - _boundsAfterResize.Y = _boundsBeforeResize.Top; - _boundsAfterResize.Width = x - _boundsAfterResize.Left; - _boundsAfterResize.Height = y - _boundsAfterResize.Top; - - ScaleHelper.Scale(_boundsBeforeResize, x, y, ref _boundsAfterResize, GetAngleRoundProcessor()); - - // apply scaled bounds to this DrawableContainer - ApplyBounds(_boundsAfterResize); - - ResumeLayout(); - Invalidate(); - return true; - } - - /// - /// A handler for the MouseUp - /// - /// current mouse x - /// current mouse y - public virtual void HandleMouseUp(int x, int y) - { - } - - protected virtual void SwitchParent(Surface newParent) - { - // Target gripper - if (_parent != null && _targetGripper != null) - { - _parent.Controls.Remove(_targetGripper); - } - // Normal grippers - if (_parent != null && _grippers != null) - { - for (int i = 0; i < _grippers.Length; i++) - { - _parent.Controls.Remove(_grippers[i]); - } - } - else if (_grippers == null) - { - InitControls(); - } - _parent = newParent; - // Target gripper - if (_parent != null && _targetGripper != null) - { - _parent.Controls.Add(_targetGripper); - } - // Normal grippers - if (_parent != null && _grippers != null) - { - _parent.Controls.AddRange(_grippers); - } - - foreach (IFilter filter in Filters) - { - filter.Parent = this; - } - } - - // drawablecontainers are regarded equal if they are of the same type and their bounds are equal. this should be sufficient. - public override bool Equals(object obj) - { - bool ret = false; - if (obj != null && GetType() == obj.GetType()) - { - DrawableContainer other = obj as DrawableContainer; - if (other != null && left == other.left && top == other.top && width == other.width && height == other.height) - { - ret = true; - } - } - return ret; - } - - public override int GetHashCode() - { - // This actually doesn't make sense... - // Place the container in a list, and you can't find it :) - return left.GetHashCode() ^ top.GetHashCode() ^ width.GetHashCode() ^ height.GetHashCode() ^ GetFields().GetHashCode(); - } - - protected void OnPropertyChanged(string propertyName) - { - if (_propertyChanged != null) - { - _propertyChanged(this, new PropertyChangedEventArgs(propertyName)); - Invalidate(); - } - } - - /// - /// This method will be called before a field is changes. - /// Using this makes it possible to invalidate the object as is before changing. - /// - /// The field to be changed - /// The new value - public virtual void BeforeFieldChange(Field fieldToBeChanged, object newValue) - { - _parent.MakeUndoable(new ChangeFieldHolderMemento(this, fieldToBeChanged), true); - Invalidate(); - } - - /// - /// Handle the field changed event, this should invalidate the correct bounds (e.g. when shadow comes or goes more pixels!) - /// - /// - /// - public void HandleFieldChanged(object sender, FieldChangedEventArgs e) - { - LOG.DebugFormat("Field {0} changed", e.Field.FieldType); - if (e.Field.FieldType == FieldType.SHADOW) - { - accountForShadowChange = true; - } - Invalidate(); - } - - /// - /// Retrieve the Y scale from the matrix - /// - /// - /// - public static float CalculateScaleY(Matrix matrix) - { - return matrix.Elements[M22]; - } - - /// - /// Retrieve the X scale from the matrix - /// - /// - /// - public static float CalculateScaleX(Matrix matrix) - { - return matrix.Elements[M11]; - } - - /// - /// Retrieve the rotation angle from the matrix - /// - /// - /// - public static int CalculateAngle(Matrix matrix) - { - const int M11 = 0; - const int M21 = 2; - var radians = Math.Atan2(matrix.Elements[M21], matrix.Elements[M11]); - return (int)-Math.Round(radians * 180 / Math.PI); - } - - /// - /// This method is called on a DrawableContainers when: - /// 1) The capture on the surface is modified in such a way, that the elements would not be placed correctly. - /// 2) Currently not implemented: an element needs to be moved, scaled or rotated. - /// This basis implementation makes sure the coordinates of the element, including the TargetGripper, is correctly rotated/scaled/translated. - /// But this implementation doesn't take care of any changes to the content!! - /// - /// - public virtual void Transform(Matrix matrix) - { - if (matrix == null) - { - return; - } - SuspendLayout(); - Point topLeft = new Point(Left, Top); - Point bottomRight = new Point(Left + Width, Top + Height); - Point[] points; - if (TargetGripper != null) - { - points = new[] { topLeft, bottomRight, TargetGripper.Location }; - } - else - { - points = new[] { topLeft, bottomRight }; - } - matrix.TransformPoints(points); - - Left = points[0].X; - Top = points[0].Y; - Width = points[1].X - points[0].X; - Height = points[1].Y - points[0].Y; - if (TargetGripper != null) - { - TargetGripper.Location = points[points.Length - 1]; - } - ResumeLayout(); - } - - protected virtual ScaleHelper.IDoubleProcessor GetAngleRoundProcessor() - { - return ScaleHelper.ShapeAngleRoundBehavior.Instance; - } - - public virtual bool HasContextMenu - { - get - { - return true; - } - } - - public virtual bool HasDefaultSize - { - get - { - return false; - } - } - - public virtual Size DefaultSize - { - get - { - throw new NotSupportedException("Object doesn't have a default size"); - } - } - - /// - /// Allows to override the initializing of the fields, so we can actually have our own defaults - /// - protected virtual void InitializeFields() - { - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/DrawableContainerList.cs b/Greenshot.ImageEditor/Drawing/DrawableContainerList.cs deleted file mode 100644 index 96727d200..000000000 --- a/Greenshot.ImageEditor/Drawing/DrawableContainerList.cs +++ /dev/null @@ -1,673 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Drawing.Fields; -using Greenshot.Memento; -using Greenshot.Plugin; -using Greenshot.Plugin.Drawing; -using GreenshotPlugin.Core; -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Threading; -using System.Windows.Forms; - -namespace Greenshot.Drawing -{ - /// - /// Dispatches most of a DrawableContainer's public properties and methods to a list of DrawableContainers. - /// - [Serializable] - public class DrawableContainerList : List - { - private static readonly ComponentResourceManager editorFormResources = new ComponentResourceManager(typeof(ImageEditorForm)); - - public Guid ParentID - { - get; - private set; - } - - public DrawableContainerList() - { - } - - public DrawableContainerList(Guid parentID) - { - ParentID = parentID; - } - - public EditStatus Status - { - get - { - return this[Count - 1].Status; - } - set - { - foreach (var dc in this) - { - dc.Status = value; - } - } - } - - public List AsIDrawableContainerList() - { - List interfaceList = new List(); - foreach (IDrawableContainer container in this) - { - interfaceList.Add(container); - } - return interfaceList; - } - - /// - /// Gets or sets the selection status of the elements. - /// If several elements are in the list, true is only returned when all elements are selected. - /// - public bool Selected - { - get - { - bool ret = true; - foreach (var dc in this) - { - ret &= dc.Selected; - } - return ret; - } - set - { - foreach (var dc in this) - { - dc.Selected = value; - } - } - } - - /// - /// Gets or sets the parent control of the elements in the list. - /// If there are several elements, the parent control of the last added is returned. - /// - public ISurface Parent - { - get - { - if (Count > 0) - { - return this[Count - 1].Parent; - } - return null; - } - set - { - ParentID = value.ID; - foreach (var drawableContainer in this) - { - var dc = (DrawableContainer)drawableContainer; - dc.Parent = value; - } - } - } - - /// - /// Make a following bounds change on this containerlist undoable! - /// - /// true means allow the moves to be merged - public void MakeBoundsChangeUndoable(bool allowMerge) - { - List movingList = new List(); - Surface surface = null; - foreach (DrawableContainer dc in this) - { - movingList.Add(dc); - surface = dc._parent; - } - if (movingList.Count > 0 && surface != null) - { - surface.MakeUndoable(new DrawableContainerBoundsChangeMemento(movingList), allowMerge); - } - } - - /// - /// Apply matrix to all elements - /// - public void Transform(Matrix matrix) - { - // Track modifications - bool modified = false; - Invalidate(); - foreach (var dc in this) - { - dc.Transform(matrix); - modified = true; - } - // Invalidate after - Invalidate(); - // If we moved something, tell the surface it's modified! - if (modified) - { - Parent.Modified = true; - } - } - - /// - /// Moves all elements in the list by the given amount of pixels. - /// - /// pixels to move horizontally - /// pixels to move vertically - public void MoveBy(int dx, int dy) - { - // Track modifications - bool modified = false; - - // Invalidate before moving, otherwise the old locations aren't refreshed - Invalidate(); - foreach (var dc in this) - { - dc.Left += dx; - dc.Top += dy; - modified = true; - } - // Invalidate after - Invalidate(); - - // If we moved something, tell the surface it's modified! - if (modified) - { - Parent.Modified = true; - } - } - - /// - /// Hides the grippers of all elements in the list. - /// - public void HideGrippers() - { - foreach (var dc in this) - { - dc.HideGrippers(); - dc.Invalidate(); - } - } - - /// - /// Shows the grippers of all elements in the list. - /// - public void ShowGrippers() - { - foreach (var dc in this) - { - dc.ShowGrippers(); - dc.Invalidate(); - } - } - - /// - /// Indicates whether on of the elements is clickable at the given location - /// - /// x coordinate to be checked - /// y coordinate to be checked - /// true if one of the elements in the list is clickable at the given location, false otherwise - public bool ClickableAt(int x, int y) - { - bool ret = false; - foreach (var dc in this) - { - ret |= dc.ClickableAt(x, y); - } - return ret; - } - - /// - /// retrieves the topmost element being clickable at the given location - /// - /// x coordinate to be checked - /// y coordinate to be checked - /// the topmost element from the list being clickable at the given location, null if there is no clickable element - public IDrawableContainer ClickableElementAt(int x, int y) - { - for (int i = Count - 1; i >= 0; i--) - { - if (this[i].ClickableAt(x, y)) - { - return this[i]; - } - } - return null; - } - - /// - /// Dispatches OnDoubleClick to all elements in the list. - /// - public void OnDoubleClick() - { - foreach (var drawableContainer in this) - { - var dc = (DrawableContainer)drawableContainer; - dc.OnDoubleClick(); - } - } - - /// - /// Check if there are any intersecting filters, if so we need to redraw more - /// - /// - /// true if an filter intersects - public bool HasIntersectingFilters(Rectangle clipRectangle) - { - foreach (var dc in this) - { - if (dc.DrawingBounds.IntersectsWith(clipRectangle) && dc.hasFilters && dc.Status == EditStatus.IDLE) - { - return true; - } - } - return false; - } - - /// - /// Check if any of the drawableContainers are inside the rectangle - /// - /// - /// - public bool IntersectsWith(Rectangle clipRectangle) - { - foreach (var dc in this) - { - if (dc.DrawingBounds.IntersectsWith(clipRectangle)) - { - return true; - } - } - return false; - } - - /// - /// Triggers all elements in the list ot be redrawn. - /// - /// the to the bitmap related Graphics object - /// Bitmap to draw - /// the rendermode in which the element is to be drawn - /// - public void Draw(Graphics g, Bitmap bitmap, RenderMode renderMode, Rectangle clipRectangle) - { - foreach (var drawableContainer in this) - { - var dc = (DrawableContainer)drawableContainer; - if (dc.DrawingBounds.IntersectsWith(clipRectangle)) - { - dc.DrawContent(g, bitmap, renderMode, clipRectangle); - } - } - } - - /// - /// Pass the field changed event to all elements in the list - /// - /// - /// - public void HandleFieldChangedEvent(object sender, FieldChangedEventArgs e) - { - foreach (var drawableContainer in this) - { - var dc = (DrawableContainer)drawableContainer; - dc.HandleFieldChanged(sender, e); - } - } - - /// - /// Invalidate the bounds of all the DC's in this list - /// - public void Invalidate() - { - foreach (var dc in this) - { - dc.Invalidate(); - } - } - - /// - /// Indicates whether the given list of elements can be pulled up, - /// i.e. whether there is at least one unselected element higher in hierarchy - /// - /// list of elements to pull up - /// true if the elements could be pulled up - public bool CanPullUp(DrawableContainerList elements) - { - if (elements.Count == 0 || elements.Count == Count) - { - return false; - } - foreach (var element in elements) - { - if (IndexOf(element) < Count - elements.Count) - { - return true; - } - } - return false; - } - - /// - /// Pulls one or several elements up one level in hierarchy (z-index). - /// - /// list of elements to pull up - public void PullElementsUp(DrawableContainerList elements) - { - for (int i = Count - 1; i >= 0; i--) - { - var dc = this[i]; - if (!elements.Contains(dc)) - { - continue; - } - if (Count > i + 1 && !elements.Contains(this[i + 1])) - { - SwapElements(i, i + 1); - } - } - } - - /// - /// Pulls one or several elements up to the topmost level(s) in hierarchy (z-index). - /// - /// of elements to pull to top - public void PullElementsToTop(DrawableContainerList elements) - { - var dcs = ToArray(); - for (int i = 0; i < dcs.Length; i++) - { - var dc = dcs[i]; - if (!elements.Contains(dc)) - { - continue; - } - Remove(dc); - Add(dc); - Parent.Modified = true; - } - } - - /// - /// Indicates whether the given list of elements can be pushed down, - /// i.e. whether there is at least one unselected element lower in hierarchy - /// - /// list of elements to push down - /// true if the elements could be pushed down - public bool CanPushDown(DrawableContainerList elements) - { - if (elements.Count == 0 || elements.Count == Count) - { - return false; - } - foreach (var element in elements) - { - if (IndexOf(element) >= elements.Count) - { - return true; - } - } - return false; - } - - /// - /// Pushes one or several elements down one level in hierarchy (z-index). - /// - /// list of elements to push down - public void PushElementsDown(DrawableContainerList elements) - { - for (int i = 0; i < Count; i++) - { - var dc = this[i]; - if (!elements.Contains(dc)) - { - continue; - } - if ((i > 0) && !elements.Contains(this[i - 1])) - { - SwapElements(i, i - 1); - } - } - } - - /// - /// Pushes one or several elements down to the bottommost level(s) in hierarchy (z-index). - /// - /// of elements to push to bottom - public void PushElementsToBottom(DrawableContainerList elements) - { - var dcs = ToArray(); - for (int i = dcs.Length - 1; i >= 0; i--) - { - var dc = dcs[i]; - if (!elements.Contains(dc)) - { - continue; - } - Remove(dc); - Insert(0, dc); - Parent.Modified = true; - } - } - - /// - /// swaps two elements in hierarchy (z-index), - /// checks both indices to be in range - /// - /// index of the 1st element - /// index of the 2nd element - private void SwapElements(int index1, int index2) - { - if (index1 < 0 || index1 >= Count || index2 < 0 || index2 >= Count || index1 == index2) - { - return; - } - var dc = this[index1]; - this[index1] = this[index2]; - this[index2] = dc; - Parent.Modified = true; - } - - /// - /// Add items to a context menu for the selected item - /// - /// - /// - public virtual void AddContextMenuItems(ContextMenuStrip menu, Surface surface) - { - bool push = surface.Elements.CanPushDown(this); - bool pull = surface.Elements.CanPullUp(this); - - ToolStripMenuItem item; - - // Pull "up" - if (pull) - { - item = new ToolStripMenuItem("Up to top"); - item.Click += delegate - { - surface.Elements.PullElementsToTop(this); - surface.Elements.Invalidate(); - }; - menu.Items.Add(item); - item = new ToolStripMenuItem("Up one level"); - item.Click += delegate - { - surface.Elements.PullElementsUp(this); - surface.Elements.Invalidate(); - }; - menu.Items.Add(item); - } - // Push "down" - if (push) - { - item = new ToolStripMenuItem("Down to bottom"); - item.Click += delegate - { - surface.Elements.PushElementsToBottom(this); - surface.Elements.Invalidate(); - }; - menu.Items.Add(item); - item = new ToolStripMenuItem("Down one level"); - item.Click += delegate - { - surface.Elements.PushElementsDown(this); - surface.Elements.Invalidate(); - }; - menu.Items.Add(item); - } - - // Duplicate - item = new ToolStripMenuItem("Duplicate selected element"); - item.Click += delegate - { - DrawableContainerList dcs = this.Clone(); - dcs.Parent = surface; - dcs.MoveBy(10, 10); - surface.AddElements(dcs); - surface.DeselectAllElements(); - surface.SelectElements(dcs); - }; - menu.Items.Add(item); - - // Copy - item = new ToolStripMenuItem("Copy"); - item.Image = (Image)editorFormResources.GetObject("copyToolStripMenuItem.Image"); - item.Click += delegate - { - ClipboardHelper.SetClipboardData(typeof(DrawableContainerList), this); - }; - menu.Items.Add(item); - - // Cut - item = new ToolStripMenuItem("Cut"); - item.Image = (Image)editorFormResources.GetObject("btnCut.Image"); - item.Click += delegate - { - ClipboardHelper.SetClipboardData(typeof(DrawableContainerList), this); - List containersToDelete = new List(); - foreach (var drawableContainer in this) - { - var container = (DrawableContainer)drawableContainer; - containersToDelete.Add(container); - } - foreach (var container in containersToDelete) - { - surface.RemoveElement(container, true); - } - }; - menu.Items.Add(item); - - // Delete - item = new ToolStripMenuItem("Delete"); - item.Image = (Image)editorFormResources.GetObject("removeObjectToolStripMenuItem.Image"); - item.Click += delegate - { - List containersToDelete = new List(); - foreach (var drawableContainer in this) - { - var container = (DrawableContainer)drawableContainer; - containersToDelete.Add(container); - } - foreach (DrawableContainer container in containersToDelete) - { - surface.RemoveElement(container, true); - } - }; - menu.Items.Add(item); - - // Reset - bool canReset = false; - foreach (var drawableContainer in this) - { - var container = (DrawableContainer)drawableContainer; - if (container.HasDefaultSize) - { - canReset = true; - } - } - if (canReset) - { - item = new ToolStripMenuItem("Reset size"); - //item.Image = ((System.Drawing.Image)(editorFormResources.GetObject("removeObjectToolStripMenuItem.Image"))); - item.Click += delegate - { - foreach (var drawableContainer in this) - { - var container = (DrawableContainer)drawableContainer; - if (!container.HasDefaultSize) - { - continue; - } - Size defaultSize = container.DefaultSize; - container.Invalidate(); - container.MakeBoundsChangeUndoable(false); - container.Width = defaultSize.Width; - container.Height = defaultSize.Height; - container.Invalidate(); - } - }; - menu.Items.Add(item); - } - } - - public virtual void ShowContextMenu(MouseEventArgs e, Surface surface) - { - bool hasMenu = false; - foreach (var drawableContainer in this) - { - var container = (DrawableContainer)drawableContainer; - if (!container.HasContextMenu) - { - continue; - } - hasMenu = true; - break; - } - if (hasMenu) - { - ContextMenuStrip menu = new ContextMenuStrip(); - AddContextMenuItems(menu, surface); - if (menu.Items.Count > 0) - { - menu.Show(surface, e.Location); - while (true) - { - if (menu.Visible) - { - Application.DoEvents(); - Thread.Sleep(100); - } - else - { - menu.Dispose(); - break; - } - } - } - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/EllipseContainer.cs b/Greenshot.ImageEditor/Drawing/EllipseContainer.cs deleted file mode 100644 index 44b1a8d98..000000000 --- a/Greenshot.ImageEditor/Drawing/EllipseContainer.cs +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Drawing.Fields; -using Greenshot.Helpers; -using Greenshot.Plugin.Drawing; -using System; -using System.Drawing; -using System.Drawing.Drawing2D; - -namespace Greenshot.Drawing -{ - /// - /// Description of EllipseContainer. - /// - [Serializable()] - public class EllipseContainer : DrawableContainer - { - public EllipseContainer(Surface parent) : base(parent) - { - } - - protected override void InitializeFields() - { - AddField(GetType(), FieldType.LINE_THICKNESS, 2); - AddField(GetType(), FieldType.LINE_COLOR, DefaultLineColor); - AddField(GetType(), FieldType.FILL_COLOR, Color.Transparent); - AddField(GetType(), FieldType.SHADOW, true); - } - - public override void Draw(Graphics graphics, RenderMode renderMode) - { - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.PixelOffsetMode = PixelOffsetMode.None; - - int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); - Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR); - Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR); - bool shadow = GetFieldValueAsBool(FieldType.SHADOW); - Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); - DrawEllipse(rect, graphics, renderMode, lineThickness, lineColor, fillColor, shadow); - } - - /// - /// This allows another container to draw an ellipse - /// - /// - /// - /// - /// - /// - /// - /// - /// - public static void DrawEllipse(Rectangle rect, Graphics graphics, RenderMode renderMode, int lineThickness, Color lineColor, Color fillColor, bool shadow) - { - bool lineVisible = lineThickness > 0 && Colors.IsVisible(lineColor); - // draw shadow before anything else - if (shadow && (lineVisible || Colors.IsVisible(fillColor))) - { - int basealpha = 100; - int alpha = basealpha; - int steps = 5; - int currentStep = lineVisible ? 1 : 0; - while (currentStep <= steps) - { - using (Pen shadowPen = new Pen(Color.FromArgb(alpha, 100, 100, 100))) - { - shadowPen.Width = lineVisible ? lineThickness : 1; - Rectangle shadowRect = GuiRectangle.GetGuiRectangle(rect.Left + currentStep, rect.Top + currentStep, rect.Width, rect.Height); - graphics.DrawEllipse(shadowPen, shadowRect); - currentStep++; - alpha = alpha - basealpha / steps; - } - } - } - //draw the original shape - if (Colors.IsVisible(fillColor)) - { - using (Brush brush = new SolidBrush(fillColor)) - { - graphics.FillEllipse(brush, rect); - } - } - if (lineVisible) - { - using (Pen pen = new Pen(lineColor, lineThickness)) - { - graphics.DrawEllipse(pen, rect); - } - } - } - - public override bool Contains(int x, int y) - { - return EllipseContains(this, x, y); - } - - /// - /// Allow the code to be used externally - /// - /// - /// - /// - /// - public static bool EllipseContains(DrawableContainer caller, int x, int y) - { - double xDistanceFromCenter = x - (caller.Left + caller.Width / 2); - double yDistanceFromCenter = y - (caller.Top + caller.Height / 2); - // ellipse: x^2/a^2 + y^2/b^2 = 1 - return Math.Pow(xDistanceFromCenter, 2) / Math.Pow(caller.Width / 2, 2) + Math.Pow(yDistanceFromCenter, 2) / Math.Pow(caller.Height / 2, 2) < 1; - } - - public override bool ClickableAt(int x, int y) - { - int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS) + 10; - Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR); - Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); - return EllipseClickableAt(rect, lineThickness, fillColor, x, y); - } - - public static bool EllipseClickableAt(Rectangle rect, int lineThickness, Color fillColor, int x, int y) - { - // If we clicked inside the rectangle and it's visible we are clickable at. - if (!Color.Transparent.Equals(fillColor)) - { - if (rect.Contains(x, y)) - { - return true; - } - } - - // check the rest of the lines - if (lineThickness > 0) - { - using (Pen pen = new Pen(Color.White, lineThickness)) - { - using (GraphicsPath path = new GraphicsPath()) - { - path.AddEllipse(rect); - return path.IsOutlineVisible(x, y, pen); - } - } - } - return false; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/Fields/AbstractFieldHolder.cs b/Greenshot.ImageEditor/Drawing/Fields/AbstractFieldHolder.cs deleted file mode 100644 index dc7ebfdcf..000000000 --- a/Greenshot.ImageEditor/Drawing/Fields/AbstractFieldHolder.cs +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Configuration; -using Greenshot.IniFile; -using GreenshotPlugin; -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Runtime.Serialization; - -namespace Greenshot.Drawing.Fields -{ - /// - /// Basic IFieldHolder implementation, providing access to a set of fields - /// - [Serializable] - public abstract class AbstractFieldHolder : IFieldHolder - { - private static readonly EditorConfiguration editorConfiguration = IniConfig.GetIniSection(); - - /// - /// called when a field's value has changed - /// - [NonSerialized] - private FieldChangedEventHandler fieldChanged; - public event FieldChangedEventHandler FieldChanged - { - add { fieldChanged += value; } - remove { fieldChanged -= value; } - } - - // we keep two Collections of our fields, dictionary for quick access, list for serialization - // this allows us to use default serialization - [NonSerialized] - private Dictionary fieldsByType = new Dictionary(); - private readonly List fields = new List(); - - [OnDeserialized] - private void OnDeserialized(StreamingContext context) - { - fieldsByType = new Dictionary(); - // listen to changing properties - foreach (Field field in fields) - { - field.PropertyChanged += delegate - { - if (fieldChanged != null) - { - fieldChanged(this, new FieldChangedEventArgs(field)); - } - }; - fieldsByType[field.FieldType] = field; - } - } - - public void AddField(Type requestingType, FieldType fieldType, object fieldValue) - { - AddField(editorConfiguration.CreateField(requestingType, fieldType, fieldValue)); - } - - public virtual void AddField(Field field) - { - if (fieldsByType != null && fieldsByType.ContainsKey(field.FieldType)) - { - if (LOG.IsDebugEnabled) - { - LOG.DebugFormat("A field with of type '{0}' already exists in this {1}, will overwrite.", field.FieldType, GetType()); - } - } - - fields.Add(field); - fieldsByType[field.FieldType] = field; - field.PropertyChanged += delegate { if (fieldChanged != null) fieldChanged(this, new FieldChangedEventArgs(field)); }; - } - - public void RemoveField(Field field) - { - fields.Remove(field); - fieldsByType.Remove(field.FieldType); - field.PropertyChanged -= delegate - { - if (fieldChanged != null) - { - fieldChanged(this, new FieldChangedEventArgs(field)); - } - }; - } - - public List GetFields() - { - return fields; - } - - public Field GetField(FieldType fieldType) - { - try - { - return fieldsByType[fieldType]; - } - catch (KeyNotFoundException e) - { - throw new ArgumentException("Field '" + fieldType + "' does not exist in " + GetType(), e); - } - } - - public object GetFieldValue(FieldType fieldType) - { - return GetField(fieldType).Value; - } - - #region convenience methods to save us some casts outside - - public string GetFieldValueAsString(FieldType fieldType) - { - return Convert.ToString(GetFieldValue(fieldType)); - } - - public int GetFieldValueAsInt(FieldType fieldType) - { - return Convert.ToInt32(GetFieldValue(fieldType)); - } - - public decimal GetFieldValueAsDecimal(FieldType fieldType) - { - return Convert.ToDecimal(GetFieldValue(fieldType)); - } - - public double GetFieldValueAsDouble(FieldType fieldType) - { - return Convert.ToDouble(GetFieldValue(fieldType)); - } - - public float GetFieldValueAsFloat(FieldType fieldType) - { - return Convert.ToSingle(GetFieldValue(fieldType)); - } - - public bool GetFieldValueAsBool(FieldType fieldType) - { - return Convert.ToBoolean(GetFieldValue(fieldType)); - } - - public Color GetFieldValueAsColor(FieldType fieldType) - { - return (Color)GetFieldValue(fieldType); - } - - #endregion convenience methods to save us some casts outside - - public bool HasField(FieldType fieldType) - { - return fieldsByType.ContainsKey(fieldType); - } - - public bool HasFieldValue(FieldType fieldType) - { - return HasField(fieldType) && fieldsByType[fieldType].HasValue; - } - - public void SetFieldValue(FieldType fieldType, object value) - { - try - { - fieldsByType[fieldType].Value = value; - } - catch (KeyNotFoundException e) - { - throw new ArgumentException("Field '" + fieldType + "' does not exist in " + GetType(), e); - } - } - - protected void OnFieldChanged(object sender, FieldChangedEventArgs e) - { - if (fieldChanged != null) - { - fieldChanged(sender, e); - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/Fields/AbstractFieldHolderWithChildren.cs b/Greenshot.ImageEditor/Drawing/Fields/AbstractFieldHolderWithChildren.cs deleted file mode 100644 index f8364d4cb..000000000 --- a/Greenshot.ImageEditor/Drawing/Fields/AbstractFieldHolderWithChildren.cs +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace Greenshot.Drawing.Fields -{ - /// - /// Basic IFieldHolderWithChildren implementation. Similar to IFieldHolder, - /// but has a List of children. - /// Field values are passed to and from children as well. - /// - [Serializable()] - public abstract class AbstractFieldHolderWithChildren : AbstractFieldHolder - { - private readonly FieldChangedEventHandler fieldChangedEventHandler; - - [NonSerialized] - private EventHandler childrenChanged; - public event EventHandler ChildrenChanged - { - add { childrenChanged += value; } - remove { childrenChanged -= value; } - } - - public List Children = new List(); - - public AbstractFieldHolderWithChildren() - { - fieldChangedEventHandler = OnFieldChanged; - } - - [OnDeserialized()] - private void OnDeserialized(StreamingContext context) - { - // listen to changing properties - foreach (IFieldHolder fieldHolder in Children) - { - fieldHolder.FieldChanged += fieldChangedEventHandler; - } - if (childrenChanged != null) childrenChanged(this, EventArgs.Empty); - } - - public void AddChild(IFieldHolder fieldHolder) - { - Children.Add(fieldHolder); - fieldHolder.FieldChanged += fieldChangedEventHandler; - if (childrenChanged != null) childrenChanged(this, EventArgs.Empty); - } - - public void RemoveChild(IFieldHolder fieldHolder) - { - Children.Remove(fieldHolder); - fieldHolder.FieldChanged -= fieldChangedEventHandler; - if (childrenChanged != null) childrenChanged(this, EventArgs.Empty); - } - - public new List GetFields() - { - List ret = new List(); - ret.AddRange(base.GetFields()); - foreach (IFieldHolder fh in Children) - { - ret.AddRange(fh.GetFields()); - } - return ret; - } - - public new Field GetField(FieldType fieldType) - { - Field ret = null; - if (base.HasField(fieldType)) - { - ret = base.GetField(fieldType); - } - else - { - foreach (IFieldHolder fh in Children) - { - if (fh.HasField(fieldType)) - { - ret = fh.GetField(fieldType); - break; - } - } - } - if (ret == null) - { - throw new ArgumentException("Field '" + fieldType + "' does not exist in " + GetType()); - } - return ret; - } - - public new bool HasField(FieldType fieldType) - { - bool ret = base.HasField(fieldType); - if (!ret) - { - foreach (IFieldHolder fh in Children) - { - if (fh.HasField(fieldType)) - { - ret = true; - break; - } - } - } - return ret; - } - - public new bool HasFieldValue(FieldType fieldType) - { - Field f = GetField(fieldType); - return f != null && f.HasValue; - } - - public new void SetFieldValue(FieldType fieldType, object value) - { - Field f = GetField(fieldType); - if (f != null) f.Value = value; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/Fields/Binding/AbstractBindingConverter.cs b/Greenshot.ImageEditor/Drawing/Fields/Binding/AbstractBindingConverter.cs deleted file mode 100644 index 77a4ad207..000000000 --- a/Greenshot.ImageEditor/Drawing/Fields/Binding/AbstractBindingConverter.cs +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System; - -namespace Greenshot.Drawing.Fields.Binding -{ - /// - /// Basic IBindingConverter implementation - /// - public abstract class AbstractBindingConverter : IBindingConverter - { - public object convert(object o) - { - if (o == null) - { - return null; - } - if (o is T1) - { - return convert((T1)o); - } - if (o is T2) - { - return convert((T2)o); - } - throw new ArgumentException("Cannot handle argument of type " + o.GetType()); - } - - protected abstract T2 convert(T1 o); - - protected abstract T1 convert(T2 o); - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/Fields/Binding/BidirectionalBinding.cs b/Greenshot.ImageEditor/Drawing/Fields/Binding/BidirectionalBinding.cs deleted file mode 100644 index f5fdcb492..000000000 --- a/Greenshot.ImageEditor/Drawing/Fields/Binding/BidirectionalBinding.cs +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System; -using System.ComponentModel; -using System.Reflection; - -namespace Greenshot.Drawing.Fields.Binding -{ - /// - /// Bidirectional binding of properties of two INotifyPropertyChanged instances. - /// This implementation synchronizes null values, too. If you do not want this - /// behavior (e.g. when binding to a - /// - public class BidirectionalBinding - { - private readonly INotifyPropertyChanged _controlObject; - private readonly INotifyPropertyChanged _fieldObject; - private readonly string _controlPropertyName; - private readonly string _fieldPropertyName; - private bool _updatingControl = false; - private bool _updatingField = false; - private IBindingConverter _converter; - private readonly IBindingValidator _validator; - - /// - /// Whether or not null values are passed on to the other object. - /// - protected bool AllowSynchronizeNull = true; - - /// - /// Bind properties of two objects bidirectionally - /// - /// Object containing 1st property to bind - /// Property of 1st object to bind - /// Object containing 2nd property to bind - /// Property of 2nd object to bind - public BidirectionalBinding(INotifyPropertyChanged controlObject, string controlPropertyName, INotifyPropertyChanged fieldObject, string fieldPropertyName) - { - _controlObject = controlObject; - _fieldObject = fieldObject; - _controlPropertyName = controlPropertyName; - _fieldPropertyName = fieldPropertyName; - - _controlObject.PropertyChanged += ControlPropertyChanged; - _fieldObject.PropertyChanged += FieldPropertyChanged; - } - - /// - /// Bind properties of two objects bidirectionally, converting the values using a converter - /// - /// Object containing 1st property to bind - /// Property of 1st object to bind - /// Object containing 2nd property to bind - /// Property of 2nd object to bind - /// taking care of converting the synchronized value to the correct target format and back - public BidirectionalBinding(INotifyPropertyChanged controlObject, string controlPropertyName, INotifyPropertyChanged fieldObject, string fieldPropertyName, IBindingConverter converter) : this(controlObject, controlPropertyName, fieldObject, fieldPropertyName) - { - _converter = converter; - } - - /// - /// Bind properties of two objects bidirectionally, converting the values using a converter. - /// Synchronization can be intercepted by adding a validator. - /// - /// Object containing 1st property to bind - /// Property of 1st object to bind - /// Object containing 2nd property to bind - /// Property of 2nd object to bind - /// validator to intercept synchronization if the value does not match certain criteria - public BidirectionalBinding(INotifyPropertyChanged controlObject, string controlPropertyName, INotifyPropertyChanged fieldObject, string fieldPropertyName, IBindingValidator validator) : this(controlObject, controlPropertyName, fieldObject, fieldPropertyName) - { - _validator = validator; - } - - /// - /// Bind properties of two objects bidirectionally, converting the values using a converter. - /// Synchronization can be intercepted by adding a validator. - /// - /// Object containing 1st property to bind - /// Property of 1st object to bind - /// Object containing 2nd property to bind - /// Property of 2nd object to bind - /// taking care of converting the synchronized value to the correct target format and back - /// validator to intercept synchronization if the value does not match certain criteria - public BidirectionalBinding(INotifyPropertyChanged controlObject, string controlPropertyName, INotifyPropertyChanged fieldObject, string fieldPropertyName, IBindingConverter converter, IBindingValidator validator) : this(controlObject, controlPropertyName, fieldObject, fieldPropertyName, converter) - { - _validator = validator; - } - - public void ControlPropertyChanged(object sender, PropertyChangedEventArgs e) - { - if (!_updatingControl && e.PropertyName.Equals(_controlPropertyName)) - { - _updatingField = true; - Synchronize(_controlObject, _controlPropertyName, _fieldObject, _fieldPropertyName); - _updatingField = false; - } - } - - public void FieldPropertyChanged(object sender, PropertyChangedEventArgs e) - { - if (!_updatingField && e.PropertyName.Equals(_fieldPropertyName)) - { - _updatingControl = true; - Synchronize(_fieldObject, _fieldPropertyName, _controlObject, _controlPropertyName); - _updatingControl = false; - } - } - - private void Synchronize(INotifyPropertyChanged sourceObject, string sourceProperty, INotifyPropertyChanged targetObject, string targetProperty) - { - PropertyInfo targetPropertyInfo = ResolvePropertyInfo(targetObject, targetProperty); - PropertyInfo sourcePropertyInfo = ResolvePropertyInfo(sourceObject, sourceProperty); - - if (sourcePropertyInfo != null && targetPropertyInfo != null && targetPropertyInfo.CanWrite) - { - object bValue = sourcePropertyInfo.GetValue(sourceObject, null); - if (_converter != null && bValue != null) - { - bValue = _converter.convert(bValue); - } - try - { - if (_validator == null || _validator.validate(bValue)) - { - targetPropertyInfo.SetValue(targetObject, bValue, null); - } - } - catch (Exception e) - { - throw new MemberAccessException("Could not set property '" + targetProperty + "' to '" + bValue + "' [" + (bValue != null ? bValue.GetType().Name : "") + "] on " + targetObject + ". Probably other type than expected, IBindingCoverter to the rescue.", e); - } - } - } - - private static PropertyInfo ResolvePropertyInfo(object obj, string property) - { - PropertyInfo ret = null; - string[] properties = property.Split(".".ToCharArray()); - for (int i = 0; i < properties.Length; i++) - { - string prop = properties[i]; - ret = obj.GetType().GetProperty(prop); - if (ret != null && ret.CanRead && i < prop.Length - 1) - { - obj = ret.GetValue(obj, null); - } - } - return ret; - } - - public IBindingConverter Converter - { - get { return _converter; } - set { _converter = value; } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/Fields/Binding/DecimalDoublePercentageConverter.cs b/Greenshot.ImageEditor/Drawing/Fields/Binding/DecimalDoublePercentageConverter.cs deleted file mode 100644 index 6d65e430d..000000000 --- a/Greenshot.ImageEditor/Drawing/Fields/Binding/DecimalDoublePercentageConverter.cs +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System; - -namespace Greenshot.Drawing.Fields.Binding -{ - /// - /// Converts decimal to double (%) and vice versa, e.g. 95f <---> 0.95d - /// - public class DecimalDoublePercentageConverter : AbstractBindingConverter - { - private static DecimalDoublePercentageConverter uniqueInstance; - - private DecimalDoublePercentageConverter() - { - } - - protected override decimal convert(double o) - { - return Convert.ToDecimal(o) * 100; - } - - protected override double convert(decimal o) - { - return Convert.ToDouble(o) / 100; - } - - public static DecimalDoublePercentageConverter GetInstance() - { - if (uniqueInstance == null) uniqueInstance = new DecimalDoublePercentageConverter(); - return uniqueInstance; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/Fields/Binding/DecimalFloatConverter.cs b/Greenshot.ImageEditor/Drawing/Fields/Binding/DecimalFloatConverter.cs deleted file mode 100644 index 1632bd0f8..000000000 --- a/Greenshot.ImageEditor/Drawing/Fields/Binding/DecimalFloatConverter.cs +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System; - -namespace Greenshot.Drawing.Fields.Binding -{ - /// - /// Converts decimal to float and vice versa. - /// - public class DecimalFloatConverter : AbstractBindingConverter - { - private static DecimalFloatConverter uniqueInstance; - - private DecimalFloatConverter() - { - } - - protected override decimal convert(float o) - { - return Convert.ToDecimal(o); - } - - protected override float convert(decimal o) - { - return Convert.ToInt16(o); - } - - public static DecimalFloatConverter GetInstance() - { - if (uniqueInstance == null) uniqueInstance = new DecimalFloatConverter(); - return uniqueInstance; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/Fields/Binding/DecimalIntConverter.cs b/Greenshot.ImageEditor/Drawing/Fields/Binding/DecimalIntConverter.cs deleted file mode 100644 index 033b6bbdc..000000000 --- a/Greenshot.ImageEditor/Drawing/Fields/Binding/DecimalIntConverter.cs +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System; - -namespace Greenshot.Drawing.Fields.Binding -{ - /// - /// Converts decimal to int and vice versa. - /// - public class DecimalIntConverter : AbstractBindingConverter - { - private static DecimalIntConverter uniqueInstance; - - private DecimalIntConverter() - { - } - - protected override decimal convert(int o) - { - return Convert.ToDecimal(o); - } - - protected override int convert(decimal o) - { - return Convert.ToInt16(o); - } - - public static DecimalIntConverter GetInstance() - { - if (uniqueInstance == null) uniqueInstance = new DecimalIntConverter(); - return uniqueInstance; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/Fields/Binding/IBindingConverter.cs b/Greenshot.ImageEditor/Drawing/Fields/Binding/IBindingConverter.cs deleted file mode 100644 index 581cb8857..000000000 --- a/Greenshot.ImageEditor/Drawing/Fields/Binding/IBindingConverter.cs +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -namespace Greenshot.Drawing.Fields.Binding -{ - /// - /// Interface for a bidirectional converter, for use with BidirectionalBinding. - /// convert(object) implementation must deal with both directions. - /// see DecimalIntConverter - /// - public interface IBindingConverter - { - object convert(object o); - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/Fields/Binding/IBindingValidator.cs b/Greenshot.ImageEditor/Drawing/Fields/Binding/IBindingValidator.cs deleted file mode 100644 index 72b5c89ea..000000000 --- a/Greenshot.ImageEditor/Drawing/Fields/Binding/IBindingValidator.cs +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -namespace Greenshot.Drawing.Fields.Binding -{ - /// - /// Interface for a bidirectional validator, for use with BidirectionalBinding. - /// Useful if you do not want to synchronize values which would be illegal on - /// one of the bound objects (e.g. null value on some form components) - /// see NotNullValidator - /// - public interface IBindingValidator - { - bool validate(object o); - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/Fields/Binding/NotNullValidator.cs b/Greenshot.ImageEditor/Drawing/Fields/Binding/NotNullValidator.cs deleted file mode 100644 index 1f979bc28..000000000 --- a/Greenshot.ImageEditor/Drawing/Fields/Binding/NotNullValidator.cs +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -namespace Greenshot.Drawing.Fields.Binding -{ - /// - /// Validates a value not to be null. - /// - public class NotNullValidator : IBindingValidator - { - private static NotNullValidator uniqueInstance; - - private NotNullValidator() - { - } - - public bool validate(object o) - { - return o != null; - } - - public static NotNullValidator GetInstance() - { - if (uniqueInstance == null) uniqueInstance = new NotNullValidator(); - return uniqueInstance; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/Fields/Field.cs b/Greenshot.ImageEditor/Drawing/Fields/Field.cs deleted file mode 100644 index 0ea945aa7..000000000 --- a/Greenshot.ImageEditor/Drawing/Fields/Field.cs +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System; -using System.ComponentModel; - -namespace Greenshot.Drawing.Fields -{ - /// - /// Represents a single field of a drawable element, i.e. - /// line thickness of a rectangle. - /// - [Serializable] - public class Field : INotifyPropertyChanged - { - [field: NonSerialized] - public event PropertyChangedEventHandler PropertyChanged; - - public object myValue; - public object Value - { - get - { - return myValue; - } - set - { - if (!Equals(myValue, value)) - { - myValue = value; - if (PropertyChanged != null) - { - PropertyChanged(this, new PropertyChangedEventArgs("Value")); - } - } - } - } - public FieldType FieldType; - public string Scope; - - /// - /// Constructs a new Field instance, usually you should be using FieldFactory - /// to create Fields. - /// - /// FieldType of the Field to be created - /// The scope to which the value of this Field is relevant. - /// Depending on the scope the Field's value may be shared for other elements - /// containing the same FieldType for defaulting to the last used value. - /// When scope is set to a Type (e.g. typeof(RectangleContainer)), its value - /// should not be reused for FieldHolders of another Type (e.g. typeof(EllipseContainer)) - /// - public Field(FieldType fieldType, Type scope) - { - FieldType = fieldType; - Scope = scope.Name; - } - - public Field(FieldType fieldType, string scope) - { - FieldType = fieldType; - Scope = scope; - } - - public Field(FieldType fieldType) - { - FieldType = fieldType; - } - - /// - /// Returns true if this field holds a value other than null. - /// - public bool HasValue - { - get { return Value != null; } - } - - /// - /// Creates a flat clone of this Field. The fields value itself is not cloned. - /// - /// - public Field Clone() - { - Field ret = new Field(FieldType, Scope); - ret.Value = Value; - return ret; - } - - public override int GetHashCode() - { - int hashCode = 0; - unchecked - { - hashCode += 1000000009 * FieldType.GetHashCode(); - if (Scope != null) - hashCode += 1000000021 * Scope.GetHashCode(); - } - return hashCode; - } - - public override bool Equals(object obj) - { - Field other = obj as Field; - if (other == null) - { - return false; - } - return FieldType == other.FieldType && Equals(Scope, other.Scope); - } - - public override string ToString() - { - return string.Format("[Field FieldType={1} Value={0} Scope={2}]", myValue, FieldType, Scope); - } - } - - /// - /// EventHandler to be used when a field value changes - /// - public delegate void FieldChangedEventHandler(object sender, FieldChangedEventArgs e); - - /// - /// EventArgs to be used with FieldChangedEventHandler - /// - public class FieldChangedEventArgs : EventArgs - { - public readonly Field Field; - - public FieldChangedEventArgs(Field field) - { - Field = field; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/Fields/FieldAggregator.cs b/Greenshot.ImageEditor/Drawing/Fields/FieldAggregator.cs deleted file mode 100644 index 197ded39c..000000000 --- a/Greenshot.ImageEditor/Drawing/Fields/FieldAggregator.cs +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Configuration; -using Greenshot.IniFile; -using Greenshot.Plugin.Drawing; -using System.Collections.Generic; -using System.ComponentModel; - -namespace Greenshot.Drawing.Fields -{ - /// - /// Represents the current set of properties for the editor. - /// When one of EditorProperties' properties is updated, the change will be promoted - /// to all bound elements. - /// * If an element is selected: - /// This class represents the element's properties - /// * I n>1 elements are selected: - /// This class represents the properties of all elements. - /// Properties that do not apply for ALL selected elements are null (or 0 respectively) - /// If the property values of the selected elements differ, the value of the last bound element wins. - /// - public class FieldAggregator : AbstractFieldHolder - { - private readonly List boundContainers; - private bool internalUpdateRunning; - - private static readonly EditorConfiguration editorConfiguration = IniConfig.GetIniSection(); - - public FieldAggregator() - { - foreach (FieldType fieldType in FieldType.Values) - { - Field field = new Field(fieldType, GetType()); - AddField(field); - } - boundContainers = new List(); - } - - public override void AddField(Field field) - { - base.AddField(field); - field.PropertyChanged += OwnPropertyChanged; - } - - public void BindElements(DrawableContainerList dcs) - { - foreach (DrawableContainer dc in dcs) - { - BindElement(dc); - } - } - - public void BindElement(IDrawableContainer dc) - { - DrawableContainer container = dc as DrawableContainer; - if (container != null && !boundContainers.Contains(container)) - { - boundContainers.Add(container); - container.ChildrenChanged += delegate - { - UpdateFromBoundElements(); - }; - UpdateFromBoundElements(); - } - } - - public void BindAndUpdateElement(IDrawableContainer dc) - { - UpdateElement(dc); - BindElement(dc); - } - - public void UpdateElement(IDrawableContainer dc) - { - DrawableContainer container = dc as DrawableContainer; - if (container == null) - { - return; - } - internalUpdateRunning = true; - foreach (Field field in GetFields()) - { - if (container.HasField(field.FieldType) && field.HasValue) - { - //if(LOG.IsDebugEnabled) LOG.Debug(" "+field+ ": "+field.Value); - container.SetFieldValue(field.FieldType, field.Value); - } - } - internalUpdateRunning = false; - } - - public void UnbindElement(IDrawableContainer dc) - { - if (boundContainers.Contains(dc)) - { - boundContainers.Remove(dc); - UpdateFromBoundElements(); - } - } - - public void Clear() - { - ClearFields(); - boundContainers.Clear(); - UpdateFromBoundElements(); - } - - /// - /// sets all field values to null, however does not remove fields - /// - private void ClearFields() - { - internalUpdateRunning = true; - foreach (Field field in GetFields()) - { - field.Value = null; - } - internalUpdateRunning = false; - } - - /// - /// Updates this instance using the respective fields from the bound elements. - /// Fields that do not apply to every bound element are set to null, or 0 respectively. - /// All other fields will be set to the field value of the least bound element. - /// - private void UpdateFromBoundElements() - { - ClearFields(); - internalUpdateRunning = true; - foreach (Field field in FindCommonFields()) - { - SetFieldValue(field.FieldType, field.Value); - } - internalUpdateRunning = false; - } - - private List FindCommonFields() - { - List returnFields = null; - if (boundContainers.Count > 0) - { - // take all fields from the least selected container... - DrawableContainer leastSelectedContainer = boundContainers[boundContainers.Count - 1] as DrawableContainer; - if (leastSelectedContainer != null) - { - returnFields = leastSelectedContainer.GetFields(); - for (int i = 0; i < boundContainers.Count - 1; i++) - { - DrawableContainer dc = boundContainers[i] as DrawableContainer; - if (dc != null) - { - List fieldsToRemove = new List(); - foreach (Field f in returnFields) - { - // ... throw out those that do not apply to one of the other containers - if (!dc.HasField(f.FieldType)) - { - fieldsToRemove.Add(f); - } - } - foreach (Field f in fieldsToRemove) - { - returnFields.Remove(f); - } - } - } - } - } - if (returnFields == null) - { - returnFields = new List(); - } - return returnFields; - } - - public void OwnPropertyChanged(object sender, PropertyChangedEventArgs ea) - { - Field field = (Field)sender; - if (!internalUpdateRunning && field.Value != null) - { - foreach (DrawableContainer drawableContainer in boundContainers) - { - if (drawableContainer.HasField(field.FieldType)) - { - Field drawableContainerField = drawableContainer.GetField(field.FieldType); - // Notify before change, so we can e.g. invalidate the area - drawableContainer.BeforeFieldChange(drawableContainerField, field.Value); - - drawableContainerField.Value = field.Value; - // update last used from DC field, so that scope is honored - editorConfiguration.UpdateLastFieldValue(drawableContainerField); - } - } - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/Fields/FieldType.cs b/Greenshot.ImageEditor/Drawing/Fields/FieldType.cs deleted file mode 100644 index 4bd3ce2d2..000000000 --- a/Greenshot.ImageEditor/Drawing/Fields/FieldType.cs +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System; - -namespace Greenshot.Drawing.Fields -{ - /// - /// Defines all FieldTypes + their default value. - /// (The additional value is why this is not an enum) - /// - [Serializable] - public class FieldType - { - public static readonly FieldType ARROWHEADS = new FieldType("ARROWHEADS"); - public static readonly FieldType BLUR_RADIUS = new FieldType("BLUR_RADIUS"); - public static readonly FieldType BRIGHTNESS = new FieldType("BRIGHTNESS"); - public static readonly FieldType FILL_COLOR = new FieldType("FILL_COLOR"); - public static readonly FieldType FONT_BOLD = new FieldType("FONT_BOLD"); - public static readonly FieldType FONT_FAMILY = new FieldType("FONT_FAMILY"); - public static readonly FieldType FONT_ITALIC = new FieldType("FONT_ITALIC"); - public static readonly FieldType FONT_SIZE = new FieldType("FONT_SIZE"); - public static readonly FieldType TEXT_HORIZONTAL_ALIGNMENT = new FieldType("TEXT_HORIZONTAL_ALIGNMENT"); - public static readonly FieldType TEXT_VERTICAL_ALIGNMENT = new FieldType("TEXT_VERTICAL_ALIGNMENT"); - public static readonly FieldType HIGHLIGHT_COLOR = new FieldType("HIGHLIGHT_COLOR"); - public static readonly FieldType LINE_COLOR = new FieldType("LINE_COLOR"); - public static readonly FieldType LINE_THICKNESS = new FieldType("LINE_THICKNESS"); - public static readonly FieldType MAGNIFICATION_FACTOR = new FieldType("MAGNIFICATION_FACTOR"); - public static readonly FieldType PIXEL_SIZE = new FieldType("PIXEL_SIZE"); - public static readonly FieldType PREVIEW_QUALITY = new FieldType("PREVIEW_QUALITY"); - public static readonly FieldType SHADOW = new FieldType("SHADOW"); - public static readonly FieldType PREPARED_FILTER_OBFUSCATE = new FieldType("PREPARED_FILTER_OBFUSCATE"); - public static readonly FieldType PREPARED_FILTER_HIGHLIGHT = new FieldType("PREPARED_FILTER_HIGHLIGHT"); - public static readonly FieldType FLAGS = new FieldType("FLAGS"); - - public static FieldType[] Values = new FieldType[]{ - ARROWHEADS, - BLUR_RADIUS, - BRIGHTNESS, - FILL_COLOR, - FONT_BOLD, - FONT_FAMILY, - FONT_ITALIC, - FONT_SIZE, - TEXT_HORIZONTAL_ALIGNMENT, - TEXT_VERTICAL_ALIGNMENT, - HIGHLIGHT_COLOR, - LINE_COLOR, - LINE_THICKNESS, - MAGNIFICATION_FACTOR, - PIXEL_SIZE, - PREVIEW_QUALITY, - SHADOW, - PREPARED_FILTER_OBFUSCATE, - PREPARED_FILTER_HIGHLIGHT, - FLAGS - }; - - [Flags] - public enum Flag - { - NONE = 0, - CONFIRMABLE = 1 - } - - public string Name; - - private FieldType(string name) - { - Name = name; - } - - public override string ToString() - { - return Name; - } - - public override int GetHashCode() - { - int hashCode = 0; - unchecked - { - if (Name != null) - hashCode += 1000000009 * Name.GetHashCode(); - } - return hashCode; - } - - public override bool Equals(object obj) - { - FieldType other = obj as FieldType; - if (other == null) - return false; - return Equals(Name, other.Name); - } - - public static bool operator ==(FieldType a, FieldType b) - { - return Equals(a, b); - } - - public static bool operator !=(FieldType a, FieldType b) - { - return !Equals(a, b); - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/Fields/IFieldHolder.cs b/Greenshot.ImageEditor/Drawing/Fields/IFieldHolder.cs deleted file mode 100644 index db40967c9..000000000 --- a/Greenshot.ImageEditor/Drawing/Fields/IFieldHolder.cs +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System.Collections.Generic; - -namespace Greenshot.Drawing.Fields -{ - /// - /// Any element holding Fields must provide access to it. - /// AbstractFieldHolder is the basic implementation. - /// If you need the fieldHolder to have child fieldHolders, - /// you should consider using IFieldHolderWithChildren. - /// - public interface IFieldHolder - { - event FieldChangedEventHandler FieldChanged; - - void AddField(Field field); - - void RemoveField(Field field); - - List GetFields(); - - Field GetField(FieldType fieldType); - - bool HasField(FieldType fieldType); - - void SetFieldValue(FieldType fieldType, object value); - } - - /// - /// Extended fieldHolder which has fieldHolder children. - /// Implementations should pass field values to and from - /// their children. - /// AbstractFieldHolderWithChildren is the basic implementation. - /// - public interface IFieldHolderWithChildren : IFieldHolder - { - void AddChild(IFieldHolder fieldHolder); - - void RemoveChild(IFieldHolder fieldHolder); - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/FilterContainer.cs b/Greenshot.ImageEditor/Drawing/FilterContainer.cs deleted file mode 100644 index 7c84f7067..000000000 --- a/Greenshot.ImageEditor/Drawing/FilterContainer.cs +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Drawing.Fields; -using Greenshot.Helpers; -using Greenshot.Plugin.Drawing; -using System; -using System.Drawing; -using System.Drawing.Drawing2D; - -namespace Greenshot.Drawing -{ - /// - /// empty container for filter-only elements - /// - [Serializable()] - public abstract class FilterContainer : DrawableContainer - { - public enum PreparedFilterMode { OBFUSCATE, HIGHLIGHT }; - public enum PreparedFilter { BLUR, PIXELIZE, TEXT_HIGHTLIGHT, AREA_HIGHLIGHT, GRAYSCALE, MAGNIFICATION }; - - public PreparedFilter Filter - { - get { return (PreparedFilter)GetFieldValue(FieldType.PREPARED_FILTER_HIGHLIGHT); } - } - - public FilterContainer(Surface parent) : base(parent) - { - } - - protected override void InitializeFields() - { - AddField(GetType(), FieldType.LINE_THICKNESS, 0); - AddField(GetType(), FieldType.LINE_COLOR, DefaultLineColor); - AddField(GetType(), FieldType.SHADOW, false); - } - - public override void Draw(Graphics graphics, RenderMode rm) - { - int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); - Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR); - bool shadow = GetFieldValueAsBool(FieldType.SHADOW); - bool lineVisible = lineThickness > 0 && Colors.IsVisible(lineColor); - if (lineVisible) - { - graphics.SmoothingMode = SmoothingMode.HighSpeed; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.PixelOffsetMode = PixelOffsetMode.None; - //draw shadow first - if (shadow) - { - int basealpha = 100; - int alpha = basealpha; - int steps = 5; - int currentStep = lineVisible ? 1 : 0; - while (currentStep <= steps) - { - using (Pen shadowPen = new Pen(Color.FromArgb(alpha, 100, 100, 100), lineThickness)) - { - Rectangle shadowRect = GuiRectangle.GetGuiRectangle(Left + currentStep, Top + currentStep, Width, Height); - graphics.DrawRectangle(shadowPen, shadowRect); - currentStep++; - alpha = alpha - basealpha / steps; - } - } - } - Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); - if (lineThickness > 0) - { - using (Pen pen = new Pen(lineColor, lineThickness)) - { - graphics.DrawRectangle(pen, rect); - } - } - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/Filters/AbstractFilter.cs b/Greenshot.ImageEditor/Drawing/Filters/AbstractFilter.cs deleted file mode 100644 index a336a08ac..000000000 --- a/Greenshot.ImageEditor/Drawing/Filters/AbstractFilter.cs +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Drawing.Fields; -using Greenshot.Plugin.Drawing; -using System; -using System.ComponentModel; -using System.Drawing; - -/// -/// Graphical filter which can be added to DrawableContainer. -/// Subclasses should fulfill INotifyPropertyChanged contract, i.e. call -/// OnPropertyChanged whenever a public property has been changed. -/// -namespace Greenshot.Drawing.Filters -{ - [Serializable()] - public abstract class AbstractFilter : AbstractFieldHolder, IFilter - { - [NonSerialized] - private PropertyChangedEventHandler propertyChanged; - public event PropertyChangedEventHandler PropertyChanged - { - add { propertyChanged += value; } - remove { propertyChanged -= value; } - } - - private bool invert; - public bool Invert - { - get - { - return invert; - } - set - { - invert = value; - OnPropertyChanged("Invert"); - } - } - - protected DrawableContainer parent; - public DrawableContainer Parent - { - get - { - return parent; - } - set - { - parent = value; - } - } - - public AbstractFilter(DrawableContainer parent) - { - this.parent = parent; - } - - public DrawableContainer GetParent() - { - return parent; - } - - public abstract void Apply(Graphics graphics, Bitmap applyBitmap, Rectangle rect, RenderMode renderMode); - - protected void OnPropertyChanged(string propertyName) - { - if (propertyChanged != null) - { - propertyChanged(this, new PropertyChangedEventArgs(propertyName)); - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/Filters/BlurFilter.cs b/Greenshot.ImageEditor/Drawing/Filters/BlurFilter.cs deleted file mode 100644 index 00b4bb279..000000000 --- a/Greenshot.ImageEditor/Drawing/Filters/BlurFilter.cs +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Drawing.Fields; -using Greenshot.Plugin.Drawing; -using GreenshotPlugin.Core; -using GreenshotPlugin.UnmanagedHelpers; -using System; -using System.Drawing; -using System.Drawing.Drawing2D; - -namespace Greenshot.Drawing.Filters -{ - [Serializable()] - public class BlurFilter : AbstractFilter - { - public double previewQuality; - public double PreviewQuality - { - get { return previewQuality; } - set { previewQuality = value; OnPropertyChanged("PreviewQuality"); } - } - - public BlurFilter(DrawableContainer parent) : base(parent) - { - AddField(GetType(), FieldType.BLUR_RADIUS, 15); - AddField(GetType(), FieldType.PREVIEW_QUALITY, 1.0d); - } - - public override void Apply(Graphics graphics, Bitmap applyBitmap, Rectangle rect, RenderMode renderMode) - { - int blurRadius = GetFieldValueAsInt(FieldType.BLUR_RADIUS); - Rectangle applyRect = ImageHelper.CreateIntersectRectangle(applyBitmap.Size, rect, Invert); - if (applyRect.Width == 0 || applyRect.Height == 0) - { - return; - } - GraphicsState state = graphics.Save(); - if (Invert) - { - graphics.SetClip(applyRect); - graphics.ExcludeClip(rect); - } - if (GDIplus.IsBlurPossible(blurRadius)) - { - GDIplus.DrawWithBlur(graphics, applyBitmap, applyRect, null, null, blurRadius, false); - } - else - { - using (IFastBitmap fastBitmap = FastBitmap.CreateCloneOf(applyBitmap, applyRect)) - { - ImageHelper.ApplyBoxBlur(fastBitmap, blurRadius); - fastBitmap.DrawTo(graphics, applyRect); - } - } - graphics.Restore(state); - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/Filters/BrightnessFilter.cs b/Greenshot.ImageEditor/Drawing/Filters/BrightnessFilter.cs deleted file mode 100644 index 1c09b0831..000000000 --- a/Greenshot.ImageEditor/Drawing/Filters/BrightnessFilter.cs +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Drawing.Fields; -using Greenshot.Plugin.Drawing; -using GreenshotPlugin.Core; -using System; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Imaging; - -namespace Greenshot.Drawing.Filters -{ - [Serializable()] - public class BrightnessFilter : AbstractFilter - { - public BrightnessFilter(DrawableContainer parent) : base(parent) - { - AddField(GetType(), FieldType.BRIGHTNESS, 0.9d); - } - - /// - /// Implements the Apply code for the Brightness Filet - /// - /// - /// - /// - /// - public override void Apply(Graphics graphics, Bitmap applyBitmap, Rectangle rect, RenderMode renderMode) - { - Rectangle applyRect = ImageHelper.CreateIntersectRectangle(applyBitmap.Size, rect, Invert); - - if (applyRect.Width == 0 || applyRect.Height == 0) - { - // nothing to do - return; - } - - GraphicsState state = graphics.Save(); - if (Invert) - { - graphics.SetClip(applyRect); - graphics.ExcludeClip(rect); - } - float brightness = GetFieldValueAsFloat(FieldType.BRIGHTNESS); - using (ImageAttributes ia = ImageHelper.CreateAdjustAttributes(brightness, 1f, 1f)) - { - graphics.DrawImage(applyBitmap, applyRect, applyRect.X, applyRect.Y, applyRect.Width, applyRect.Height, GraphicsUnit.Pixel, ia); - } - graphics.Restore(state); - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/Filters/GrayscaleFilter.cs b/Greenshot.ImageEditor/Drawing/Filters/GrayscaleFilter.cs deleted file mode 100644 index bb7f73c55..000000000 --- a/Greenshot.ImageEditor/Drawing/Filters/GrayscaleFilter.cs +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Plugin.Drawing; -using GreenshotPlugin.Core; -using System; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Imaging; - -namespace Greenshot.Drawing.Filters -{ - /// - /// Description of GrayscaleFilter. - /// - [Serializable()] - public class GrayscaleFilter : AbstractFilter - { - public GrayscaleFilter(DrawableContainer parent) : base(parent) - { - } - - public override void Apply(Graphics graphics, Bitmap applyBitmap, Rectangle rect, RenderMode renderMode) - { - Rectangle applyRect = ImageHelper.CreateIntersectRectangle(applyBitmap.Size, rect, Invert); - - if (applyRect.Width == 0 || applyRect.Height == 0) - { - // nothing to do - return; - } - GraphicsState state = graphics.Save(); - if (Invert) - { - graphics.SetClip(applyRect); - graphics.ExcludeClip(rect); - } - ColorMatrix grayscaleMatrix = new ColorMatrix(new[] { - new[] {.3f, .3f, .3f, 0, 0}, - new[] {.59f, .59f, .59f, 0, 0}, - new[] {.11f, .11f, .11f, 0, 0}, - new float[] {0, 0, 0, 1, 0}, - new float[] {0, 0, 0, 0, 1} - }); - using (ImageAttributes ia = new ImageAttributes()) - { - ia.SetColorMatrix(grayscaleMatrix); - graphics.DrawImage(applyBitmap, applyRect, applyRect.X, applyRect.Y, applyRect.Width, applyRect.Height, GraphicsUnit.Pixel, ia); - } - graphics.Restore(state); - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/Filters/HighlightFilter.cs b/Greenshot.ImageEditor/Drawing/Filters/HighlightFilter.cs deleted file mode 100644 index 03665adc7..000000000 --- a/Greenshot.ImageEditor/Drawing/Filters/HighlightFilter.cs +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Drawing.Fields; -using Greenshot.Plugin.Drawing; -using GreenshotPlugin.Core; -using System; -using System.Drawing; -using System.Drawing.Drawing2D; - -namespace Greenshot.Drawing.Filters -{ - [Serializable()] - public class HighlightFilter : AbstractFilter - { - public HighlightFilter(DrawableContainer parent) : base(parent) - { - AddField(GetType(), FieldType.FILL_COLOR, Color.Yellow); - } - - /// - /// Implements the Apply code for the Brightness Filet - /// - /// - /// - /// - /// - public override void Apply(Graphics graphics, Bitmap applyBitmap, Rectangle rect, RenderMode renderMode) - { - Rectangle applyRect = ImageHelper.CreateIntersectRectangle(applyBitmap.Size, rect, Invert); - - if (applyRect.Width == 0 || applyRect.Height == 0) - { - // nothing to do - return; - } - GraphicsState state = graphics.Save(); - if (Invert) - { - graphics.SetClip(applyRect); - graphics.ExcludeClip(rect); - } - using (IFastBitmap fastBitmap = FastBitmap.CreateCloneOf(applyBitmap, applyRect)) - { - Color highlightColor = GetFieldValueAsColor(FieldType.FILL_COLOR); - for (int y = fastBitmap.Top; y < fastBitmap.Bottom; y++) - { - for (int x = fastBitmap.Left; x < fastBitmap.Right; x++) - { - Color color = fastBitmap.GetColorAt(x, y); - color = Color.FromArgb(color.A, Math.Min(highlightColor.R, color.R), Math.Min(highlightColor.G, color.G), Math.Min(highlightColor.B, color.B)); - fastBitmap.SetColorAt(x, y, color); - } - } - fastBitmap.DrawTo(graphics, applyRect.Location); - } - graphics.Restore(state); - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/Filters/IFilter.cs b/Greenshot.ImageEditor/Drawing/Filters/IFilter.cs deleted file mode 100644 index 7920f3f9f..000000000 --- a/Greenshot.ImageEditor/Drawing/Filters/IFilter.cs +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Drawing.Fields; -using Greenshot.Plugin.Drawing; -using System.ComponentModel; -using System.Drawing; - -namespace Greenshot.Drawing.Filters -{ - public interface IFilter : INotifyPropertyChanged, IFieldHolder - { - DrawableContainer Parent { get; set; } - - void Apply(Graphics graphics, Bitmap bmp, Rectangle rect, RenderMode renderMode); - - DrawableContainer GetParent(); - - bool Invert { get; set; } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/Filters/MagnifierFilter.cs b/Greenshot.ImageEditor/Drawing/Filters/MagnifierFilter.cs deleted file mode 100644 index e60b7cb6d..000000000 --- a/Greenshot.ImageEditor/Drawing/Filters/MagnifierFilter.cs +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Drawing.Fields; -using Greenshot.Plugin.Drawing; -using GreenshotPlugin.Core; -using System; -using System.Drawing; -using System.Drawing.Drawing2D; - -namespace Greenshot.Drawing.Filters -{ - [Serializable] - public class MagnifierFilter : AbstractFilter - { - public MagnifierFilter(DrawableContainer parent) : base(parent) - { - AddField(GetType(), FieldType.MAGNIFICATION_FACTOR, 2); - } - - public override void Apply(Graphics graphics, Bitmap applyBitmap, Rectangle rect, RenderMode renderMode) - { - Rectangle applyRect = ImageHelper.CreateIntersectRectangle(applyBitmap.Size, rect, Invert); - - if (applyRect.Width == 0 || applyRect.Height == 0) - { - // nothing to do - return; - } - int magnificationFactor = GetFieldValueAsInt(FieldType.MAGNIFICATION_FACTOR); - GraphicsState state = graphics.Save(); - if (Invert) - { - graphics.SetClip(applyRect); - graphics.ExcludeClip(rect); - } - graphics.SmoothingMode = SmoothingMode.None; - graphics.InterpolationMode = InterpolationMode.NearestNeighbor; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.PixelOffsetMode = PixelOffsetMode.None; - int halfWidth = rect.Width / 2; - int halfHeight = rect.Height / 2; - int newWidth = rect.Width / magnificationFactor; - int newHeight = rect.Height / magnificationFactor; - Rectangle source = new Rectangle(rect.X + halfWidth - newWidth / 2, rect.Y + halfHeight - newHeight / 2, newWidth, newHeight); - graphics.DrawImage(applyBitmap, rect, source, GraphicsUnit.Pixel); - graphics.Restore(state); - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/Filters/PixelizationFilter.cs b/Greenshot.ImageEditor/Drawing/Filters/PixelizationFilter.cs deleted file mode 100644 index 7f29f3ea8..000000000 --- a/Greenshot.ImageEditor/Drawing/Filters/PixelizationFilter.cs +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Drawing.Fields; -using Greenshot.Helpers; -using Greenshot.Plugin.Drawing; -using GreenshotPlugin.Core; -using System; -using System.Collections.Generic; -using System.Drawing; - -namespace Greenshot.Drawing.Filters -{ - [Serializable()] - public class PixelizationFilter : AbstractFilter - { - public PixelizationFilter(DrawableContainer parent) : base(parent) - { - AddField(GetType(), FieldType.PIXEL_SIZE, 7); - } - - public override void Apply(Graphics graphics, Bitmap applyBitmap, Rectangle rect, RenderMode renderMode) - { - int pixelSize = GetFieldValueAsInt(FieldType.PIXEL_SIZE); - ImageHelper.CreateIntersectRectangle(applyBitmap.Size, rect, Invert); - if (pixelSize <= 1 || rect.Width == 0 || rect.Height == 0) - { - // Nothing to do - return; - } - if (rect.Width < pixelSize) - { - pixelSize = rect.Width; - } - if (rect.Height < pixelSize) - { - pixelSize = rect.Height; - } - using (IFastBitmap dest = FastBitmap.CreateCloneOf(applyBitmap, rect)) - { - using (IFastBitmap src = FastBitmap.Create(applyBitmap, rect)) - { - List colors = new List(); - int halbPixelSize = pixelSize / 2; - for (int y = src.Top - halbPixelSize; y < src.Bottom + halbPixelSize; y = y + pixelSize) - { - for (int x = src.Left - halbPixelSize; x <= src.Right + halbPixelSize; x = x + pixelSize) - { - colors.Clear(); - for (int yy = y; yy < y + pixelSize; yy++) - { - if (yy >= src.Top && yy < src.Bottom) - { - for (int xx = x; xx < x + pixelSize; xx++) - { - if (xx >= src.Left && xx < src.Right) - { - colors.Add(src.GetColorAt(xx, yy)); - } - } - } - } - Color currentAvgColor = Colors.Mix(colors); - for (int yy = y; yy <= y + pixelSize; yy++) - { - if (yy >= src.Top && yy < src.Bottom) - { - for (int xx = x; xx <= x + pixelSize; xx++) - { - if (xx >= src.Left && xx < src.Right) - { - dest.SetColorAt(xx, yy, currentAvgColor); - } - } - } - } - } - } - } - dest.DrawTo(graphics, rect.Location); - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/FreehandContainer.cs b/Greenshot.ImageEditor/Drawing/FreehandContainer.cs deleted file mode 100644 index 08452680b..000000000 --- a/Greenshot.ImageEditor/Drawing/FreehandContainer.cs +++ /dev/null @@ -1,324 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Drawing.Fields; -using Greenshot.Helpers; -using Greenshot.Plugin.Drawing; -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Runtime.Serialization; - -namespace Greenshot.Drawing -{ - /// - /// Description of PathContainer. - /// - [Serializable] - public class FreehandContainer : DrawableContainer - { - private static readonly float[] POINT_OFFSET = new float[] { 0.5f, 0.25f, 0.75f }; - - [NonSerialized] - private GraphicsPath freehandPath = new GraphicsPath(); - private Rectangle myBounds = Rectangle.Empty; - private Point lastMouse = Point.Empty; - private readonly List capturePoints = new List(); - private bool isRecalculated; - - /// - /// Constructor - /// - public FreehandContainer(Surface parent) : base(parent) - { - Init(); - Width = parent.Width; - Height = parent.Height; - Top = 0; - Left = 0; - } - - protected override void InitializeFields() - { - AddField(GetType(), FieldType.LINE_THICKNESS, 3); - AddField(GetType(), FieldType.LINE_COLOR, DefaultLineColor); - } - - protected void Init() - { - if (_grippers != null) - { - for (int i = 0; i < _grippers.Length; i++) - { - _grippers[i].Enabled = false; - _grippers[i].Visible = false; - } - } - } - - public override void Transform(Matrix matrix) - { - Point[] points = capturePoints.ToArray(); - - matrix.TransformPoints(points); - capturePoints.Clear(); - capturePoints.AddRange(points); - RecalculatePath(); - } - - [OnDeserialized] - private void OnDeserialized(StreamingContext context) - { - InitGrippers(); - DoLayout(); - Init(); - RecalculatePath(); - } - - /// - /// This Dispose is called from the Dispose and the Destructor. - /// - /// When disposing==true all non-managed resources should be freed too! - protected override void Dispose(bool disposing) - { - base.Dispose(disposing); - if (disposing) - { - if (freehandPath != null) - { - freehandPath.Dispose(); - } - } - freehandPath = null; - } - - /// - /// Called from Surface (the parent) when the drawing begins (mouse-down) - /// - /// true if the surface doesn't need to handle the event - public override bool HandleMouseDown(int mouseX, int mouseY) - { - lastMouse = new Point(mouseX, mouseY); - capturePoints.Add(lastMouse); - return true; - } - - /// - /// Called from Surface (the parent) if a mouse move is made while drawing - /// - /// true if the surface doesn't need to handle the event - public override bool HandleMouseMove(int mouseX, int mouseY) - { - Point previousPoint = capturePoints[capturePoints.Count - 1]; - - if (GeometryHelper.Distance2D(previousPoint.X, previousPoint.Y, mouseX, mouseY) >= 2 * EditorConfig.FreehandSensitivity) - { - capturePoints.Add(new Point(mouseX, mouseY)); - } - if (GeometryHelper.Distance2D(lastMouse.X, lastMouse.Y, mouseX, mouseY) >= EditorConfig.FreehandSensitivity) - { - //path.AddCurve(new Point[]{lastMouse, new Point(mouseX, mouseY)}); - freehandPath.AddLine(lastMouse, new Point(mouseX, mouseY)); - lastMouse = new Point(mouseX, mouseY); - // Only re-calculate the bounds & redraw when we added something to the path - myBounds = Rectangle.Round(freehandPath.GetBounds()); - Invalidate(); - } - return true; - } - - /// - /// Called when the surface finishes drawing the element - /// - public override void HandleMouseUp(int mouseX, int mouseY) - { - // Make sure we don't loose the ending point - if (GeometryHelper.Distance2D(lastMouse.X, lastMouse.Y, mouseX, mouseY) >= EditorConfig.FreehandSensitivity) - { - capturePoints.Add(new Point(mouseX, mouseY)); - } - RecalculatePath(); - } - - /// - /// Here we recalculate the freehand path by smoothing out the lines with Beziers. - /// - private void RecalculatePath() - { - isRecalculated = true; - // Dispose the previous path, if we have one - if (freehandPath != null) - { - freehandPath.Dispose(); - } - freehandPath = new GraphicsPath(); - - // Here we can put some cleanup... like losing all the uninteresting points. - if (capturePoints.Count >= 3) - { - int index = 0; - while ((capturePoints.Count - 1) % 3 != 0) - { - // duplicate points, first at 50% than 25% than 75% - capturePoints.Insert((int)(capturePoints.Count * POINT_OFFSET[index]), capturePoints[(int)(capturePoints.Count * POINT_OFFSET[index++])]); - } - freehandPath.AddBeziers(capturePoints.ToArray()); - } - else if (capturePoints.Count == 2) - { - freehandPath.AddLine(capturePoints[0], capturePoints[1]); - } - - // Recalculate the bounds - myBounds = Rectangle.Round(freehandPath.GetBounds()); - } - - /// - /// Do the drawing of the freehand "stroke" - /// - /// - /// - public override void Draw(Graphics graphics, RenderMode renderMode) - { - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - - int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); - Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR); - using (Pen pen = new Pen(lineColor)) - { - pen.Width = lineThickness; - if (pen.Width > 0) - { - // Make sure the lines are nicely rounded - pen.EndCap = LineCap.Round; - pen.StartCap = LineCap.Round; - pen.LineJoin = LineJoin.Round; - - // Move to where we need to draw - graphics.TranslateTransform(Left, Top); - if (isRecalculated && Selected && renderMode == RenderMode.EDIT) - { - DrawSelectionBorder(graphics, pen); - } - graphics.DrawPath(pen, freehandPath); - // Move back, otherwise everything is shifted - graphics.TranslateTransform(-Left, -Top); - } - } - } - - /// - /// Draw a selectionborder around the freehand path - /// - /// - /// - protected void DrawSelectionBorder(Graphics graphics, Pen linePen) - { - using (Pen selectionPen = (Pen)linePen.Clone()) - { - using (GraphicsPath selectionPath = (GraphicsPath)freehandPath.Clone()) - { - selectionPen.Width += 5; - selectionPen.Color = Color.FromArgb(120, Color.LightSeaGreen); - graphics.DrawPath(selectionPen, selectionPath); - selectionPath.Widen(selectionPen); - selectionPen.DashPattern = new float[] { 2, 2 }; - selectionPen.Color = Color.LightSeaGreen; - selectionPen.Width = 1; - graphics.DrawPath(selectionPen, selectionPath); - } - } - } - - /// - /// Get the bounds in which we have something drawn, plus safety margin, these are not the normal bounds... - /// - public override Rectangle DrawingBounds - { - get - { - if (!myBounds.IsEmpty) - { - int lineThickness = Math.Max(10, GetFieldValueAsInt(FieldType.LINE_THICKNESS)); - int safetymargin = 10; - return new Rectangle(myBounds.Left + Left - (safetymargin + lineThickness), myBounds.Top + Top - (safetymargin + lineThickness), myBounds.Width + 2 * (lineThickness + safetymargin), myBounds.Height + 2 * (lineThickness + safetymargin)); - } - return new Rectangle(0, 0, _parent.Width, _parent.Height); - } - } - - /// - /// FreehandContainer are regarded equal if they are of the same type and their paths are equal. - /// - /// - /// - public override bool Equals(object obj) - { - bool ret = false; - if (obj != null && GetType().Equals(obj.GetType())) - { - FreehandContainer other = obj as FreehandContainer; - if (freehandPath.Equals(other.freehandPath)) - { - ret = true; - } - } - return ret; - } - - public override int GetHashCode() - { - return freehandPath.GetHashCode(); - } - - /// - /// This is overriden to prevent the grippers to be modified. - /// Might not be the best way... - /// - protected override void DoLayout() - { - } - - public override void ShowGrippers() - { - ResumeLayout(); - } - - public override bool ClickableAt(int x, int y) - { - bool returnValue = base.ClickableAt(x, y); - if (returnValue) - { - int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); - using (Pen pen = new Pen(Color.White)) - { - pen.Width = lineThickness + 10; - returnValue = freehandPath.IsOutlineVisible(x - Left, y - Top, pen); - } - } - return returnValue; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/Gripper.cs b/Greenshot.ImageEditor/Drawing/Gripper.cs deleted file mode 100644 index bd7eabd6f..000000000 --- a/Greenshot.ImageEditor/Drawing/Gripper.cs +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using System.Drawing; -using System.Windows.Forms; - -namespace Greenshot.Drawing -{ - /// - /// Grippers are the dragable edges of our containers - /// - public class Gripper : Label - { - /// - /// Constants for anchor/gripper position: - /// 0 1 2 - /// 7 3 - /// 6 5 4 - /// - public const int POSITION_TOP_LEFT = 0; - public const int POSITION_TOP_CENTER = 1; - public const int POSITION_TOP_RIGHT = 2; - public const int POSITION_MIDDLE_RIGHT = 3; - public const int POSITION_BOTTOM_RIGHT = 4; - public const int POSITION_BOTTOM_CENTER = 5; - public const int POSITION_BOTTOM_LEFT = 6; - public const int POSITION_MIDDLE_LEFT = 7; - - public const int GripperSize = 7; - - public int Position - { - get; - set; - } - - public Gripper() - { - Width = GripperSize; - Height = GripperSize; - BackColor = Color.White; - BorderStyle = BorderStyle.FixedSingle; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/HighlightContainer.cs b/Greenshot.ImageEditor/Drawing/HighlightContainer.cs deleted file mode 100644 index f395377c1..000000000 --- a/Greenshot.ImageEditor/Drawing/HighlightContainer.cs +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Drawing.Fields; -using Greenshot.Drawing.Filters; -using System; -using System.Runtime.Serialization; - -namespace Greenshot.Drawing -{ - /// - /// Description of ObfuscateContainer. - /// - [Serializable] - public class HighlightContainer : FilterContainer - { - public HighlightContainer(Surface parent) : base(parent) - { - Init(); - } - - /// - /// Use settings from base, extend with our own field - /// - protected override void InitializeFields() - { - base.InitializeFields(); - AddField(GetType(), FieldType.PREPARED_FILTER_HIGHLIGHT, PreparedFilter.TEXT_HIGHTLIGHT); - } - - [OnDeserialized] - private void OnDeserialized(StreamingContext context) - { - Init(); - } - - private void Init() - { - FieldChanged += HighlightContainer_OnFieldChanged; - ConfigurePreparedFilters(); - } - - protected void HighlightContainer_OnFieldChanged(object sender, FieldChangedEventArgs e) - { - if (!sender.Equals(this)) - { - return; - } - if (e.Field.FieldType == FieldType.PREPARED_FILTER_HIGHLIGHT) - { - ConfigurePreparedFilters(); - } - } - - private void ConfigurePreparedFilters() - { - PreparedFilter preset = (PreparedFilter)GetFieldValue(FieldType.PREPARED_FILTER_HIGHLIGHT); - while (Filters.Count > 0) - { - Remove(Filters[0]); - } - switch (preset) - { - case PreparedFilter.TEXT_HIGHTLIGHT: - Add(new HighlightFilter(this)); - break; - case PreparedFilter.AREA_HIGHLIGHT: - AbstractFilter bf = new BrightnessFilter(this); - bf.Invert = true; - Add(bf); - bf = new BlurFilter(this); - bf.Invert = true; - Add(bf); - break; - case PreparedFilter.GRAYSCALE: - AbstractFilter f = new GrayscaleFilter(this); - f.Invert = true; - Add(f); - break; - case PreparedFilter.MAGNIFICATION: - Add(new MagnifierFilter(this)); - break; - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/IconContainer.cs b/Greenshot.ImageEditor/Drawing/IconContainer.cs deleted file mode 100644 index a0a0603cd..000000000 --- a/Greenshot.ImageEditor/Drawing/IconContainer.cs +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Plugin.Drawing; -using GreenshotPlugin; -using System; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.IO; - -namespace Greenshot.Drawing -{ - /// - /// Description of IconContainer. - /// - [Serializable] - public class IconContainer : DrawableContainer, IIconContainer - { - protected Icon icon; - - public IconContainer(Surface parent) : base(parent) - { - } - - public IconContainer(Surface parent, string filename) : base(parent) - { - Load(filename); - } - - public Icon Icon - { - set - { - if (icon != null) - { - icon.Dispose(); - } - icon = (Icon)value.Clone(); - Width = value.Width; - Height = value.Height; - } - get - { - return icon; - } - } - - /** - * This Dispose is called from the Dispose and the Destructor. - * When disposing==true all non-managed resources should be freed too! - */ - - protected override void Dispose(bool disposing) - { - if (disposing) - { - if (icon != null) - { - icon.Dispose(); - } - } - icon = null; - base.Dispose(disposing); - } - - public void Load(string filename) - { - if (File.Exists(filename)) - { - using (Icon fileIcon = new Icon(filename)) - { - Icon = fileIcon; - LOG.Debug("Loaded file: " + filename + " with resolution: " + Height + "," + Width); - } - } - } - - public override void Draw(Graphics graphics, RenderMode rm) - { - if (icon != null) - { - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.InterpolationMode = InterpolationMode.NearestNeighbor; - graphics.CompositingQuality = CompositingQuality.Default; - graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - graphics.DrawIcon(icon, Bounds); - } - } - - public override bool HasDefaultSize - { - get - { - return true; - } - } - - public override Size DefaultSize - { - get - { - return icon.Size; - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/ImageContainer.cs b/Greenshot.ImageEditor/Drawing/ImageContainer.cs deleted file mode 100644 index a7e705c78..000000000 --- a/Greenshot.ImageEditor/Drawing/ImageContainer.cs +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Core; -using Greenshot.Drawing.Fields; -using Greenshot.Plugin.Drawing; -using GreenshotPlugin; -using GreenshotPlugin.Core; -using System; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.IO; - -namespace Greenshot.Drawing -{ - /// - /// Description of BitmapContainer. - /// - [Serializable] - public class ImageContainer : DrawableContainer, IImageContainer - { - private Image image; - - /// - /// This is the shadow version of the bitmap, rendered once to save performance - /// Do not serialize, as the shadow is recreated from the original bitmap if it's not available - /// - [NonSerialized] - private Image _shadowBitmap; - - /// - /// This is the offset for the shadow version of the bitmap - /// Do not serialize, as the offset is recreated - /// - [NonSerialized] - private Point _shadowOffset = new Point(-1, -1); - - public ImageContainer(Surface parent, string filename) : this(parent) - { - Load(filename); - } - - public ImageContainer(Surface parent) : base(parent) - { - FieldChanged += BitmapContainer_OnFieldChanged; - } - - protected override void InitializeFields() - { - AddField(GetType(), FieldType.SHADOW, false); - } - - protected void BitmapContainer_OnFieldChanged(object sender, FieldChangedEventArgs e) - { - if (sender.Equals(this)) - { - if (e.Field.FieldType == FieldType.SHADOW) - { - ChangeShadowField(); - } - } - } - - public void ChangeShadowField() - { - bool shadow = GetFieldValueAsBool(FieldType.SHADOW); - if (shadow) - { - CheckShadow(true); - Width = _shadowBitmap.Width; - Height = _shadowBitmap.Height; - Left = Left - _shadowOffset.X; - Top = Top - _shadowOffset.Y; - } - else - { - Width = image.Width; - Height = image.Height; - if (_shadowBitmap != null) - { - Left = Left + _shadowOffset.X; - Top = Top + _shadowOffset.Y; - } - } - } - - public Image Image - { - set - { - // Remove all current bitmaps - DisposeImage(); - DisposeShadow(); - image = ImageHelper.Clone(value); - bool shadow = GetFieldValueAsBool(FieldType.SHADOW); - CheckShadow(shadow); - if (!shadow) - { - Width = image.Width; - Height = image.Height; - } - else - { - Width = _shadowBitmap.Width; - Height = _shadowBitmap.Height; - Left = Left - _shadowOffset.X; - Top = Top - _shadowOffset.Y; - } - } - get - { - return image; - } - } - - /// - /// The bulk of the clean-up code is implemented in Dispose(bool) - /// This Dispose is called from the Dispose and the Destructor. - /// When disposing==true all non-managed resources should be freed too! - /// - /// - protected override void Dispose(bool disposing) - { - if (disposing) - { - DisposeImage(); - DisposeShadow(); - } - base.Dispose(disposing); - } - - private void DisposeImage() - { - if (image != null) - { - image.Dispose(); - } - image = null; - } - - private void DisposeShadow() - { - if (_shadowBitmap != null) - { - _shadowBitmap.Dispose(); - } - _shadowBitmap = null; - } - - /// - /// Make sure the content is also transformed. - /// - /// - public override void Transform(Matrix matrix) - { - int rotateAngle = CalculateAngle(matrix); - // we currently assume only one transformation has been made. - if (rotateAngle != 0) - { - LOG.DebugFormat("Rotating element with {0} degrees.", rotateAngle); - DisposeShadow(); - using (var tmpMatrix = new Matrix()) - { - using (Image tmpImage = image) - { - image = ImageHelper.ApplyEffect(image, new RotateEffect(rotateAngle), tmpMatrix); - } - } - } - base.Transform(matrix); - } - - /// - /// - /// - /// - public void Load(string filename) - { - if (File.Exists(filename)) - { - // Always make sure ImageHelper.LoadBitmap results are disposed some time, - // as we close the bitmap internally, we need to do it afterwards - using (Image tmpImage = ImageHelper.LoadImage(filename)) - { - Image = tmpImage; - } - LOG.Debug("Loaded file: " + filename + " with resolution: " + Height + "," + Width); - } - } - - /// - /// This checks if a shadow is already generated - /// - /// - private void CheckShadow(bool shadow) - { - if (shadow && _shadowBitmap == null) - { - using (var matrix = new Matrix()) - { - _shadowBitmap = ImageHelper.ApplyEffect(image, new DropShadowEffect(), matrix); - } - } - } - - /// - /// Draw the actual container to the graphics object - /// - /// - /// - public override void Draw(Graphics graphics, RenderMode rm) - { - if (image != null) - { - bool shadow = GetFieldValueAsBool(FieldType.SHADOW); - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - - if (shadow) - { - CheckShadow(true); - graphics.DrawImage(_shadowBitmap, Bounds); - } - else - { - graphics.DrawImage(image, Bounds); - } - } - } - - public override bool HasDefaultSize - { - get - { - return true; - } - } - - public override Size DefaultSize - { - get - { - return image.Size; - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/LineContainer.cs b/Greenshot.ImageEditor/Drawing/LineContainer.cs deleted file mode 100644 index 6114697e5..000000000 --- a/Greenshot.ImageEditor/Drawing/LineContainer.cs +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Drawing.Fields; -using Greenshot.Helpers; -using Greenshot.Plugin.Drawing; -using System; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Runtime.Serialization; - -namespace Greenshot.Drawing -{ - /// - /// Description of LineContainer. - /// - [Serializable()] - public class LineContainer : DrawableContainer - { - public static readonly int MAX_CLICK_DISTANCE_TOLERANCE = 10; - - public LineContainer(Surface parent) : base(parent) - { - Init(); - } - - protected override void InitializeFields() - { - AddField(GetType(), FieldType.LINE_THICKNESS, 2); - AddField(GetType(), FieldType.LINE_COLOR, DefaultLineColor); - AddField(GetType(), FieldType.SHADOW, true); - } - - [OnDeserialized()] - private void OnDeserialized(StreamingContext context) - { - InitGrippers(); - DoLayout(); - Init(); - } - - protected void Init() - { - if (_grippers != null) - { - foreach (int index in new[] { 1, 2, 3, 5, 6, 7 }) - { - _grippers[index].Enabled = false; - } - } - } - - public override void Draw(Graphics graphics, RenderMode rm) - { - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBilinear; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.PixelOffsetMode = PixelOffsetMode.None; - - int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); - Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR); - bool shadow = GetFieldValueAsBool(FieldType.SHADOW); - - if (lineThickness > 0) - { - if (shadow) - { - //draw shadow first - int basealpha = 100; - int alpha = basealpha; - int steps = 5; - int currentStep = 1; - while (currentStep <= steps) - { - using (Pen shadowCapPen = new Pen(Color.FromArgb(alpha, 100, 100, 100), lineThickness)) - { - graphics.DrawLine(shadowCapPen, - Left + currentStep, - Top + currentStep, - Left + currentStep + Width, - Top + currentStep + Height); - - currentStep++; - alpha = alpha - basealpha / steps; - } - } - } - - using (Pen pen = new Pen(lineColor, lineThickness)) - { - graphics.DrawLine(pen, Left, Top, Left + Width, Top + Height); - } - } - } - - public override bool ClickableAt(int x, int y) - { - int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS) + 5; - if (lineThickness > 0) - { - using (Pen pen = new Pen(Color.White)) - { - pen.Width = lineThickness; - using (GraphicsPath path = new GraphicsPath()) - { - path.AddLine(Left, Top, Left + Width, Top + Height); - return path.IsOutlineVisible(x, y, pen); - } - } - } - return false; - } - - protected override ScaleHelper.IDoubleProcessor GetAngleRoundProcessor() - { - return ScaleHelper.LineAngleRoundBehavior.Instance; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/ObfuscateContainer.cs b/Greenshot.ImageEditor/Drawing/ObfuscateContainer.cs deleted file mode 100644 index e295c259d..000000000 --- a/Greenshot.ImageEditor/Drawing/ObfuscateContainer.cs +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Drawing.Fields; -using Greenshot.Drawing.Filters; -using System; -using System.Runtime.Serialization; - -namespace Greenshot.Drawing -{ - /// - /// Description of ObfuscateContainer. - /// - [Serializable] - public class ObfuscateContainer : FilterContainer - { - public ObfuscateContainer(Surface parent) : base(parent) - { - Init(); - } - - protected override void InitializeFields() - { - base.InitializeFields(); - AddField(GetType(), FieldType.PREPARED_FILTER_OBFUSCATE, PreparedFilter.PIXELIZE); - } - - [OnDeserialized] - private void OnDeserialized(StreamingContext context) - { - Init(); - } - - private void Init() - { - FieldChanged += ObfuscateContainer_OnFieldChanged; - ConfigurePreparedFilters(); - } - - protected void ObfuscateContainer_OnFieldChanged(object sender, FieldChangedEventArgs e) - { - if (sender.Equals(this)) - { - if (e.Field.FieldType == FieldType.PREPARED_FILTER_OBFUSCATE) - { - ConfigurePreparedFilters(); - } - } - } - - private void ConfigurePreparedFilters() - { - PreparedFilter preset = (PreparedFilter)GetFieldValue(FieldType.PREPARED_FILTER_OBFUSCATE); - while (Filters.Count > 0) - { - Remove(Filters[0]); - } - switch (preset) - { - case PreparedFilter.BLUR: - Add(new BlurFilter(this)); - break; - case PreparedFilter.PIXELIZE: - Add(new PixelizationFilter(this)); - break; - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/RectangleContainer.cs b/Greenshot.ImageEditor/Drawing/RectangleContainer.cs deleted file mode 100644 index 3dbdd5812..000000000 --- a/Greenshot.ImageEditor/Drawing/RectangleContainer.cs +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Drawing.Fields; -using Greenshot.Helpers; -using Greenshot.Plugin.Drawing; -using System; -using System.Drawing; -using System.Drawing.Drawing2D; - -namespace Greenshot.Drawing -{ - /// - /// Represents a rectangular shape on the Surface - /// - [Serializable] - public class RectangleContainer : DrawableContainer - { - public RectangleContainer(Surface parent) : base(parent) - { - } - - protected override void InitializeFields() - { - AddField(GetType(), FieldType.LINE_THICKNESS, 2); - AddField(GetType(), FieldType.LINE_COLOR, DefaultLineColor); - AddField(GetType(), FieldType.FILL_COLOR, Color.Transparent); - AddField(GetType(), FieldType.SHADOW, true); - } - - public override void Draw(Graphics graphics, RenderMode rm) - { - int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); - Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR); - Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR); - bool shadow = GetFieldValueAsBool(FieldType.SHADOW); - Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); - - DrawRectangle(rect, graphics, rm, lineThickness, lineColor, fillColor, shadow); - } - - /// - /// This method can also be used from other containers, if the right values are passed! - /// - /// - /// - /// - /// - /// - /// - /// - public static void DrawRectangle(Rectangle rect, Graphics graphics, RenderMode rm, int lineThickness, Color lineColor, Color fillColor, bool shadow) - { - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.PixelOffsetMode = PixelOffsetMode.None; - - bool lineVisible = lineThickness > 0 && Colors.IsVisible(lineColor); - if (shadow && (lineVisible || Colors.IsVisible(fillColor))) - { - //draw shadow first - int basealpha = 100; - int alpha = basealpha; - int steps = 5; - int currentStep = lineVisible ? 1 : 0; - while (currentStep <= steps) - { - using (Pen shadowPen = new Pen(Color.FromArgb(alpha, 100, 100, 100))) - { - shadowPen.Width = lineVisible ? lineThickness : 1; - Rectangle shadowRect = GuiRectangle.GetGuiRectangle( - rect.Left + currentStep, - rect.Top + currentStep, - rect.Width, - rect.Height); - graphics.DrawRectangle(shadowPen, shadowRect); - currentStep++; - alpha = alpha - basealpha / steps; - } - } - } - - if (Colors.IsVisible(fillColor)) - { - using (Brush brush = new SolidBrush(fillColor)) - { - graphics.FillRectangle(brush, rect); - } - } - - graphics.SmoothingMode = SmoothingMode.HighSpeed; - if (lineVisible) - { - using (Pen pen = new Pen(lineColor, lineThickness)) - { - graphics.DrawRectangle(pen, rect); - } - } - } - - public override bool ClickableAt(int x, int y) - { - Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); - int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS) + 10; - Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR); - - return RectangleClickableAt(rect, lineThickness, fillColor, x, y); - } - - public static bool RectangleClickableAt(Rectangle rect, int lineThickness, Color fillColor, int x, int y) - { - // If we clicked inside the rectangle and it's visible we are clickable at. - if (!Color.Transparent.Equals(fillColor)) - { - if (rect.Contains(x, y)) - { - return true; - } - } - - // check the rest of the lines - if (lineThickness > 0) - { - using (Pen pen = new Pen(Color.White, lineThickness)) - { - using (GraphicsPath path = new GraphicsPath()) - { - path.AddRectangle(rect); - return path.IsOutlineVisible(x, y, pen); - } - } - } - return false; - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/SpeechbubbleContainer.cs b/Greenshot.ImageEditor/Drawing/SpeechbubbleContainer.cs deleted file mode 100644 index b9560670b..000000000 --- a/Greenshot.ImageEditor/Drawing/SpeechbubbleContainer.cs +++ /dev/null @@ -1,388 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2012 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Drawing.Fields; -using Greenshot.Helpers; -using Greenshot.Plugin.Drawing; -using System; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Text; -using System.Runtime.Serialization; - -namespace Greenshot.Drawing -{ - /// - /// Description of SpeechbubbleContainer. - /// - [Serializable] - public class SpeechbubbleContainer : TextContainer - { - private Point _initialGripperPoint; - - #region TargetGripper serializing code - - // Only used for serializing the TargetGripper location - private Point _storedTargetGripperLocation; - - /// - /// Store the current location of the target gripper - /// - /// - [OnSerializing] - private void SetValuesOnSerializing(StreamingContext context) - { - if (TargetGripper != null) - { - _storedTargetGripperLocation = TargetGripper.Location; - } - } - - /// - /// Restore the target gripper - /// - /// - [OnDeserialized] - private void SetValuesOnDeserialized(StreamingContext context) - { - InitTargetGripper(Color.Yellow, _storedTargetGripperLocation); - } - - #endregion TargetGripper serializing code - - public SpeechbubbleContainer(Surface parent) - : base(parent) - { - } - - /// - /// We set our own field values - /// - protected override void InitializeFields() - { - AddField(GetType(), FieldType.LINE_THICKNESS, 2); - AddField(GetType(), FieldType.LINE_COLOR, DefaultLineColor); - AddField(GetType(), FieldType.SHADOW, false); - AddField(GetType(), FieldType.FONT_ITALIC, false); - AddField(GetType(), FieldType.FONT_BOLD, false); - AddField(GetType(), FieldType.FILL_COLOR, Color.White); - AddField(GetType(), FieldType.FONT_FAMILY, FontFamily.GenericSansSerif.Name); - AddField(GetType(), FieldType.FONT_SIZE, 20f); - AddField(GetType(), FieldType.TEXT_HORIZONTAL_ALIGNMENT, StringAlignment.Center); - AddField(GetType(), FieldType.TEXT_VERTICAL_ALIGNMENT, StringAlignment.Center); - } - - /// - /// Called from Surface (the _parent) when the drawing begins (mouse-down) - /// - /// true if the surface doesn't need to handle the event - public override bool HandleMouseDown(int mouseX, int mouseY) - { - if (TargetGripper == null) - { - _initialGripperPoint = new Point(mouseX, mouseY); - InitTargetGripper(Color.Yellow, new Point(mouseX, mouseY)); - } - return base.HandleMouseDown(mouseX, mouseY); - } - - /// - /// Overriding the HandleMouseMove will help us to make sure the tail is always visible. - /// Should fix BUG-1682 - /// - /// - /// - /// base.HandleMouseMove - public override bool HandleMouseMove(int x, int y) - { - bool returnValue = base.HandleMouseMove(x, y); - - bool leftAligned = _boundsAfterResize.Right - _boundsAfterResize.Left >= 0; - bool topAligned = _boundsAfterResize.Bottom - _boundsAfterResize.Top >= 0; - - int xOffset = leftAligned ? -20 : 20; - int yOffset = topAligned ? -20 : 20; - - Point newGripperLocation = _initialGripperPoint; - newGripperLocation.Offset(xOffset, yOffset); - - if (TargetGripper.Location != newGripperLocation) - { - Invalidate(); - TargetGripperMove(newGripperLocation.X, newGripperLocation.Y); - Invalidate(); - } - return returnValue; - } - - /// - /// The DrawingBound should be so close as possible to the shape, so we don't invalidate to much. - /// - public override Rectangle DrawingBounds - { - get - { - if (Status != EditStatus.UNDRAWN) - { - int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); - Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR); - bool shadow = GetFieldValueAsBool(FieldType.SHADOW); - using (Pen pen = new Pen(lineColor, lineThickness)) - { - int inflateValue = lineThickness + 2 + (shadow ? 6 : 0); - using (GraphicsPath tailPath = CreateTail()) - { - return Rectangle.Inflate(Rectangle.Union(Rectangle.Round(tailPath.GetBounds(new Matrix(), pen)), GuiRectangle.GetGuiRectangle(Left, Top, Width, Height)), inflateValue, inflateValue); - } - } - } - return Rectangle.Empty; - } - } - - /// - /// Helper method to create the bubble GraphicsPath, so we can also calculate the bounds - /// - /// - /// - private GraphicsPath CreateBubble(int lineThickness) - { - GraphicsPath bubble = new GraphicsPath(); - Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); - - Rectangle bubbleRect = GuiRectangle.GetGuiRectangle(0, 0, rect.Width, rect.Height); - // adapt corner radius to small rectangle dimensions - int smallerSideLength = Math.Min(bubbleRect.Width, bubbleRect.Height); - int cornerRadius = Math.Min(30, smallerSideLength / 2 - lineThickness); - if (cornerRadius > 0) - { - bubble.AddArc(bubbleRect.X, bubbleRect.Y, cornerRadius, cornerRadius, 180, 90); - bubble.AddArc(bubbleRect.X + bubbleRect.Width - cornerRadius, bubbleRect.Y, cornerRadius, cornerRadius, 270, 90); - bubble.AddArc(bubbleRect.X + bubbleRect.Width - cornerRadius, bubbleRect.Y + bubbleRect.Height - cornerRadius, cornerRadius, cornerRadius, 0, 90); - bubble.AddArc(bubbleRect.X, bubbleRect.Y + bubbleRect.Height - cornerRadius, cornerRadius, cornerRadius, 90, 90); - } - else - { - bubble.AddRectangle(bubbleRect); - } - bubble.CloseAllFigures(); - using (Matrix bubbleMatrix = new Matrix()) - { - bubbleMatrix.Translate(rect.Left, rect.Top); - bubble.Transform(bubbleMatrix); - } - return bubble; - } - - /// - /// Helper method to create the tail of the bubble, so we can also calculate the bounds - /// - /// - private GraphicsPath CreateTail() - { - Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); - - int tailLength = GeometryHelper.Distance2D(rect.Left + rect.Width / 2, rect.Top + rect.Height / 2, TargetGripper.Left, TargetGripper.Top); - int tailWidth = (Math.Abs(rect.Width) + Math.Abs(rect.Height)) / 20; - - // This should fix a problem with the tail being to wide - tailWidth = Math.Min(Math.Abs(rect.Width) / 2, tailWidth); - tailWidth = Math.Min(Math.Abs(rect.Height) / 2, tailWidth); - - GraphicsPath tail = new GraphicsPath(); - tail.AddLine(-tailWidth, 0, tailWidth, 0); - tail.AddLine(tailWidth, 0, 0, -tailLength); - tail.CloseFigure(); - - int tailAngle = 90 + (int)GeometryHelper.Angle2D(rect.Left + rect.Width / 2, rect.Top + rect.Height / 2, TargetGripper.Left, TargetGripper.Top); - - using (Matrix tailMatrix = new Matrix()) - { - tailMatrix.Translate(rect.Left + rect.Width / 2, rect.Top + rect.Height / 2); - tailMatrix.Rotate(tailAngle); - tail.Transform(tailMatrix); - } - - return tail; - } - - /// - /// This is to draw the actual container - /// - /// - /// - public override void Draw(Graphics graphics, RenderMode renderMode) - { - if (TargetGripper == null) - { - return; - } - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.PixelOffsetMode = PixelOffsetMode.None; - graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit; - - Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR); - Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR); - bool shadow = GetFieldValueAsBool(FieldType.SHADOW); - int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); - - bool lineVisible = lineThickness > 0 && Colors.IsVisible(lineColor); - Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); - - if (Selected && renderMode == RenderMode.EDIT) - { - DrawSelectionBorder(graphics, rect); - } - - GraphicsPath bubble = CreateBubble(lineThickness); - - GraphicsPath tail = CreateTail(); - - //draw shadow first - if (shadow && (lineVisible || Colors.IsVisible(fillColor))) - { - const int basealpha = 100; - int alpha = basealpha; - const int steps = 5; - int currentStep = lineVisible ? 1 : 0; - using (Matrix shadowMatrix = new Matrix()) - using (GraphicsPath bubbleClone = (GraphicsPath)bubble.Clone()) - using (GraphicsPath tailClone = (GraphicsPath)tail.Clone()) - { - shadowMatrix.Translate(1, 1); - while (currentStep <= steps) - { - using (Pen shadowPen = new Pen(Color.FromArgb(alpha, 100, 100, 100))) - { - shadowPen.Width = lineVisible ? lineThickness : 1; - tailClone.Transform(shadowMatrix); - graphics.DrawPath(shadowPen, tailClone); - bubbleClone.Transform(shadowMatrix); - graphics.DrawPath(shadowPen, bubbleClone); - } - currentStep++; - alpha = alpha - basealpha / steps; - } - } - } - - GraphicsState state = graphics.Save(); - // draw the tail border where the bubble is not visible - using (Region clipRegion = new Region(bubble)) - { - graphics.SetClip(clipRegion, CombineMode.Exclude); - using (Pen pen = new Pen(lineColor, lineThickness)) - { - graphics.DrawPath(pen, tail); - } - } - graphics.Restore(state); - - if (Colors.IsVisible(fillColor)) - { - //draw the bubbleshape - state = graphics.Save(); - using (Brush brush = new SolidBrush(fillColor)) - { - graphics.FillPath(brush, bubble); - } - graphics.Restore(state); - } - - if (lineVisible) - { - //draw the bubble border - state = graphics.Save(); - // Draw bubble where the Tail is not visible. - using (Region clipRegion = new Region(tail)) - { - graphics.SetClip(clipRegion, CombineMode.Exclude); - using (Pen pen = new Pen(lineColor, lineThickness)) - { - //pen.EndCap = pen.StartCap = LineCap.Round; - graphics.DrawPath(pen, bubble); - } - } - graphics.Restore(state); - } - - if (Colors.IsVisible(fillColor)) - { - // Draw the tail border - state = graphics.Save(); - using (Brush brush = new SolidBrush(fillColor)) - { - graphics.FillPath(brush, tail); - } - graphics.Restore(state); - } - - // cleanup the paths - bubble.Dispose(); - tail.Dispose(); - - // Draw the text - DrawText(graphics, rect, lineThickness, lineColor, shadow, StringFormat, Text, Font); - } - - public override bool Contains(int x, int y) - { - if (base.Contains(x, y)) - { - return true; - } - Point clickedPoint = new Point(x, y); - if (Status != EditStatus.UNDRAWN) - { - int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); - Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR); - using (Pen pen = new Pen(lineColor, lineThickness)) - { - using (GraphicsPath bubblePath = CreateBubble(lineThickness)) - { - bubblePath.Widen(pen); - if (bubblePath.IsVisible(clickedPoint)) - { - return true; - } - } - using (GraphicsPath tailPath = CreateTail()) - { - tailPath.Widen(pen); - if (tailPath.IsVisible(clickedPoint)) - { - return true; - } - } - } - } - - return false; - } - - public override bool ClickableAt(int x, int y) - { - return Contains(x, y); - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/StepLabelContainer.cs b/Greenshot.ImageEditor/Drawing/StepLabelContainer.cs deleted file mode 100644 index 1c1c41766..000000000 --- a/Greenshot.ImageEditor/Drawing/StepLabelContainer.cs +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2012 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Drawing.Fields; -using Greenshot.Helpers; -using Greenshot.Plugin.Drawing; -using System; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Text; -using System.Runtime.Serialization; - -namespace Greenshot.Drawing -{ - /// - /// This is an enumerated label, every single StepLabelContainer shows the number of the order it was created. - /// To make sure that deleting recalculates, we check the location before every draw. - /// - [Serializable] - public class StepLabelContainer : DrawableContainer - { - [NonSerialized] - private StringFormat _stringFormat = new StringFormat(); - - private readonly bool _drawAsRectangle = false; - - private float fontSize = 16; - - public StepLabelContainer(Surface parent) : base(parent) - { - parent.AddStepLabel(this); - InitContent(); - } - - #region Number serializing - - // Used to store the number of this label, so when deserializing it can be placed back to the StepLabels list in the right location - private int _number; - public int Number - { - get - { - return _number; - } - set - { - _number = value; - } - } - - /// - /// Retrieve the counter before serializing - /// - /// - [OnSerializing] - private void SetValuesOnSerializing(StreamingContext context) - { - if (Parent != null) - { - Number = ((Surface)Parent).CountStepLabels(this); - } - } - - #endregion Number serializing - - /// - /// Restore values that don't serialize - /// - /// - [OnDeserialized] - private void SetValuesOnDeserialized(StreamingContext context) - { - _stringFormat = new StringFormat(); - _stringFormat.Alignment = StringAlignment.Center; - _stringFormat.LineAlignment = StringAlignment.Center; - } - - /// - /// Add the StepLabel to the parent - /// - /// - protected override void SwitchParent(Surface newParent) - { - if (Parent != null) - { - ((Surface)Parent).RemoveStepLabel(this); - } - base.SwitchParent(newParent); - if (newParent != null) - { - ((Surface)Parent).AddStepLabel(this); - } - } - - public override Size DefaultSize - { - get - { - return new Size(30, 30); - } - } - - public override bool InitContent() - { - _defaultEditMode = EditStatus.IDLE; - _stringFormat.Alignment = StringAlignment.Center; - _stringFormat.LineAlignment = StringAlignment.Center; - - // Set defaults - Width = DefaultSize.Width; - Height = DefaultSize.Height; - - return true; - } - - /// - /// This makes it possible for the label to be placed exactly in the middle of the pointer. - /// - public override bool HandleMouseDown(int mouseX, int mouseY) - { - return base.HandleMouseDown(mouseX - Width / 2, mouseY - Height / 2); - } - - /// - /// We set our own field values - /// - protected override void InitializeFields() - { - AddField(GetType(), FieldType.FILL_COLOR, DefaultLineColor); - AddField(GetType(), FieldType.LINE_COLOR, Color.White); - } - - /// - /// Make sure this element is no longer referenced from the surface - /// - protected override void Dispose(bool disposing) - { - base.Dispose(disposing); - if (!disposing) - { - return; - } - ((Surface)Parent).RemoveStepLabel(this); - if (_stringFormat != null) - { - _stringFormat.Dispose(); - _stringFormat = null; - } - } - - public override bool HandleMouseMove(int x, int y) - { - Invalidate(); - Left = x - Width / 2; - Top = y - Height / 2; - Invalidate(); - return true; - } - - /// - /// Make sure the size of the font is scaled - /// - /// - public override void Transform(Matrix matrix) - { - Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); - int widthBefore = rect.Width; - int heightBefore = rect.Height; - - // Transform this container - base.Transform(matrix); - rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); - - int widthAfter = rect.Width; - int heightAfter = rect.Height; - float factor = ((float)widthAfter / widthBefore + (float)heightAfter / heightBefore) / 2; - - fontSize *= factor; - } - - /// - /// Override the parent, calculate the label number, than draw - /// - /// - /// - public override void Draw(Graphics graphics, RenderMode rm) - { - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.PixelOffsetMode = PixelOffsetMode.None; - graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit; - string text = ((Surface)Parent).CountStepLabels(this).ToString(); - Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); - Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR); - Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR); - if (_drawAsRectangle) - { - RectangleContainer.DrawRectangle(rect, graphics, rm, 0, Color.Transparent, fillColor, false); - } - else - { - EllipseContainer.DrawEllipse(rect, graphics, rm, 0, Color.Transparent, fillColor, false); - } - using (FontFamily fam = new FontFamily(FontFamily.GenericSansSerif.Name)) - { - using (Font _font = new Font(fam, fontSize, FontStyle.Bold, GraphicsUnit.Pixel)) - { - TextContainer.DrawText(graphics, rect, 0, lineColor, false, _stringFormat, text, _font); - } - } - } - - public override bool ClickableAt(int x, int y) - { - Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); - Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR); - if (_drawAsRectangle) - { - return RectangleContainer.RectangleClickableAt(rect, 0, fillColor, x, y); - } - else - { - return EllipseContainer.EllipseClickableAt(rect, 0, fillColor, x, y); - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/Surface.cs b/Greenshot.ImageEditor/Drawing/Surface.cs deleted file mode 100644 index 613a737d7..000000000 --- a/Greenshot.ImageEditor/Drawing/Surface.cs +++ /dev/null @@ -1,2026 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Core; -using Greenshot.Drawing.Fields; -using Greenshot.Helpers; -using Greenshot.IniFile; -using Greenshot.Memento; -using Greenshot.Plugin; -using Greenshot.Plugin.Drawing; -using GreenshotPlugin; -using GreenshotPlugin.Controls; -using GreenshotPlugin.Core; -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Imaging; -using System.IO; -using System.Runtime.Serialization.Formatters.Binary; -using System.Windows.Forms; - -namespace Greenshot.Drawing -{ - /// - /// Description of Surface. - /// - public class Surface : Control, ISurface - { - public static int Count; - private static readonly CoreConfiguration conf = IniConfig.GetIniSection(); - - // Property to identify the Surface ID - private Guid _uniqueId = Guid.NewGuid(); - - /// - /// The GUID of the surface - /// - public Guid ID - { - get - { - return _uniqueId; - } - set - { - _uniqueId = value; - } - } - - /// - /// Event handlers (do not serialize!) - /// - [NonSerialized] - private SurfaceElementEventHandler _movingElementChanged; - public event SurfaceElementEventHandler MovingElementChanged - { - add - { - _movingElementChanged += value; - } - remove - { - _movingElementChanged -= value; - } - } - [NonSerialized] - private SurfaceDrawingModeEventHandler _drawingModeChanged; - public event SurfaceDrawingModeEventHandler DrawingModeChanged - { - add - { - _drawingModeChanged += value; - } - remove - { - _drawingModeChanged -= value; - } - } - [NonSerialized] - private SurfaceSizeChangeEventHandler _surfaceSizeChanged; - public event SurfaceSizeChangeEventHandler SurfaceSizeChanged - { - add - { - _surfaceSizeChanged += value; - } - remove - { - _surfaceSizeChanged -= value; - } - } - [NonSerialized] - private SurfaceMessageEventHandler _surfaceMessage; - public event SurfaceMessageEventHandler SurfaceMessage - { - add - { - _surfaceMessage += value; - } - remove - { - _surfaceMessage -= value; - } - } - - /// - /// inUndoRedo makes sure we don't undo/redo while in a undo/redo action - /// - [NonSerialized] - private bool _inUndoRedo; - - /// - /// Make only one surfacemove cycle undoable, see SurfaceMouseMove - /// - [NonSerialized] - private bool _isSurfaceMoveMadeUndoable; - - /// - /// Undo/Redo stacks, should not be serialized as the file would be way to big - /// - [NonSerialized] - private readonly Stack _undoStack = new Stack(); - [NonSerialized] - private readonly Stack _redoStack = new Stack(); - - /// - /// Last save location, do not serialize! - /// - [NonSerialized] - private string _lastSaveFullPath; - - /// - /// current drawing mode, do not serialize! - /// - [NonSerialized] - private DrawingModes _drawingMode = DrawingModes.None; - - /// - /// the keyslocked flag helps with focus issues - /// - [NonSerialized] - private bool _keysLocked; - - /// - /// Location of the mouse-down (it "starts" here), do not serialize - /// - [NonSerialized] - private Point _mouseStart = Point.Empty; - - /// - /// are we in a mouse down, do not serialize - /// - [NonSerialized] - private bool _mouseDown; - - /// - /// The selected element for the mouse down, do not serialize - /// - [NonSerialized] - private IDrawableContainer _mouseDownElement; - - /// - /// all selected elements, do not serialize - /// - [NonSerialized] - private readonly DrawableContainerList selectedElements; - - /// - /// the element we are drawing with, do not serialize - /// - [NonSerialized] - private IDrawableContainer _drawingElement; - - /// - /// the element we want to draw with (not yet drawn), do not serialize - /// - [NonSerialized] - private IDrawableContainer _undrawnElement; - - /// - /// the cropcontainer, when cropping this is set, do not serialize - /// - [NonSerialized] - private IDrawableContainer _cropContainer; - - /// - /// the brush which is used for transparent backgrounds, set by the editor, do not serialize - /// - [NonSerialized] - private Brush _transparencyBackgroundBrush; - - /// - /// The buffer is only for drawing on it when using filters (to supply access) - /// This saves a lot of "create new bitmap" commands - /// Should not be serialized, as it's generated. - /// The actual bitmap is in the paintbox... - /// Check if this buffer is still needed! - /// - [NonSerialized] - private Bitmap _buffer; - - /// - /// all stepLabels for the surface, needed with serialization - /// - private readonly List _stepLabels = new List(); - - public void AddStepLabel(StepLabelContainer stepLabel) - { - _stepLabels.Add(stepLabel); - } - - public void RemoveStepLabel(StepLabelContainer stepLabel) - { - _stepLabels.Remove(stepLabel); - } - - /// - /// Count all the VISIBLE steplabels in the surface, up to the supplied one - /// - /// can be null, if not the counting stops here - /// number of steplabels before the supplied container - public int CountStepLabels(IDrawableContainer stopAtContainer) - { - int number = 1; - foreach (var possibleThis in _stepLabels) - { - if (possibleThis.Equals(stopAtContainer)) - { - break; - } - if (IsOnSurface(possibleThis)) - { - number++; - } - } - return number; - } - - /// - /// all elements on the surface, needed with serialization - /// - private readonly DrawableContainerList _elements; - - /// - /// all elements on the surface, needed with serialization - /// - private FieldAggregator _fieldAggregator = new FieldAggregator(); - - /// - /// the cursor container, needed with serialization as we need a direct acces to it. - /// - private IDrawableContainer _cursorContainer; - - /// - /// the capture details, needed with serialization - /// - private ICaptureDetails _captureDetails; - - /// - /// the modified flag specifies if the surface has had modifications after the last export. - /// Initial state is modified, as "it's not saved" - /// After serialization this should actually be "false" (the surface came from a stream) - /// For now we just serialize it... - /// - private bool _modified = true; - - /// - /// The image is the actual captured image, needed with serialization - /// - private Image _image; - public Image Image - { - get - { - return _image; - } - set - { - _image = value; - Size = _image.Size; - } - } - - /// - /// The field aggregator is that which is used to have access to all the fields inside the currently selected elements. - /// e.g. used to decided if and which line thickness is shown when multiple elements are selected. - /// - public FieldAggregator FieldAggregator - { - get - { - return _fieldAggregator; - } - set - { - _fieldAggregator = value; - } - } - - /// - /// The cursor container has it's own accessor so we can find and remove this (when needed) - /// - public IDrawableContainer CursorContainer - { - get - { - return _cursorContainer; - } - } - - /// - /// A simple getter to ask if this surface has a cursor - /// - public bool HasCursor - { - get - { - return _cursorContainer != null; - } - } - - /// - /// A simple helper method to remove the cursor from the surface - /// - public void RemoveCursor() - { - RemoveElement(_cursorContainer, true); - _cursorContainer = null; - } - - /// - /// The brush which is used to draw the transparent background - /// - public Brush TransparencyBackgroundBrush - { - get - { - return _transparencyBackgroundBrush; - } - set - { - _transparencyBackgroundBrush = value; - } - } - - /// - /// Are the keys on this surface locked? - /// - public bool KeysLocked - { - get - { - return _keysLocked; - } - set - { - _keysLocked = value; - } - } - - /// - /// Is this surface modified? This is only true if the surface has not been exported. - /// - public bool Modified - { - get - { - return _modified; - } - set - { - _modified = value; - } - } - - /// - /// The DrawingMode property specifies the mode for drawing, more or less the element type. - /// - public DrawingModes DrawingMode - { - get - { - return _drawingMode; - } - set - { - _drawingMode = value; - if (_drawingModeChanged != null) - { - SurfaceDrawingModeEventArgs eventArgs = new SurfaceDrawingModeEventArgs(); - eventArgs.DrawingMode = _drawingMode; - _drawingModeChanged.Invoke(this, eventArgs); - } - DeselectAllElements(); - CreateUndrawnElement(); - } - } - - /// - /// Property for accessing the last save "full" path - /// - public string LastSaveFullPath - { - get - { - return _lastSaveFullPath; - } - set - { - _lastSaveFullPath = value; - } - } - - /// - /// Property for accessing the URL to which the surface was recently uploaded - /// - public string UploadURL - { - get; - set; - } - - /// - /// Property for accessing the capture details - /// - public ICaptureDetails CaptureDetails - { - get - { - return _captureDetails; - } - set - { - _captureDetails = value; - } - } - - /// - /// Base Surface constructor - /// - public Surface() : base() - { - Count++; - _elements = new DrawableContainerList(_uniqueId); - selectedElements = new DrawableContainerList(_uniqueId); - LOG.Debug("Creating surface!"); - MouseDown += SurfaceMouseDown; - MouseUp += SurfaceMouseUp; - MouseMove += SurfaceMouseMove; - MouseDoubleClick += SurfaceDoubleClick; - Paint += SurfacePaint; - AllowDrop = true; - DragDrop += OnDragDrop; - DragEnter += OnDragEnter; - // bind selected & elements to this, otherwise they can't inform of modifications - selectedElements.Parent = this; - _elements.Parent = this; - // Make sure we are visible - Visible = true; - TabStop = false; - // Enable double buffering - DoubleBuffered = true; - SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | ControlStyles.ContainerControl | ControlStyles.OptimizedDoubleBuffer | ControlStyles.SupportsTransparentBackColor, true); - } - - /// - /// Private method, the current image is disposed the new one will stay. - /// - /// The new image - /// true if the old image needs to be disposed, when using undo this should not be true!! - private void SetImage(Image newImage, bool dispose) - { - // Dispose - if (_image != null && dispose) - { - _image.Dispose(); - } - - // Set new values - Image = newImage; - Size = newImage.Size; - - _modified = true; - } - - /// - /// Surface constructor with an image - /// - /// - public Surface(Image newImage) : this() - { - LOG.DebugFormat("Got image with dimensions {0} and format {1}", newImage.Size, newImage.PixelFormat); - SetImage(newImage, true); - } - - /// - /// Surface contructor with a capture - /// - /// - public Surface(ICapture capture) : this(capture.Image) - { - // check if cursor is captured, and visible - if (capture.Cursor != null && capture.CursorVisible) - { - Rectangle cursorRect = new Rectangle(capture.CursorLocation, capture.Cursor.Size); - Rectangle captureRect = new Rectangle(Point.Empty, capture.Image.Size); - // check if cursor is on the capture, otherwise we leave it out. - if (cursorRect.IntersectsWith(captureRect)) - { - _cursorContainer = AddIconContainer(capture.Cursor, capture.CursorLocation.X, capture.CursorLocation.Y); - SelectElement(_cursorContainer); - } - } - // Make sure the image is NOT disposed, we took the reference directly into ourselves - ((Capture)capture).NullImage(); - - _captureDetails = capture.CaptureDetails; - } - - protected override void Dispose(bool disposing) - { - if (disposing) - { - Count--; - LOG.Debug("Disposing surface!"); - if (_buffer != null) - { - _buffer.Dispose(); - _buffer = null; - } - if (_transparencyBackgroundBrush != null) - { - _transparencyBackgroundBrush.Dispose(); - _transparencyBackgroundBrush = null; - } - - // Cleanup undo/redo stacks - while (_undoStack != null && _undoStack.Count > 0) - { - _undoStack.Pop().Dispose(); - } - while (_redoStack != null && _redoStack.Count > 0) - { - _redoStack.Pop().Dispose(); - } - foreach (IDrawableContainer container in _elements) - { - container.Dispose(); - } - if (_undrawnElement != null) - { - _undrawnElement.Dispose(); - _undrawnElement = null; - } - if (_cropContainer != null) - { - _cropContainer.Dispose(); - _cropContainer = null; - } - } - base.Dispose(disposing); - } - - /// - /// Undo the last action - /// - public void Undo() - { - if (_undoStack.Count > 0) - { - _inUndoRedo = true; - IMemento top = _undoStack.Pop(); - _redoStack.Push(top.Restore()); - _inUndoRedo = false; - } - } - - /// - /// Undo an undo (=redo) - /// - public void Redo() - { - if (_redoStack.Count > 0) - { - _inUndoRedo = true; - IMemento top = _redoStack.Pop(); - _undoStack.Push(top.Restore()); - _inUndoRedo = false; - } - } - - /// - /// Returns if the surface can do a undo - /// - public bool CanUndo - { - get - { - return _undoStack.Count > 0; - } - } - - /// - /// Returns if the surface can do a redo - /// - public bool CanRedo - { - get - { - return _redoStack.Count > 0; - } - } - - /// - /// Make an action undo-able - /// - /// The memento implementing the undo - /// Allow changes to be merged - public void MakeUndoable(IMemento memento, bool allowMerge) - { - if (_inUndoRedo) - { - throw new InvalidOperationException("Invoking do within an undo/redo action."); - } - if (memento != null) - { - bool allowPush = true; - if (_undoStack.Count > 0 && allowMerge) - { - // Check if merge is possible - allowPush = !_undoStack.Peek().Merge(memento); - } - if (allowPush) - { - // Clear the redo-stack and dispose - while (_redoStack.Count > 0) - { - _redoStack.Pop().Dispose(); - } - _undoStack.Push(memento); - } - } - } - - /// - /// This saves the elements of this surface to a stream. - /// Is used to save a template of the complete surface - /// - /// - /// - public long SaveElementsToStream(Stream streamWrite) - { - long bytesWritten = 0; - try - { - long lengtBefore = streamWrite.Length; - BinaryFormatter binaryWrite = new BinaryFormatter(); - binaryWrite.Serialize(streamWrite, _elements); - bytesWritten = streamWrite.Length - lengtBefore; - } - catch (Exception e) - { - LOG.Error("Error serializing elements to stream.", e); - } - return bytesWritten; - } - - /// - /// This loads elements from a stream, among others this is used to load a surface. - /// - /// - public void LoadElementsFromStream(Stream streamRead) - { - try - { - BinaryFormatter binaryRead = new BinaryFormatter(); - DrawableContainerList loadedElements = (DrawableContainerList)binaryRead.Deserialize(streamRead); - loadedElements.Parent = this; - // Make sure the steplabels are sorted accoring to their number - _stepLabels.Sort(delegate (StepLabelContainer p1, StepLabelContainer p2) - { - return p1.Number.CompareTo(p2.Number); - }); - DeselectAllElements(); - AddElements(loadedElements); - SelectElements(loadedElements); - FieldAggregator.BindElements(loadedElements); - } - catch (Exception e) - { - LOG.Error("Error serializing elements from stream.", e); - } - } - - /// - /// This is called from the DrawingMode setter, which is not very correct... - /// But here an element is created which is not yet draw, thus "undrawnElement". - /// The element is than used while drawing on the surface. - /// - private void CreateUndrawnElement() - { - if (_undrawnElement != null) - { - FieldAggregator.UnbindElement(_undrawnElement); - } - switch (DrawingMode) - { - case DrawingModes.Rect: - _undrawnElement = new RectangleContainer(this); - break; - case DrawingModes.Ellipse: - _undrawnElement = new EllipseContainer(this); - break; - case DrawingModes.Text: - _undrawnElement = new TextContainer(this); - break; - case DrawingModes.SpeechBubble: - _undrawnElement = new SpeechbubbleContainer(this); - break; - case DrawingModes.StepLabel: - _undrawnElement = new StepLabelContainer(this); - break; - case DrawingModes.Line: - _undrawnElement = new LineContainer(this); - break; - case DrawingModes.Arrow: - _undrawnElement = new ArrowContainer(this); - break; - case DrawingModes.Highlight: - _undrawnElement = new HighlightContainer(this); - break; - case DrawingModes.Obfuscate: - _undrawnElement = new ObfuscateContainer(this); - break; - case DrawingModes.Crop: - _cropContainer = new CropContainer(this); - _undrawnElement = _cropContainer; - break; - case DrawingModes.Bitmap: - _undrawnElement = new ImageContainer(this); - break; - case DrawingModes.Path: - _undrawnElement = new FreehandContainer(this); - break; - case DrawingModes.None: - _undrawnElement = null; - break; - } - if (_undrawnElement != null) - { - FieldAggregator.BindElement(_undrawnElement); - } - } - - #region Plugin interface implementations - - public IImageContainer AddImageContainer(Image image, int x, int y) - { - ImageContainer bitmapContainer = new ImageContainer(this); - bitmapContainer.Image = image; - bitmapContainer.Left = x; - bitmapContainer.Top = y; - AddElement(bitmapContainer); - return bitmapContainer; - } - - public IImageContainer AddImageContainer(string filename, int x, int y) - { - ImageContainer bitmapContainer = new ImageContainer(this); - bitmapContainer.Load(filename); - bitmapContainer.Left = x; - bitmapContainer.Top = y; - AddElement(bitmapContainer); - return bitmapContainer; - } - - public IIconContainer AddIconContainer(Icon icon, int x, int y) - { - IconContainer iconContainer = new IconContainer(this); - iconContainer.Icon = icon; - iconContainer.Left = x; - iconContainer.Top = y; - AddElement(iconContainer); - return iconContainer; - } - - public IIconContainer AddIconContainer(string filename, int x, int y) - { - IconContainer iconContainer = new IconContainer(this); - iconContainer.Load(filename); - iconContainer.Left = x; - iconContainer.Top = y; - AddElement(iconContainer); - return iconContainer; - } - - public ICursorContainer AddCursorContainer(Cursor cursor, int x, int y) - { - CursorContainer cursorContainer = new CursorContainer(this); - cursorContainer.Cursor = cursor; - cursorContainer.Left = x; - cursorContainer.Top = y; - AddElement(cursorContainer); - return cursorContainer; - } - - public ICursorContainer AddCursorContainer(string filename, int x, int y) - { - CursorContainer cursorContainer = new CursorContainer(this); - cursorContainer.Load(filename); - cursorContainer.Left = x; - cursorContainer.Top = y; - AddElement(cursorContainer); - return cursorContainer; - } - - public ITextContainer AddTextContainer(string text, HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment, FontFamily family, float size, bool italic, bool bold, bool shadow, int borderSize, Color color, Color fillColor) - { - TextContainer textContainer = new TextContainer(this); - textContainer.Text = text; - textContainer.SetFieldValue(FieldType.FONT_FAMILY, family.Name); - textContainer.SetFieldValue(FieldType.FONT_BOLD, bold); - textContainer.SetFieldValue(FieldType.FONT_ITALIC, italic); - textContainer.SetFieldValue(FieldType.FONT_SIZE, size); - textContainer.SetFieldValue(FieldType.FILL_COLOR, fillColor); - textContainer.SetFieldValue(FieldType.LINE_COLOR, color); - textContainer.SetFieldValue(FieldType.LINE_THICKNESS, borderSize); - textContainer.SetFieldValue(FieldType.SHADOW, shadow); - // Make sure the Text fits - textContainer.FitToText(); - // Align to Surface - textContainer.AlignToParent(horizontalAlignment, verticalAlignment); - - //AggregatedProperties.UpdateElement(textContainer); - AddElement(textContainer); - return textContainer; - } - - #endregion Plugin interface implementations - - #region DragDrop - - private void OnDragEnter(object sender, DragEventArgs e) - { - if (LOG.IsDebugEnabled) - { - LOG.Debug("DragEnter got following formats: "); - foreach (string format in ClipboardHelper.GetFormats(e.Data)) - { - LOG.Debug(format); - } - } - if ((e.AllowedEffect & DragDropEffects.Copy) != DragDropEffects.Copy) - { - e.Effect = DragDropEffects.None; - } - else - { - if (ClipboardHelper.ContainsImage(e.Data) || ClipboardHelper.ContainsFormat(e.Data, "DragImageBits")) - { - e.Effect = DragDropEffects.Copy; - } - else - { - e.Effect = DragDropEffects.None; - } - } - } - - /// - /// Handle the drag/drop - /// - /// - /// - private void OnDragDrop(object sender, DragEventArgs e) - { - Point mouse = PointToClient(new Point(e.X, e.Y)); - if (e.Data.GetDataPresent("Text")) - { - string possibleUrl = ClipboardHelper.GetText(e.Data); - // 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) - { - AddImageContainer(image, mouse.X, mouse.Y); - return; - } - } - } - } - - foreach (Image image in ClipboardHelper.GetImages(e.Data)) - { - AddImageContainer(image, mouse.X, mouse.Y); - mouse.Offset(10, 10); - image.Dispose(); - } - } - - #endregion DragDrop - - /// - /// Auto crop the image - /// - /// true if cropped - public bool AutoCrop() - { - Rectangle cropRectangle; - using (Image tmpImage = GetImageForExport()) - { - cropRectangle = ImageHelper.FindAutoCropRectangle(tmpImage, conf.AutoCropDifference); - } - if (!IsCropPossible(ref cropRectangle)) - { - return false; - } - DeselectAllElements(); - // Maybe a bit obscure, but the following line creates a drop container - // It's available as "undrawnElement" - DrawingMode = DrawingModes.Crop; - _undrawnElement.Left = cropRectangle.X; - _undrawnElement.Top = cropRectangle.Y; - _undrawnElement.Width = cropRectangle.Width; - _undrawnElement.Height = cropRectangle.Height; - _undrawnElement.Status = EditStatus.UNDRAWN; - AddElement(_undrawnElement); - SelectElement(_undrawnElement); - _drawingElement = null; - _undrawnElement = null; - return true; - } - - /// - /// A simple clear - /// - /// The color for the background - public void Clear(Color newColor) - { - //create a blank bitmap the same size as original - Bitmap newBitmap = ImageHelper.CreateEmptyLike(Image, Color.Empty); - if (newBitmap != null) - { - // Make undoable - MakeUndoable(new SurfaceBackgroundChangeMemento(this, null), false); - SetImage(newBitmap, false); - Invalidate(); - } - } - - /// - /// Apply a bitmap effect to the surface - /// - /// - public void ApplyBitmapEffect(IEffect effect) - { - BackgroundForm backgroundForm = new BackgroundForm("Effect", "Please wait"); - backgroundForm.Show(); - Application.DoEvents(); - try - { - Rectangle imageRectangle = new Rectangle(Point.Empty, Image.Size); - Matrix matrix = new Matrix(); - Image newImage = ImageHelper.ApplyEffect(Image, effect, matrix); - if (newImage != null) - { - // Make sure the elements move according to the offset the effect made the bitmap move - _elements.Transform(matrix); - // Make undoable - MakeUndoable(new SurfaceBackgroundChangeMemento(this, matrix), false); - SetImage(newImage, false); - Invalidate(); - if (_surfaceSizeChanged != null && !imageRectangle.Equals(new Rectangle(Point.Empty, newImage.Size))) - { - _surfaceSizeChanged(this, null); - } - } - else - { - // clean up matrix, as it hasn't been used in the undo stack. - matrix.Dispose(); - } - } - finally - { - // Always close the background form - backgroundForm.CloseDialog(); - } - } - - /// - /// check if a crop is possible - /// - /// - /// true if this is possible - public bool IsCropPossible(ref Rectangle cropRectangle) - { - cropRectangle = GuiRectangle.GetGuiRectangle(cropRectangle.Left, cropRectangle.Top, cropRectangle.Width, cropRectangle.Height); - if (cropRectangle.Left < 0) - { - cropRectangle = new Rectangle(0, cropRectangle.Top, cropRectangle.Width + cropRectangle.Left, cropRectangle.Height); - } - if (cropRectangle.Top < 0) - { - cropRectangle = new Rectangle(cropRectangle.Left, 0, cropRectangle.Width, cropRectangle.Height + cropRectangle.Top); - } - if (cropRectangle.Left + cropRectangle.Width > Width) - { - cropRectangle = new Rectangle(cropRectangle.Left, cropRectangle.Top, Width - cropRectangle.Left, cropRectangle.Height); - } - if (cropRectangle.Top + cropRectangle.Height > Height) - { - cropRectangle = new Rectangle(cropRectangle.Left, cropRectangle.Top, cropRectangle.Width, Height - cropRectangle.Top); - } - if (cropRectangle.Height > 0 && cropRectangle.Width > 0) - { - return true; - } - return false; - } - - /// - /// Use to send any registered SurfaceMessageEventHandler a message, e.g. used for the notification area - /// - /// Who send - /// Type of message - /// Message itself - public void SendMessageEvent(object source, SurfaceMessageTyp messageType, string message) - { - if (_surfaceMessage != null) - { - SurfaceMessageEventArgs eventArgs = new SurfaceMessageEventArgs(); - eventArgs.Message = message; - eventArgs.MessageType = messageType; - eventArgs.Surface = this; - _surfaceMessage(source, eventArgs); - } - } - - /// - /// Crop the surface - /// - /// - /// - public bool ApplyCrop(Rectangle cropRectangle) - { - if (IsCropPossible(ref cropRectangle)) - { - Rectangle imageRectangle = new Rectangle(Point.Empty, Image.Size); - Bitmap tmpImage; - // Make sure we have information, this this fails - try - { - tmpImage = ImageHelper.CloneArea(Image, cropRectangle, PixelFormat.DontCare); - } - catch (Exception ex) - { - ex.Data.Add("CropRectangle", cropRectangle); - ex.Data.Add("Width", Image.Width); - ex.Data.Add("Height", Image.Height); - ex.Data.Add("Pixelformat", Image.PixelFormat); - throw; - } - - Matrix matrix = new Matrix(); - matrix.Translate(-cropRectangle.Left, -cropRectangle.Top, MatrixOrder.Append); - // Make undoable - MakeUndoable(new SurfaceBackgroundChangeMemento(this, matrix), false); - - // Do not dispose otherwise we can't undo the image! - SetImage(tmpImage, false); - _elements.Transform(matrix); - if (_surfaceSizeChanged != null && !imageRectangle.Equals(new Rectangle(Point.Empty, tmpImage.Size))) - { - _surfaceSizeChanged(this, null); - } - Invalidate(); - return true; - } - return false; - } - - /// - /// The background here is the captured image. - /// This is called from the SurfaceBackgroundChangeMemento. - /// - /// - /// - public void UndoBackgroundChange(Image previous, Matrix matrix) - { - SetImage(previous, false); - if (matrix != null) - { - _elements.Transform(matrix); - } - if (_surfaceSizeChanged != null) - { - _surfaceSizeChanged(this, null); - } - Invalidate(); - } - - /// - /// This event handler is called when someone presses the mouse on a surface. - /// - /// - /// - private void SurfaceMouseDown(object sender, MouseEventArgs e) - { - _mouseStart = e.Location; - - // check contextmenu - if (e.Button == MouseButtons.Right) - { - DrawableContainerList selectedList = null; - if (selectedElements != null && selectedElements.Count > 0) - { - selectedList = selectedElements; - } - else - { - // Single element - IDrawableContainer rightClickedContainer = _elements.ClickableElementAt(_mouseStart.X, _mouseStart.Y); - if (rightClickedContainer != null) - { - selectedList = new DrawableContainerList(ID); - selectedList.Add(rightClickedContainer); - } - } - if (selectedList != null && selectedList.Count > 0) - { - selectedList.ShowContextMenu(e, this); - } - return; - } - - _mouseDown = true; - _isSurfaceMoveMadeUndoable = false; - - if (_cropContainer != null && (_undrawnElement == null || DrawingMode != DrawingModes.Crop)) - { - RemoveElement(_cropContainer, false); - _cropContainer = null; - _drawingElement = null; - } - - if (_drawingElement == null && DrawingMode != DrawingModes.None) - { - if (_undrawnElement == null) - { - DeselectAllElements(); - if (_undrawnElement == null) - { - CreateUndrawnElement(); - } - } - _drawingElement = _undrawnElement; - // if a new element has been drawn, set location and register it - if (_drawingElement != null) - { - if (_undrawnElement != null) - { - _drawingElement.Status = _undrawnElement.DefaultEditMode; - } - _drawingElement.PropertyChanged += ElementPropertyChanged; - if (!_drawingElement.HandleMouseDown(_mouseStart.X, _mouseStart.Y)) - { - _drawingElement.Left = _mouseStart.X; - _drawingElement.Top = _mouseStart.Y; - } - AddElement(_drawingElement); - _drawingElement.Selected = true; - } - _undrawnElement = null; - } - else - { - // check whether an existing element was clicked - // we save mouse down element separately from selectedElements (checked on mouse up), - // since it could be moved around before it is actually selected - _mouseDownElement = _elements.ClickableElementAt(_mouseStart.X, _mouseStart.Y); - - if (_mouseDownElement != null) - { - _mouseDownElement.Status = EditStatus.MOVING; - } - } - } - - /// - /// This event handle is called when the mouse button is unpressed - /// - /// - /// - private void SurfaceMouseUp(object sender, MouseEventArgs e) - { - Point currentMouse = new Point(e.X, e.Y); - - _elements.Status = EditStatus.IDLE; - if (_mouseDownElement != null) - { - _mouseDownElement.Status = EditStatus.IDLE; - } - _mouseDown = false; - _mouseDownElement = null; - if (DrawingMode == DrawingModes.None) - { - // check whether an existing element was clicked - IDrawableContainer element = _elements.ClickableElementAt(currentMouse.X, currentMouse.Y); - bool shiftModifier = (ModifierKeys & Keys.Shift) == Keys.Shift; - if (element != null) - { - element.Invalidate(); - bool alreadySelected = selectedElements.Contains(element); - if (shiftModifier) - { - if (alreadySelected) - { - DeselectElement(element); - } - else - { - SelectElement(element); - } - } - else - { - if (!alreadySelected) - { - DeselectAllElements(); - SelectElement(element); - } - } - } - else if (!shiftModifier) - { - DeselectAllElements(); - } - } - - if (selectedElements.Count > 0) - { - selectedElements.ShowGrippers(); - selectedElements.Selected = true; - } - - if (_drawingElement != null) - { - if (!_drawingElement.InitContent()) - { - _elements.Remove(_drawingElement); - _drawingElement.Invalidate(); - } - else - { - _drawingElement.HandleMouseUp(currentMouse.X, currentMouse.Y); - _drawingElement.Invalidate(); - if (Math.Abs(_drawingElement.Width) < 5 && Math.Abs(_drawingElement.Height) < 5) - { - _drawingElement.Width = 25; - _drawingElement.Height = 25; - } - SelectElement(_drawingElement); - _drawingElement.Selected = true; - } - _drawingElement = null; - } - } - - /// - /// This event handler is called when the mouse moves over the surface - /// - /// - /// - private void SurfaceMouseMove(object sender, MouseEventArgs e) - { - Point currentMouse = e.Location; - - if (DrawingMode != DrawingModes.None) - { - Cursor = Cursors.Cross; - } - else - { - Cursor = Cursors.Default; - } - - if (_mouseDown) - { - if (_mouseDownElement != null) - { // an element is currently dragged - _mouseDownElement.Invalidate(); - selectedElements.HideGrippers(); - // Move the element - if (_mouseDownElement.Selected) - { - if (!_isSurfaceMoveMadeUndoable) - { - // Only allow one undoable per mouse-down/move/up "cycle" - _isSurfaceMoveMadeUndoable = true; - selectedElements.MakeBoundsChangeUndoable(false); - } - // dragged element has been selected before -> move all - selectedElements.MoveBy(currentMouse.X - _mouseStart.X, currentMouse.Y - _mouseStart.Y); - } - else - { - if (!_isSurfaceMoveMadeUndoable) - { - // Only allow one undoable per mouse-down/move/up "cycle" - _isSurfaceMoveMadeUndoable = true; - _mouseDownElement.MakeBoundsChangeUndoable(false); - } - // dragged element is not among selected elements -> just move dragged one - _mouseDownElement.MoveBy(currentMouse.X - _mouseStart.X, currentMouse.Y - _mouseStart.Y); - } - _mouseStart = currentMouse; - _mouseDownElement.Invalidate(); - _modified = true; - } - else if (_drawingElement != null) - { - _drawingElement.HandleMouseMove(currentMouse.X, currentMouse.Y); - _modified = true; - } - } - } - - /// - /// This event handler is called when the surface is double clicked. - /// - /// - /// - private void SurfaceDoubleClick(object sender, MouseEventArgs e) - { - selectedElements.OnDoubleClick(); - selectedElements.Invalidate(); - } - - /// - /// Privately used to get the rendered image with all the elements on it. - /// - /// - /// - private Image GetImage(RenderMode renderMode) - { - // Generate a copy of the original image with a dpi equal to the default... - Bitmap clone = ImageHelper.Clone(_image, PixelFormat.DontCare); - // otherwise we would have a problem drawing the image to the surface... :( - using (Graphics graphics = Graphics.FromImage(clone)) - { - // Do not set the following, the containers need to decide themselves - //graphics.SmoothingMode = SmoothingMode.HighQuality; - //graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - //graphics.CompositingQuality = CompositingQuality.HighQuality; - //graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - _elements.Draw(graphics, clone, renderMode, new Rectangle(Point.Empty, clone.Size)); - } - return clone; - } - - /// - /// This returns the image "result" of this surface, with all the elements rendered on it. - /// - /// - public Image GetImageForExport() - { - return GetImage(RenderMode.EXPORT); - } - - /// - /// This is the event handler for the Paint Event, try to draw as little as possible! - /// - /// - /// - private void SurfacePaint(object sender, PaintEventArgs e) - { - Graphics targetGraphics = e.Graphics; - Rectangle clipRectangle = e.ClipRectangle; - if (Rectangle.Empty.Equals(clipRectangle)) - { - LOG.Debug("Empty cliprectangle??"); - return; - } - - if (_elements.HasIntersectingFilters(clipRectangle)) - { - if (_buffer != null) - { - if (_buffer.Width != Image.Width || _buffer.Height != Image.Height || _buffer.PixelFormat != Image.PixelFormat) - { - _buffer.Dispose(); - _buffer = null; - } - } - if (_buffer == null) - { - _buffer = ImageHelper.CreateEmpty(Image.Width, Image.Height, Image.PixelFormat, Color.Empty, Image.HorizontalResolution, Image.VerticalResolution); - LOG.DebugFormat("Created buffer with size: {0}x{1}", Image.Width, Image.Height); - } - // Elements might need the bitmap, so we copy the part we need - using (Graphics graphics = Graphics.FromImage(_buffer)) - { - // do not set the following, the containers need to decide this themselves! - //graphics.SmoothingMode = SmoothingMode.HighQuality; - //graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - //graphics.CompositingQuality = CompositingQuality.HighQuality; - //graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - DrawBackground(graphics, clipRectangle); - graphics.DrawImage(Image, clipRectangle, clipRectangle, GraphicsUnit.Pixel); - graphics.SetClip(targetGraphics); - _elements.Draw(graphics, _buffer, RenderMode.EDIT, clipRectangle); - } - targetGraphics.DrawImage(_buffer, clipRectangle, clipRectangle, GraphicsUnit.Pixel); - } - else - { - DrawBackground(targetGraphics, clipRectangle); - targetGraphics.DrawImage(Image, clipRectangle, clipRectangle, GraphicsUnit.Pixel); - _elements.Draw(targetGraphics, null, RenderMode.EDIT, clipRectangle); - } - } - - private void DrawBackground(Graphics targetGraphics, Rectangle clipRectangle) - { - // check if we need to draw the checkerboard - if (Image.IsAlphaPixelFormat(Image.PixelFormat) && _transparencyBackgroundBrush != null) - { - targetGraphics.FillRectangle(_transparencyBackgroundBrush, clipRectangle); - } - else - { - targetGraphics.Clear(BackColor); - } - } - - /// - /// Draw a checkboard when capturing with transparency - /// - /// PaintEventArgs - protected override void OnPaintBackground(PaintEventArgs e) - { - } - - /// - /// Wrapper for makeUndoable flag which was introduced later, will call AddElement with makeundoable set to true - /// - /// the new element - public void AddElement(IDrawableContainer element) - { - AddElement(element, true); - } - - /// - /// Add a new element to the surface - /// - /// the new element - /// true if the adding should be undoable - public void AddElement(IDrawableContainer element, bool makeUndoable) - { - _elements.Add(element); - DrawableContainer container = element as DrawableContainer; - if (container != null) - { - container.FieldChanged += element_FieldChanged; - } - element.PropertyChanged += ElementPropertyChanged; - if (element.Status == EditStatus.UNDRAWN) - { - element.Status = EditStatus.IDLE; - } - element.Invalidate(); - if (makeUndoable) - { - MakeUndoable(new AddElementMemento(this, element), false); - } - _modified = true; - } - - /// - /// Remove an element of the elements list - /// - /// Element to remove - /// flag specifying if the remove needs to be undoable - public void RemoveElement(IDrawableContainer elementToRemove, bool makeUndoable) - { - DeselectElement(elementToRemove); - _elements.Remove(elementToRemove); - DrawableContainer element = elementToRemove as DrawableContainer; - if (element != null) - { - element.FieldChanged -= element_FieldChanged; - } - elementToRemove.PropertyChanged -= ElementPropertyChanged; - // Do not dispose, the memento should!! element.Dispose(); - Invalidate(); - if (makeUndoable) - { - MakeUndoable(new DeleteElementMemento(this, elementToRemove), false); - } - _modified = true; - } - - /// - /// Add the supplied elements to the surface - /// - /// - public void AddElements(DrawableContainerList elementsToAdd) - { - foreach (IDrawableContainer element in elementsToAdd) - { - AddElement(element, true); - } - } - - /// - /// Returns if this surface has selected elements - /// - /// - public bool HasSelectedElements - { - get - { - return selectedElements != null && selectedElements.Count > 0; - } - } - - /// - /// Remove all the selected elements - /// - public void RemoveSelectedElements() - { - if (HasSelectedElements) - { - // As RemoveElement will remove the element from the selectedElements list we need to copy the element - // to another list. - List elementsToRemove = new List(); - foreach (DrawableContainer element in selectedElements) - { - // Collect to remove later - elementsToRemove.Add(element); - } - // Remove now - foreach (DrawableContainer element in elementsToRemove) - { - RemoveElement(element, true); - } - selectedElements.Clear(); - if (_movingElementChanged != null) - { - SurfaceElementEventArgs eventArgs = new SurfaceElementEventArgs(); - eventArgs.Elements = selectedElements; - _movingElementChanged(this, eventArgs); - } - } - } - - /// - /// Cut the selected elements from the surface to the clipboard - /// - public void CutSelectedElements() - { - if (HasSelectedElements) - { - ClipboardHelper.SetClipboardData(typeof(DrawableContainerList), selectedElements); - RemoveSelectedElements(); - } - } - - /// - /// Copy the selected elements to the clipboard - /// - public void CopySelectedElements() - { - if (HasSelectedElements) - { - ClipboardHelper.SetClipboardData(typeof(DrawableContainerList), selectedElements); - } - } - - /// - /// This method is called to confirm/cancel "confirmable" elements, like the crop-container. - /// Called when pressing enter or using the "check" in the editor. - /// - /// - public void ConfirmSelectedConfirmableElements(bool confirm) - { - // create new collection so that we can iterate safely (selectedElements might change due with confirm/cancel) - List selectedDCs = new List(selectedElements); - if (_cropContainer == null) - { - return; - } - foreach (IDrawableContainer dc in selectedDCs) - { - if (dc.Equals(_cropContainer)) - { - DrawingMode = DrawingModes.None; - // No undo memento for the cropcontainer itself, only for the effect - RemoveElement(_cropContainer, false); - if (confirm) - { - ApplyCrop(_cropContainer.Bounds); - } - _cropContainer.Dispose(); - _cropContainer = null; - break; - } - } - } - - /// - /// Paste all the elements that are on the clipboard - /// - public void PasteElementFromClipboard() - { - IDataObject clipboard = ClipboardHelper.GetDataObject(); - - List formats = ClipboardHelper.GetFormats(clipboard); - if (formats == null || formats.Count == 0) - { - return; - } - - if (LOG.IsDebugEnabled) - { - LOG.Debug("List of clipboard formats available for pasting:"); - foreach (string format in formats) - { - LOG.Debug("\tgot format: " + format); - } - } - - if (formats.Contains(typeof(DrawableContainerList).FullName)) - { - DrawableContainerList dcs = (DrawableContainerList)ClipboardHelper.GetFromDataObject(clipboard, typeof(DrawableContainerList)); - if (dcs != null) - { - // Make element(s) only move 10,10 if the surface is the same - Point moveOffset; - bool isSameSurface = dcs.ParentID == _uniqueId; - dcs.Parent = this; - if (isSameSurface) - { - moveOffset = new Point(10, 10); - } - else - { - moveOffset = Point.Empty; - } - // Here a fix for bug #1475, first calculate the bounds of the complete DrawableContainerList - Rectangle drawableContainerListBounds = Rectangle.Empty; - foreach (IDrawableContainer element in dcs) - { - if (drawableContainerListBounds == Rectangle.Empty) - { - drawableContainerListBounds = element.DrawingBounds; - } - else - { - drawableContainerListBounds = Rectangle.Union(drawableContainerListBounds, element.DrawingBounds); - } - } - // And find a location inside the target surface to paste to - bool containersCanFit = drawableContainerListBounds.Width < Bounds.Width && drawableContainerListBounds.Height < Bounds.Height; - if (!containersCanFit) - { - Point containersLocation = drawableContainerListBounds.Location; - containersLocation.Offset(moveOffset); - if (!Bounds.Contains(containersLocation)) - { - // Easy fix for same surface - if (isSameSurface) - { - moveOffset = new Point(-10, -10); - } - else - { - // For different surface, which is most likely smaller, we move to "10,10" - moveOffset = new Point(-drawableContainerListBounds.Location.X + 10, -drawableContainerListBounds.Location.Y + 10); - } - } - } - else - { - Rectangle moveContainerListBounds = drawableContainerListBounds; - moveContainerListBounds.Offset(moveOffset); - // check if the element is inside - if (!Bounds.Contains(moveContainerListBounds)) - { - // Easy fix for same surface - if (isSameSurface) - { - moveOffset = new Point(-10, -10); - } - else - { - // For different surface, which is most likely smaller - int offsetX = 0; - int offsetY = 0; - if (drawableContainerListBounds.Right > Bounds.Right) - { - offsetX = Bounds.Right - drawableContainerListBounds.Right; - // Correction for the correction - if (drawableContainerListBounds.Left + offsetX < 0) - { - offsetX += Math.Abs(drawableContainerListBounds.Left + offsetX); - } - } - if (drawableContainerListBounds.Bottom > Bounds.Bottom) - { - offsetY = Bounds.Bottom - drawableContainerListBounds.Bottom; - // Correction for the correction - if (drawableContainerListBounds.Top + offsetY < 0) - { - offsetY += Math.Abs(drawableContainerListBounds.Top + offsetY); - } - } - moveOffset = new Point(offsetX, offsetY); - } - } - } - dcs.MoveBy(moveOffset.X, moveOffset.Y); - AddElements(dcs); - FieldAggregator.BindElements(dcs); - DeselectAllElements(); - SelectElements(dcs); - } - } - else if (ClipboardHelper.ContainsImage(clipboard)) - { - int x = 10; - int y = 10; - foreach (Image clipboardImage in ClipboardHelper.GetImages(clipboard)) - { - if (clipboardImage != null) - { - DeselectAllElements(); - IImageContainer container = AddImageContainer(clipboardImage as Bitmap, x, y); - SelectElement(container); - clipboardImage.Dispose(); - x += 10; - y += 10; - } - } - } - else if (ClipboardHelper.ContainsText(clipboard)) - { - string text = ClipboardHelper.GetText(clipboard); - if (text != null) - { - DeselectAllElements(); - ITextContainer textContainer = AddTextContainer(text, HorizontalAlignment.Center, VerticalAlignment.CENTER, - FontFamily.GenericSansSerif, 12f, false, false, false, 2, Color.Black, Color.Transparent); - SelectElement(textContainer); - } - } - } - - /// - /// Duplicate all the selecteded elements - /// - public void DuplicateSelectedElements() - { - LOG.DebugFormat("Duplicating {0} selected elements", selectedElements.Count); - DrawableContainerList dcs = selectedElements.Clone(); - dcs.Parent = this; - dcs.MoveBy(10, 10); - AddElements(dcs); - DeselectAllElements(); - SelectElements(dcs); - } - - /// - /// Deselect the specified element - /// - /// - public void DeselectElement(IDrawableContainer container) - { - container.HideGrippers(); - container.Selected = false; - selectedElements.Remove(container); - FieldAggregator.UnbindElement(container); - if (_movingElementChanged != null) - { - SurfaceElementEventArgs eventArgs = new SurfaceElementEventArgs(); - eventArgs.Elements = selectedElements; - _movingElementChanged(this, eventArgs); - } - } - - /// - /// Deselect all the selected elements - /// - public void DeselectAllElements() - { - if (HasSelectedElements) - { - while (selectedElements.Count > 0) - { - IDrawableContainer element = selectedElements[0]; - element.Invalidate(); - element.HideGrippers(); - element.Selected = false; - selectedElements.Remove(element); - FieldAggregator.UnbindElement(element); - } - if (_movingElementChanged != null) - { - SurfaceElementEventArgs eventArgs = new SurfaceElementEventArgs(); - eventArgs.Elements = selectedElements; - _movingElementChanged(this, eventArgs); - } - } - } - - /// - /// Select the supplied element - /// - /// - public void SelectElement(IDrawableContainer container) - { - if (!selectedElements.Contains(container)) - { - selectedElements.Add(container); - container.ShowGrippers(); - container.Selected = true; - FieldAggregator.BindElement(container); - if (_movingElementChanged != null) - { - SurfaceElementEventArgs eventArgs = new SurfaceElementEventArgs(); - eventArgs.Elements = selectedElements; - _movingElementChanged(this, eventArgs); - } - container.Invalidate(); - } - } - - /// - /// Select all elements, this is called when Ctrl+A is pressed - /// - public void SelectAllElements() - { - SelectElements(_elements); - } - - /// - /// Select the supplied elements - /// - /// - public void SelectElements(DrawableContainerList elements) - { - foreach (DrawableContainer element in elements) - { - SelectElement(element); - } - } - - /// - /// Process key presses on the surface, this is called from the editor (and NOT an override from the Control) - /// - /// Keys - /// false if no keys were processed - public bool ProcessCmdKey(Keys k) - { - if (selectedElements.Count > 0) - { - bool shiftModifier = (ModifierKeys & Keys.Shift) == Keys.Shift; - int px = shiftModifier ? 10 : 1; - Point moveBy = Point.Empty; - - switch (k) - { - case Keys.Left: - case Keys.Left | Keys.Shift: - moveBy = new Point(-px, 0); - break; - case Keys.Up: - case Keys.Up | Keys.Shift: - moveBy = new Point(0, -px); - break; - case Keys.Right: - case Keys.Right | Keys.Shift: - moveBy = new Point(px, 0); - break; - case Keys.Down: - case Keys.Down | Keys.Shift: - moveBy = new Point(0, px); - break; - case Keys.PageUp: - PullElementsUp(); - break; - case Keys.PageDown: - PushElementsDown(); - break; - case Keys.Home: - PullElementsToTop(); - break; - case Keys.End: - PushElementsToBottom(); - break; - case Keys.Enter: - ConfirmSelectedConfirmableElements(true); - break; - case Keys.Escape: - ConfirmSelectedConfirmableElements(false); - break; - /*case Keys.Delete: - RemoveSelectedElements(); - break;*/ - default: - return false; - } - if (!Point.Empty.Equals(moveBy)) - { - selectedElements.MakeBoundsChangeUndoable(true); - selectedElements.MoveBy(moveBy.X, moveBy.Y); - } - return true; - } - return false; - } - - /// - /// Property for accessing the elements on the surface - /// - public DrawableContainerList Elements - { - get - { - return _elements; - } - } - - /// - /// pulls selected elements up one level in hierarchy - /// - public void PullElementsUp() - { - _elements.PullElementsUp(selectedElements); - _elements.Invalidate(); - } - - /// - /// pushes selected elements up to top in hierarchy - /// - public void PullElementsToTop() - { - _elements.PullElementsToTop(selectedElements); - _elements.Invalidate(); - } - - /// - /// pushes selected elements down one level in hierarchy - /// - public void PushElementsDown() - { - _elements.PushElementsDown(selectedElements); - _elements.Invalidate(); - } - - /// - /// pushes selected elements down to bottom in hierarchy - /// - public void PushElementsToBottom() - { - _elements.PushElementsToBottom(selectedElements); - _elements.Invalidate(); - } - - /// - /// indicates whether the selected elements could be pulled up in hierarchy - /// - /// true if selected elements could be pulled up, false otherwise - public bool CanPullSelectionUp() - { - return _elements.CanPullUp(selectedElements); - } - - /// - /// indicates whether the selected elements could be pushed down in hierarchy - /// - /// true if selected elements could be pushed down, false otherwise - public bool CanPushSelectionDown() - { - return _elements.CanPushDown(selectedElements); - } - - public void ElementPropertyChanged(object sender, PropertyChangedEventArgs e) - { - //Invalidate(); - } - - public void element_FieldChanged(object sender, FieldChangedEventArgs e) - { - selectedElements.HandleFieldChangedEvent(sender, e); - } - - public bool IsOnSurface(IDrawableContainer container) - { - return _elements.Contains(container); - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Drawing/TextContainer.cs b/Greenshot.ImageEditor/Drawing/TextContainer.cs deleted file mode 100644 index 7c385524c..000000000 --- a/Greenshot.ImageEditor/Drawing/TextContainer.cs +++ /dev/null @@ -1,547 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Drawing.Fields; -using Greenshot.Helpers; -using Greenshot.Memento; -using Greenshot.Plugin.Drawing; -using System; -using System.ComponentModel; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Text; -using System.Runtime.Serialization; -using System.Windows.Forms; - -namespace Greenshot.Drawing -{ - /// - /// Represents a textbox (extends RectangleContainer for border/background support - /// - [Serializable] - public class TextContainer : RectangleContainer, ITextContainer - { - // If makeUndoable is true the next text-change will make the change undoable. - // This is set to true AFTER the first change is made, as there is already a "add element" on the undo stack - private bool makeUndoable; - [NonSerialized] - private Font _font; - public Font Font - { - get - { - return _font; - } - } - - [NonSerialized] - private TextBox _textBox; - - /// - /// The StringFormat object is not serializable!! - /// - [NonSerialized] - private StringFormat _stringFormat = new StringFormat(); - public StringFormat StringFormat - { - get - { - return _stringFormat; - } - } - private string text; - // there is a binding on the following property! - public string Text - { - get { return text; } - set { ChangeText(value, true); } - } - - internal void ChangeText(string newText, bool allowUndoable) - { - if ((text == null && newText != null) || (text != null && !string.Equals(text, newText))) - { - if (makeUndoable && allowUndoable) - { - makeUndoable = false; - _parent.MakeUndoable(new TextChangeMemento(this), false); - } - text = newText; - OnPropertyChanged("Text"); - } - } - - public TextContainer(Surface parent) : base(parent) - { - Init(); - } - - protected override void InitializeFields() - { - AddField(GetType(), FieldType.LINE_THICKNESS, 2); - AddField(GetType(), FieldType.LINE_COLOR, DefaultLineColor); - AddField(GetType(), FieldType.SHADOW, false); - AddField(GetType(), FieldType.FONT_ITALIC, false); - AddField(GetType(), FieldType.FONT_BOLD, false); - AddField(GetType(), FieldType.FILL_COLOR, Color.White); - AddField(GetType(), FieldType.FONT_FAMILY, FontFamily.GenericSansSerif.Name); - AddField(GetType(), FieldType.FONT_SIZE, 20f); - AddField(GetType(), FieldType.TEXT_HORIZONTAL_ALIGNMENT, StringAlignment.Center); - AddField(GetType(), FieldType.TEXT_VERTICAL_ALIGNMENT, StringAlignment.Center); - } - - [OnDeserialized] - private void OnDeserialized(StreamingContext context) - { - Init(); - } - - protected override void Dispose(bool disposing) - { - if (disposing) - { - if (_font != null) - { - _font.Dispose(); - _font = null; - } - if (_stringFormat != null) - { - _stringFormat.Dispose(); - _stringFormat = null; - } - if (_textBox != null) - { - _textBox.Dispose(); - _textBox = null; - } - } - base.Dispose(disposing); - } - - private void Init() - { - _stringFormat = new StringFormat - { - Trimming = StringTrimming.EllipsisWord - }; - - CreateTextBox(); - - UpdateFormat(); - UpdateTextBoxFormat(); - - PropertyChanged += TextContainer_PropertyChanged; - FieldChanged += TextContainer_FieldChanged; - } - - public override void Invalidate() - { - base.Invalidate(); - if (_textBox != null && _textBox.Visible) - { - _textBox.Invalidate(); - } - } - - public void FitToText() - { - Size textSize = TextRenderer.MeasureText(text, _font); - int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); - Width = textSize.Width + lineThickness; - Height = textSize.Height + lineThickness; - } - - private void TextContainer_PropertyChanged(object sender, PropertyChangedEventArgs e) - { - if (_textBox.Visible) - { - _textBox.Invalidate(); - } - - UpdateTextBoxPosition(); - UpdateTextBoxFormat(); - if (e.PropertyName.Equals("Selected")) - { - if (!Selected && _textBox.Visible) - { - HideTextBox(); - } - else if (Selected && Status == EditStatus.DRAWING) - { - ShowTextBox(); - } - else if (Selected && Status == EditStatus.IDLE && _textBox.Visible) - { - // Fix (workaround) for BUG-1698 - _parent.KeysLocked = true; - } - } - if (_textBox.Visible) - { - _textBox.Invalidate(); - } - } - - private void TextContainer_FieldChanged(object sender, FieldChangedEventArgs e) - { - if (_textBox.Visible) - { - _textBox.Invalidate(); - } - // Only dispose the font, and re-create it, when a font field has changed. - if (e.Field.FieldType.Name.StartsWith("FONT")) - { - if (_font != null) - { - _font.Dispose(); - _font = null; - } - UpdateFormat(); - } - else - { - UpdateAlignment(); - } - UpdateTextBoxFormat(); - - if (_textBox != null && _textBox.Visible) - { - _textBox.Invalidate(); - } - } - - public override void OnDoubleClick() - { - ShowTextBox(); - } - - private void CreateTextBox() - { - _textBox = new TextBox - { - ImeMode = ImeMode.On, - Multiline = true, - AcceptsTab = true, - AcceptsReturn = true, - BorderStyle = BorderStyle.None, - Visible = false - }; - - _textBox.DataBindings.Add("Text", this, "Text", false, DataSourceUpdateMode.OnPropertyChanged); - _textBox.LostFocus += textBox_LostFocus; - _textBox.KeyDown += textBox_KeyDown; - } - - private void ShowTextBox() - { - _parent.KeysLocked = true; - _parent.Controls.Add(_textBox); - EnsureTextBoxContrast(); - _textBox.Show(); - _textBox.Focus(); - } - - /// - /// Makes textbox background dark if text color is very bright - /// - private void EnsureTextBoxContrast() - { - Color lc = GetFieldValueAsColor(FieldType.LINE_COLOR); - if (lc.R > 203 && lc.G > 203 && lc.B > 203) - { - _textBox.BackColor = Color.FromArgb(51, 51, 51); - } - else - { - _textBox.BackColor = Color.White; - } - } - - private void HideTextBox() - { - _parent.Focus(); - _textBox.Hide(); - _parent.KeysLocked = false; - _parent.Controls.Remove(_textBox); - } - - /// - /// Make sure the size of the font is scaled - /// - /// - public override void Transform(Matrix matrix) - { - Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); - int pixelsBefore = rect.Width * rect.Height; - - // Transform this container - base.Transform(matrix); - rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); - - int pixelsAfter = rect.Width * rect.Height; - float factor = pixelsAfter / (float)pixelsBefore; - - float fontSize = GetFieldValueAsFloat(FieldType.FONT_SIZE); - fontSize *= factor; - SetFieldValue(FieldType.FONT_SIZE, fontSize); - UpdateFormat(); - } - - /// - /// Generate the Font-Formal so we can draw correctly - /// - protected void UpdateFormat() - { - string fontFamily = GetFieldValueAsString(FieldType.FONT_FAMILY); - bool fontBold = GetFieldValueAsBool(FieldType.FONT_BOLD); - bool fontItalic = GetFieldValueAsBool(FieldType.FONT_ITALIC); - float fontSize = GetFieldValueAsFloat(FieldType.FONT_SIZE); - try - { - FontStyle fs = FontStyle.Regular; - - bool hasStyle = false; - using (FontFamily fam = new FontFamily(fontFamily)) - { - bool boldAvailable = fam.IsStyleAvailable(FontStyle.Bold); - if (fontBold && boldAvailable) - { - fs |= FontStyle.Bold; - hasStyle = true; - } - - bool italicAvailable = fam.IsStyleAvailable(FontStyle.Italic); - if (fontItalic && italicAvailable) - { - fs |= FontStyle.Italic; - hasStyle = true; - } - - if (!hasStyle) - { - bool regularAvailable = fam.IsStyleAvailable(FontStyle.Regular); - if (regularAvailable) - { - fs = FontStyle.Regular; - } - else - { - if (boldAvailable) - { - fs = FontStyle.Bold; - } - else if (italicAvailable) - { - fs = FontStyle.Italic; - } - } - } - _font?.Dispose(); - _font = new Font(fam, fontSize, fs, GraphicsUnit.Pixel); - _textBox.Font = _font; - } - } - catch (Exception ex) - { - ex.Data.Add("fontFamily", fontFamily); - ex.Data.Add("fontBold", fontBold); - ex.Data.Add("fontItalic", fontItalic); - ex.Data.Add("fontSize", fontSize); - throw; - } - - UpdateAlignment(); - } - - private void UpdateAlignment() - { - _stringFormat.Alignment = (StringAlignment)GetFieldValue(FieldType.TEXT_HORIZONTAL_ALIGNMENT); - _stringFormat.LineAlignment = (StringAlignment)GetFieldValue(FieldType.TEXT_VERTICAL_ALIGNMENT); - } - - /// - /// This will create the textbox exactly to the inner size of the element - /// is a bit of a hack, but for now it seems to work... - /// - private void UpdateTextBoxPosition() - { - int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); - - int lineWidth = (int)Math.Floor(lineThickness / 2d); - int correction = (lineThickness + 1) % 2; - if (lineThickness <= 1) - { - lineWidth = 1; - correction = -1; - } - Rectangle absRectangle = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); - _textBox.Left = absRectangle.Left + lineWidth; - _textBox.Top = absRectangle.Top + lineWidth; - if (lineThickness <= 1) - { - lineWidth = 0; - } - _textBox.Width = absRectangle.Width - 2 * lineWidth + correction; - _textBox.Height = absRectangle.Height - 2 * lineWidth + correction; - } - - public override void ApplyBounds(RectangleF newBounds) - { - base.ApplyBounds(newBounds); - UpdateTextBoxPosition(); - } - - private void UpdateTextBoxFormat() - { - if (_textBox == null) - { - return; - } - StringAlignment alignment = (StringAlignment)GetFieldValue(FieldType.TEXT_HORIZONTAL_ALIGNMENT); - switch (alignment) - { - case StringAlignment.Near: - _textBox.TextAlign = HorizontalAlignment.Left; - break; - case StringAlignment.Far: - _textBox.TextAlign = HorizontalAlignment.Right; - break; - case StringAlignment.Center: - _textBox.TextAlign = HorizontalAlignment.Center; - break; - } - - Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR); - _textBox.ForeColor = lineColor; - } - - private void textBox_KeyDown(object sender, KeyEventArgs e) - { - // ESC and Enter/Return (w/o Shift) hide text editor - if (e.KeyCode == Keys.Escape || ((e.KeyCode == Keys.Return || e.KeyCode == Keys.Enter) && e.Modifiers == Keys.None)) - { - HideTextBox(); - e.SuppressKeyPress = true; - } - } - - private void textBox_LostFocus(object sender, EventArgs e) - { - // next change will be made undoable - makeUndoable = true; - HideTextBox(); - } - - public override void Draw(Graphics graphics, RenderMode rm) - { - base.Draw(graphics, rm); - - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.PixelOffsetMode = PixelOffsetMode.None; - graphics.TextRenderingHint = TextRenderingHint.SystemDefault; - - Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); - if (Selected && rm == RenderMode.EDIT) - { - DrawSelectionBorder(graphics, rect); - } - - if (string.IsNullOrEmpty(text)) - { - return; - } - - // we only draw the shadow if there is no background - bool shadow = GetFieldValueAsBool(FieldType.SHADOW); - Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR); - int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); - Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR); - bool drawShadow = shadow && (fillColor == Color.Transparent || fillColor == Color.Empty); - - DrawText(graphics, rect, lineThickness, lineColor, drawShadow, _stringFormat, text, _font); - } - - /// - /// This method can be used from other containers - /// - /// - /// - /// - /// - /// - /// - /// - /// - public static void DrawText(Graphics graphics, Rectangle drawingRectange, int lineThickness, Color fontColor, bool drawShadow, StringFormat stringFormat, string text, Font font) - { - int textOffset = lineThickness > 0 ? (int)Math.Ceiling(lineThickness / 2d) : 0; - // draw shadow before anything else - if (drawShadow) - { - int basealpha = 100; - int alpha = basealpha; - int steps = 5; - int currentStep = 1; - while (currentStep <= steps) - { - int offset = currentStep; - Rectangle shadowRect = GuiRectangle.GetGuiRectangle(drawingRectange.Left + offset, drawingRectange.Top + offset, drawingRectange.Width, drawingRectange.Height); - if (lineThickness > 0) - { - shadowRect.Inflate(-textOffset, -textOffset); - } - using (Brush fontBrush = new SolidBrush(Color.FromArgb(alpha, 100, 100, 100))) - { - graphics.DrawString(text, font, fontBrush, shadowRect, stringFormat); - currentStep++; - alpha = alpha - basealpha / steps; - } - } - } - - if (lineThickness > 0) - { - drawingRectange.Inflate(-textOffset, -textOffset); - } - using (Brush fontBrush = new SolidBrush(fontColor)) - { - if (stringFormat != null) - { - graphics.DrawString(text, font, fontBrush, drawingRectange, stringFormat); - } - else - { - graphics.DrawString(text, font, fontBrush, drawingRectange); - } - } - } - - public override bool ClickableAt(int x, int y) - { - Rectangle r = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); - r.Inflate(5, 5); - return r.Contains(x, y); - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Forms/AboutForm.Designer.cs b/Greenshot.ImageEditor/Forms/AboutForm.Designer.cs deleted file mode 100644 index 8b39809f5..000000000 --- a/Greenshot.ImageEditor/Forms/AboutForm.Designer.cs +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -namespace Greenshot { - partial class AboutForm { - /// - /// Designer variable used to keep track of non-visual components. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Disposes resources used by the form. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) { - if (disposing) { - if (components != null) { - components.Dispose(); - } - } - base.Dispose(disposing); - } - - /// - /// This method is required for Windows Forms designer support. - /// Do not change the method contents inside the source code editor. The Forms designer might - /// not be able to load this method if it was changed manually. - /// - private void InitializeComponent() { - this.lblTitle = new System.Windows.Forms.Label(); - this.lblLicense = new GreenshotPlugin.Controls.GreenshotLabel(); - this.lblHost = new GreenshotPlugin.Controls.GreenshotLabel(); - this.linkLblLicense = new System.Windows.Forms.LinkLabel(); - this.linkLblHost = new System.Windows.Forms.LinkLabel(); - this.linkLblBugs = new System.Windows.Forms.LinkLabel(); - this.lblBugs = new GreenshotPlugin.Controls.GreenshotLabel(); - this.linkLblDonations = new System.Windows.Forms.LinkLabel(); - this.lblDonations = new GreenshotPlugin.Controls.GreenshotLabel(); - this.linkLblIcons = new System.Windows.Forms.LinkLabel(); - this.lblIcons = new GreenshotPlugin.Controls.GreenshotLabel(); - this.linkLabel1 = new System.Windows.Forms.LinkLabel(); - this.lblTranslation = new GreenshotPlugin.Controls.GreenshotLabel(); - this.SuspendLayout(); - // - // lblTitle - // - this.lblTitle.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.lblTitle.Location = new System.Drawing.Point(13, 12); - this.lblTitle.Name = "lblTitle"; - this.lblTitle.Size = new System.Drawing.Size(145, 19); - this.lblTitle.TabIndex = 2; - this.lblTitle.Text = "Greenshot image editor"; - this.lblTitle.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; - // - // lblLicense - // - this.lblLicense.LanguageKey = ""; - this.lblLicense.Location = new System.Drawing.Point(13, 34); - this.lblLicense.Name = "lblLicense"; - this.lblLicense.Size = new System.Drawing.Size(369, 68); - this.lblLicense.TabIndex = 3; - // - // lblHost - // - this.lblHost.LanguageKey = ""; - this.lblHost.Location = new System.Drawing.Point(12, 109); - this.lblHost.Name = "lblHost"; - this.lblHost.Size = new System.Drawing.Size(466, 23); - this.lblHost.TabIndex = 4; - this.lblHost.Text = "Greenshot is hosted by sourceforge.net at"; - // - // linkLblLicense - // - this.linkLblLicense.Location = new System.Drawing.Point(13, 85); - this.linkLblLicense.Name = "linkLblLicense"; - this.linkLblLicense.Size = new System.Drawing.Size(369, 23); - this.linkLblLicense.TabIndex = 5; - this.linkLblLicense.TabStop = true; - this.linkLblLicense.Text = "http://www.gnu.org/licenses/gpl.html"; - this.linkLblLicense.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.LinkLabelClicked); - // - // linkLblHost - // - this.linkLblHost.Location = new System.Drawing.Point(13, 124); - this.linkLblHost.Name = "linkLblHost"; - this.linkLblHost.Size = new System.Drawing.Size(465, 23); - this.linkLblHost.TabIndex = 6; - this.linkLblHost.TabStop = true; - this.linkLblHost.Text = "http://sourceforge.net/projects/greenshot/"; - this.linkLblHost.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.LinkLabelClicked); - // - // linkLblBugs - // - this.linkLblBugs.Location = new System.Drawing.Point(13, 162); - this.linkLblBugs.Name = "linkLblBugs"; - this.linkLblBugs.Size = new System.Drawing.Size(465, 23); - this.linkLblBugs.TabIndex = 8; - this.linkLblBugs.TabStop = true; - this.linkLblBugs.Text = "http://getgreenshot.org/tickets/"; - this.linkLblBugs.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.LinkLabelClicked); - // - // lblBugs - // - this.lblBugs.LanguageKey = ""; - this.lblBugs.Location = new System.Drawing.Point(12, 147); - this.lblBugs.Name = "lblBugs"; - this.lblBugs.Size = new System.Drawing.Size(466, 23); - this.lblBugs.TabIndex = 7; - this.lblBugs.Text = "Please report bugs to"; - // - // linkLblDonations - // - this.linkLblDonations.Location = new System.Drawing.Point(13, 201); - this.linkLblDonations.Name = "linkLblDonations"; - this.linkLblDonations.Size = new System.Drawing.Size(465, 23); - this.linkLblDonations.TabIndex = 10; - this.linkLblDonations.TabStop = true; - this.linkLblDonations.Text = "http://getgreenshot.org/support/"; - this.linkLblDonations.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.LinkLabelClicked); - // - // lblDonations - // - this.lblDonations.LanguageKey = ""; - this.lblDonations.Location = new System.Drawing.Point(12, 186); - this.lblDonations.Name = "lblDonations"; - this.lblDonations.Size = new System.Drawing.Size(466, 23); - this.lblDonations.TabIndex = 9; - this.lblDonations.Text = "If you like Greenshot, you are welcome to support us:"; - // - // linkLblIcons - // - this.linkLblIcons.Location = new System.Drawing.Point(13, 239); - this.linkLblIcons.Name = "linkLblIcons"; - this.linkLblIcons.Size = new System.Drawing.Size(279, 23); - this.linkLblIcons.TabIndex = 12; - this.linkLblIcons.TabStop = true; - this.linkLblIcons.Text = "http://p.yusukekamiyamane.com"; - this.linkLblIcons.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.LinkLabelClicked); - // - // lblIcons - // - this.lblIcons.LanguageKey = ""; - this.lblIcons.Location = new System.Drawing.Point(12, 224); - this.lblIcons.Name = "lblIcons"; - this.lblIcons.Size = new System.Drawing.Size(530, 23); - this.lblIcons.TabIndex = 11; - this.lblIcons.Text = "Icons from Yusuke Kamiyamane\'s Fugue icon set (Creative Commons Attribution 3.0 l" + - "icense)"; - // - // linkLabel1 - // - this.linkLabel1.Location = new System.Drawing.Point(154, 12); - this.linkLabel1.Name = "linkLabel1"; - this.linkLabel1.Size = new System.Drawing.Size(130, 19); - this.linkLabel1.TabIndex = 13; - this.linkLabel1.TabStop = true; - this.linkLabel1.Text = "http://getgreenshot.org"; - this.linkLabel1.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.LinkLabelClicked); - // - // lblTranslation - // - this.lblTranslation.LanguageKey = "about_translation"; - this.lblTranslation.Location = new System.Drawing.Point(12, 262); - this.lblTranslation.Name = "lblTranslation"; - this.lblTranslation.Size = new System.Drawing.Size(466, 23); - this.lblTranslation.TabIndex = 15; - // - // AboutForm - // - this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; - this.AutoSize = true; - this.ClientSize = new System.Drawing.Size(530, 293); - this.Controls.Add(this.lblTranslation); - this.Controls.Add(this.linkLabel1); - this.Controls.Add(this.linkLblIcons); - this.Controls.Add(this.lblIcons); - this.Controls.Add(this.linkLblDonations); - this.Controls.Add(this.lblDonations); - this.Controls.Add(this.linkLblBugs); - this.Controls.Add(this.lblBugs); - this.Controls.Add(this.linkLblHost); - this.Controls.Add(this.linkLblLicense); - this.Controls.Add(this.lblHost); - this.Controls.Add(this.lblLicense); - this.Controls.Add(this.lblTitle); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "AboutForm"; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; - this.Text = "Greenshot image editor - About"; - this.ResumeLayout(false); - - } - private System.Windows.Forms.LinkLabel linkLabel1; - private System.Windows.Forms.LinkLabel linkLblHost; - private System.Windows.Forms.LinkLabel linkLblDonations; - private System.Windows.Forms.LinkLabel linkLblBugs; - private System.Windows.Forms.LinkLabel linkLblLicense; - private System.Windows.Forms.LinkLabel linkLblIcons; - private System.Windows.Forms.Label lblTitle; - private GreenshotPlugin.Controls.GreenshotLabel lblTranslation; - private GreenshotPlugin.Controls.GreenshotLabel lblHost; - private GreenshotPlugin.Controls.GreenshotLabel lblDonations; - private GreenshotPlugin.Controls.GreenshotLabel lblBugs; - private GreenshotPlugin.Controls.GreenshotLabel lblIcons; - private GreenshotPlugin.Controls.GreenshotLabel lblLicense; - } -} diff --git a/Greenshot.ImageEditor/Forms/AboutForm.cs b/Greenshot.ImageEditor/Forms/AboutForm.cs deleted file mode 100644 index 6f26d6f9b..000000000 --- a/Greenshot.ImageEditor/Forms/AboutForm.cs +++ /dev/null @@ -1,57 +0,0 @@ -/* -* Greenshot - a free and open source screenshot tool -* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom -* -* For more information see: http://getgreenshot.org/ -* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . -*/ - -using GreenshotPlugin.Core; -using System; -using System.Diagnostics; -using System.Windows.Forms; - -namespace Greenshot -{ - public partial class AboutForm : Form - { - public AboutForm() - { - InitializeComponent(); - Icon = GreenshotResources.getGreenshotIcon(); - lblLicense.Text = @"Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom -Greenshot comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions. -Details about the GNU General Public License:"; - } - - private void LinkLabelClicked(object sender, LinkLabelLinkClickedEventArgs e) - { - LinkLabel linkLabel = sender as LinkLabel; - if (linkLabel != null) - { - try - { - linkLabel.LinkVisited = true; - Process.Start(linkLabel.Text); - } - catch (Exception) - { - MessageBox.Show(string.Format("Could not open link '{0}'.", linkLabel.Text), "Error"); - } - } - } - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Forms/BaseForm.cs b/Greenshot.ImageEditor/Forms/BaseForm.cs deleted file mode 100644 index 4d8911b99..000000000 --- a/Greenshot.ImageEditor/Forms/BaseForm.cs +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using GreenshotPlugin.Controls; - -namespace Greenshot -{ - /// - /// This class is only here to help in the Designer mode, so it's clear where the language files are - /// - public class BaseForm : GreenshotForm - { - } -} \ No newline at end of file diff --git a/Greenshot.ImageEditor/Forms/ColorDialog.Designer.cs b/Greenshot.ImageEditor/Forms/ColorDialog.Designer.cs deleted file mode 100644 index eb58ff33e..000000000 --- a/Greenshot.ImageEditor/Forms/ColorDialog.Designer.cs +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -namespace Greenshot { - public partial class ColorDialog { - /// - /// Designer variable used to keep track of non-visual components. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Disposes resources used by the form. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing) { - if (components != null) { - components.Dispose(); - } - } - base.Dispose(disposing); - } - - /// - /// This method is required for Windows Forms designer support. - /// Do not change the method contents inside the source code editor. The Forms designer might - /// not be able to load this method if it was changed manually. - /// - private void InitializeComponent() - { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ColorDialog)); - this.btnTransparent = new GreenshotPlugin.Controls.GreenshotButton(); - this.colorPanel = new System.Windows.Forms.Panel(); - this.labelHtmlColor = new GreenshotPlugin.Controls.GreenshotLabel(); - this.textBoxHtmlColor = new System.Windows.Forms.TextBox(); - this.labelRed = new GreenshotPlugin.Controls.GreenshotLabel(); - this.labelGreen = new GreenshotPlugin.Controls.GreenshotLabel(); - this.labelBlue = new GreenshotPlugin.Controls.GreenshotLabel(); - this.textBoxRed = new System.Windows.Forms.TextBox(); - this.textBoxGreen = new System.Windows.Forms.TextBox(); - this.textBoxBlue = new System.Windows.Forms.TextBox(); - this.labelRecentColors = new GreenshotPlugin.Controls.GreenshotLabel(); - this.textBoxAlpha = new System.Windows.Forms.TextBox(); - this.labelAlpha = new GreenshotPlugin.Controls.GreenshotLabel(); - this.btnApply = new GreenshotPlugin.Controls.GreenshotButton(); - this.pipette = new Greenshot.Controls.Pipette(); - this.SuspendLayout(); - // - // btnTransparent - // - this.btnTransparent.BackColor = System.Drawing.Color.Transparent; - this.btnTransparent.LanguageKey = "colorpicker_transparent"; - this.btnTransparent.Location = new System.Drawing.Point(210, 4); - this.btnTransparent.Name = "btnTransparent"; - this.btnTransparent.Size = new System.Drawing.Size(78, 23); - this.btnTransparent.TabIndex = 0; - this.btnTransparent.TabStop = false; - this.btnTransparent.Text = "Transparent"; - this.btnTransparent.UseVisualStyleBackColor = false; - this.btnTransparent.Click += new System.EventHandler(this.BtnTransparentClick); - // - // colorPanel - // - this.colorPanel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.colorPanel.Location = new System.Drawing.Point(213, 30); - this.colorPanel.Name = "colorPanel"; - this.colorPanel.Size = new System.Drawing.Size(33, 23); - this.colorPanel.TabIndex = 1; - // - // labelHtmlColor - // - this.labelHtmlColor.Font = new System.Drawing.Font("Tahoma", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.World); - this.labelHtmlColor.LanguageKey = "colorpicker_htmlcolor"; - this.labelHtmlColor.Location = new System.Drawing.Point(210, 57); - this.labelHtmlColor.Name = "labelHtmlColor"; - this.labelHtmlColor.Size = new System.Drawing.Size(78, 17); - this.labelHtmlColor.TabIndex = 2; - this.labelHtmlColor.Text = "HTML color"; - // - // textBoxHtmlColor - // - this.textBoxHtmlColor.Location = new System.Drawing.Point(210, 71); - this.textBoxHtmlColor.Name = "textBoxHtmlColor"; - this.textBoxHtmlColor.Size = new System.Drawing.Size(78, 20); - this.textBoxHtmlColor.TabIndex = 1; - this.textBoxHtmlColor.Click += new System.EventHandler(this.TextBoxGotFocus); - this.textBoxHtmlColor.TextChanged += new System.EventHandler(this.TextBoxHexadecimalTextChanged); - this.textBoxHtmlColor.GotFocus += new System.EventHandler(this.TextBoxGotFocus); - this.textBoxHtmlColor.KeyDown += new System.Windows.Forms.KeyEventHandler(this.TextBoxKeyDown); - // - // labelRed - // - this.labelRed.Font = new System.Drawing.Font("Tahoma", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.World); - this.labelRed.LanguageKey = "colorpicker_red"; - this.labelRed.Location = new System.Drawing.Point(210, 98); - this.labelRed.Name = "labelRed"; - this.labelRed.Size = new System.Drawing.Size(78, 18); - this.labelRed.TabIndex = 4; - this.labelRed.Text = "Red"; - // - // labelGreen - // - this.labelGreen.Font = new System.Drawing.Font("Tahoma", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.World); - this.labelGreen.LanguageKey = "colorpicker_green"; - this.labelGreen.Location = new System.Drawing.Point(210, 122); - this.labelGreen.Name = "labelGreen"; - this.labelGreen.Size = new System.Drawing.Size(78, 18); - this.labelGreen.TabIndex = 5; - this.labelGreen.Text = "Green"; - // - // labelBlue - // - this.labelBlue.Font = new System.Drawing.Font("Tahoma", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.World); - this.labelBlue.LanguageKey = "colorpicker_blue"; - this.labelBlue.Location = new System.Drawing.Point(210, 146); - this.labelBlue.Name = "labelBlue"; - this.labelBlue.Size = new System.Drawing.Size(78, 18); - this.labelBlue.TabIndex = 6; - this.labelBlue.Text = "Blue"; - // - // textBoxRed - // - this.textBoxRed.Location = new System.Drawing.Point(258, 95); - this.textBoxRed.Name = "textBoxRed"; - this.textBoxRed.Size = new System.Drawing.Size(30, 20); - this.textBoxRed.TabIndex = 2; - this.textBoxRed.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; - this.textBoxRed.Click += new System.EventHandler(this.TextBoxGotFocus); - this.textBoxRed.TextChanged += new System.EventHandler(this.TextBoxRGBTextChanged); - this.textBoxRed.GotFocus += new System.EventHandler(this.TextBoxGotFocus); - this.textBoxRed.KeyDown += new System.Windows.Forms.KeyEventHandler(this.TextBoxKeyDown); - // - // textBoxGreen - // - this.textBoxGreen.Location = new System.Drawing.Point(258, 119); - this.textBoxGreen.Name = "textBoxGreen"; - this.textBoxGreen.Size = new System.Drawing.Size(30, 20); - this.textBoxGreen.TabIndex = 3; - this.textBoxGreen.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; - this.textBoxGreen.Click += new System.EventHandler(this.TextBoxGotFocus); - this.textBoxGreen.TextChanged += new System.EventHandler(this.TextBoxRGBTextChanged); - this.textBoxGreen.GotFocus += new System.EventHandler(this.TextBoxGotFocus); - this.textBoxGreen.KeyDown += new System.Windows.Forms.KeyEventHandler(this.TextBoxKeyDown); - // - // textBoxBlue - // - this.textBoxBlue.Location = new System.Drawing.Point(258, 143); - this.textBoxBlue.Name = "textBoxBlue"; - this.textBoxBlue.Size = new System.Drawing.Size(30, 20); - this.textBoxBlue.TabIndex = 4; - this.textBoxBlue.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; - this.textBoxBlue.Click += new System.EventHandler(this.TextBoxGotFocus); - this.textBoxBlue.TextChanged += new System.EventHandler(this.TextBoxRGBTextChanged); - this.textBoxBlue.GotFocus += new System.EventHandler(this.TextBoxGotFocus); - this.textBoxBlue.KeyDown += new System.Windows.Forms.KeyEventHandler(this.TextBoxKeyDown); - // - // labelRecentColors - // - this.labelRecentColors.LanguageKey = "colorpicker_recentcolors"; - this.labelRecentColors.Location = new System.Drawing.Point(3, 175); - this.labelRecentColors.Name = "labelRecentColors"; - this.labelRecentColors.Size = new System.Drawing.Size(148, 13); - this.labelRecentColors.TabIndex = 10; - this.labelRecentColors.Text = "Recently used colors"; - // - // textBoxAlpha - // - this.textBoxAlpha.Location = new System.Drawing.Point(258, 167); - this.textBoxAlpha.Name = "textBoxAlpha"; - this.textBoxAlpha.Size = new System.Drawing.Size(30, 20); - this.textBoxAlpha.TabIndex = 5; - this.textBoxAlpha.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; - this.textBoxAlpha.Click += new System.EventHandler(this.TextBoxGotFocus); - this.textBoxAlpha.TextChanged += new System.EventHandler(this.TextBoxRGBTextChanged); - this.textBoxAlpha.GotFocus += new System.EventHandler(this.TextBoxGotFocus); - this.textBoxAlpha.KeyDown += new System.Windows.Forms.KeyEventHandler(this.TextBoxKeyDown); - // - // labelAlpha - // - this.labelAlpha.Font = new System.Drawing.Font("Tahoma", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.World); - this.labelAlpha.LanguageKey = "colorpicker_alpha"; - this.labelAlpha.Location = new System.Drawing.Point(210, 170); - this.labelAlpha.Name = "labelAlpha"; - this.labelAlpha.Size = new System.Drawing.Size(78, 18); - this.labelAlpha.TabIndex = 11; - this.labelAlpha.Text = "Alpha"; - // - // btnApply - // - this.btnApply.BackColor = System.Drawing.Color.Transparent; - this.btnApply.LanguageKey = "colorpicker_apply"; - this.btnApply.Location = new System.Drawing.Point(210, 191); - this.btnApply.Name = "btnApply"; - this.btnApply.Size = new System.Drawing.Size(78, 23); - this.btnApply.TabIndex = 12; - this.btnApply.TabStop = false; - this.btnApply.Text = "Apply"; - this.btnApply.UseVisualStyleBackColor = false; - this.btnApply.Click += new System.EventHandler(this.BtnApplyClick); - // - // pipette - // - this.pipette.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.pipette.Cursor = System.Windows.Forms.Cursors.Arrow; - this.pipette.Image = ((System.Drawing.Image)(resources.GetObject("pipette.Image"))); - this.pipette.Location = new System.Drawing.Point(255, 30); - this.pipette.Name = "pipette"; - this.pipette.Size = new System.Drawing.Size(33, 23); - this.pipette.TabIndex = 13; - this.pipette.PipetteUsed += new System.EventHandler(this.PipetteUsed); - // - // ColorDialog - // - this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; - this.AutoSize = true; - this.ClientSize = new System.Drawing.Size(292, 218); - this.Controls.Add(this.pipette); - this.Controls.Add(this.btnApply); - this.Controls.Add(this.textBoxAlpha); - this.Controls.Add(this.labelAlpha); - this.Controls.Add(this.labelRecentColors); - this.Controls.Add(this.textBoxBlue); - this.Controls.Add(this.textBoxGreen); - this.Controls.Add(this.textBoxRed); - this.Controls.Add(this.labelBlue); - this.Controls.Add(this.labelGreen); - this.Controls.Add(this.labelRed); - this.Controls.Add(this.textBoxHtmlColor); - this.Controls.Add(this.labelHtmlColor); - this.Controls.Add(this.colorPanel); - this.Controls.Add(this.btnTransparent); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; - this.LanguageKey = "colorpicker_title"; - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "ColorDialog"; - this.ShowIcon = false; - this.ShowInTaskbar = false; - this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; - this.Text = "Color picker"; - this.ResumeLayout(false); - this.PerformLayout(); - - } - private GreenshotPlugin.Controls.GreenshotLabel labelRed; - private GreenshotPlugin.Controls.GreenshotLabel labelGreen; - private GreenshotPlugin.Controls.GreenshotLabel labelBlue; - private System.Windows.Forms.TextBox textBoxHtmlColor; - private GreenshotPlugin.Controls.GreenshotLabel labelRecentColors; - private GreenshotPlugin.Controls.GreenshotLabel labelAlpha; - private GreenshotPlugin.Controls.GreenshotLabel labelHtmlColor; - private GreenshotPlugin.Controls.GreenshotButton btnApply; - private System.Windows.Forms.TextBox textBoxAlpha; - private System.Windows.Forms.TextBox textBoxRed; - private System.Windows.Forms.TextBox textBoxGreen; - private System.Windows.Forms.TextBox textBoxBlue; - private System.Windows.Forms.Panel colorPanel; - private GreenshotPlugin.Controls.GreenshotButton btnTransparent; - private Greenshot.Controls.Pipette pipette; - - - - - - } -} diff --git a/Greenshot.ImageEditor/Forms/ColorDialog.cs b/Greenshot.ImageEditor/Forms/ColorDialog.cs deleted file mode 100644 index f0ca56dcc..000000000 --- a/Greenshot.ImageEditor/Forms/ColorDialog.cs +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 . - */ - -using Greenshot.Configuration; -using Greenshot.Controls; -using Greenshot.IniFile; -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Globalization; -using System.Threading; -using System.Windows.Forms; - -namespace Greenshot -{ - /// - /// Description of ColorDialog. - /// - public partial class ColorDialog : BaseForm - { - private static ColorDialog uniqueInstance; - private static readonly EditorConfiguration editorConfiguration = IniConfig.GetIniSection(); - - private ColorDialog() - { - SuspendLayout(); - InitializeComponent(); - SuspendLayout(); - CreateColorPalette(5, 5, 15, 15); - CreateLastUsedColorButtonRow(5, 190, 15, 15); - ResumeLayout(); - UpdateRecentColorsButtonRow(); - } - - public static ColorDialog GetInstance() - { - if (uniqueInstance == null) - { - uniqueInstance = new ColorDialog(); - } - return uniqueInstance; - } - - private readonly List