Removed Greenshot image editor

This commit is contained in:
Jaex 2017-12-05 16:47:32 +03:00
parent 88d362383a
commit b2e46f617c
309 changed files with 18 additions and 42860 deletions

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
}
/// <summary>
/// Description of CoreConfiguration.
/// </summary>
[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<string> OutputDestinations = new List<string>();
[IniProperty("ClipboardFormats", Separator = ",", Description = "Specify which formats we copy on the clipboard? Options are: PNG, HTML, HTMLDATAURL and DIB", DefaultValue = "PNG,DIB")]
public List<ClipboardFormat> ClipboardFormats = new List<ClipboardFormat>();
[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<string> 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<string> IncludePlugins;
[IniProperty("ExcludePlugins", Description = "Comma separated list of Plugins which are NOT allowed.")]
public List<string> ExcludePlugins;
[IniProperty("ExcludeDestinations", Description = "Comma separated list of destinations which should be disabled.")]
public List<string> 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<string> NoGDICaptureForProduct;
[IniProperty("NoDWMCaptureForProduct", Description = "List of productnames for which DWM capturing is skipped (using fallback).", DefaultValue = "Citrix ICA Client")]
public List<string> 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<string> ActiveTitleFixes;
[IniProperty("TitleFixMatcher", Description = "The regular expressions to match the title with.")]
public Dictionary<string, string> TitleFixMatcher;
[IniProperty("TitleFixReplacer", Description = "The replacements for the matchers.")]
public Dictionary<string, string> TitleFixReplacer;
[IniProperty("ExperimentalFeatures", Description = "A list of experimental features, this allows us to test certain features before releasing them.", ExcludeIfNull = true)]
public List<string> 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<int> 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;
/// <summary>
/// Specifies what THIS build is
/// </summary>
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;
}
}
/// <summary>
/// A helper method which returns true if the supplied experimental feature is enabled
/// </summary>
/// <param name="experimentalFeature"></param>
/// <returns></returns>
public bool isExperimentalFeatureEnabled(string experimentalFeature)
{
return (ExperimentalFeatures != null && ExperimentalFeatures.Contains(experimentalFeature));
}
/// <summary>
/// Supply values we can't put as defaults
/// </summary>
/// <param name="property">The property to return a default for</param>
/// <returns>object with the default value for the supplied property</returns>
public override object GetDefault(string property)
{
switch (property)
{
case "PluginWhitelist":
case "PluginBacklist":
return new List<string>();
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<string> activeDefaults = new List<string>();
activeDefaults.Add("Firefox");
activeDefaults.Add("IE");
activeDefaults.Add("Chrome");
return activeDefaults;
case "TitleFixMatcher":
Dictionary<string, string> matcherDefaults = new Dictionary<string, string>();
matcherDefaults.Add("Firefox", " - Mozilla Firefox.*");
matcherDefaults.Add("IE", " - (Microsoft|Windows) Internet Explorer.*");
matcherDefaults.Add("Chrome", " - Google Chrome.*");
return matcherDefaults;
case "TitleFixReplacer":
Dictionary<string, string> replacerDefaults = new Dictionary<string, string>();
replacerDefaults.Add("Firefox", "");
replacerDefaults.Add("IE", "");
replacerDefaults.Add("Chrome", "");
return replacerDefaults;
}
return null;
}
/// <summary>
/// This method will be called before converting the property, making to possible to correct a certain value
/// Can be used when migration is needed
/// </summary>
/// <param name="propertyName">The name of the property</param>
/// <param name="propertyValue">The string value of the property</param>
/// <returns>string with the propertyValue, modified or not...</returns>
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);
}
/// <summary>
/// This method will be called before writing the configuration
/// </summary>
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
{
}
}
/// <summary>
/// This method will be called after reading the configuration, so eventually some corrections can be made
/// </summary>
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<string>();
}
// 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<ClipboardFormat>();
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;
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// Description of CoreConfiguration.
/// </summary>
[IniSection("Editor", Description = "Greenshot editor configuration")]
public class EditorConfiguration : IniSection
{
[IniProperty("RecentColors", Separator = "|", Description = "Last used colors")]
public List<Color> 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<string, object> 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<Color>();
}
}
/// <param name="requestingType">Type of the class for which to create the field</param>
/// <param name="fieldType">FieldType of the field to construct</param>
/// <param name="preferredDefaultValue">FieldType of the field to construct</param>
/// <returns>a new Field of the given fieldType, with the scope of it's value being restricted to the Type scope</returns>
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<string, object>();
}
// 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<string, object>();
}
// 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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using GreenshotPlugin.Core;
using System;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
namespace GreenshotPlugin.Controls
{
/// <summary>
/// Description of PleaseWaitForm.
/// </summary>
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();
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
namespace GreenshotPlugin.Controls
{
partial class BackgroundForm
{
/// <summary>
/// Designer variable used to keep track of non-visual components.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Disposes resources used by the form.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing) {
if (components != null) {
components.Dispose();
}
}
base.Dispose(disposing);
}
/// <summary>
/// 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.
/// </summary>
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;
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using GreenshotPlugin.Controls;
using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace Greenshot.Controls
{
/// <summary>
/// Description of BindableToolStripButton.
/// </summary>
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"));
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using GreenshotPlugin.Controls;
using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace Greenshot.Controls
{
/// <summary>
/// A simple ToolStripComboBox implementing INotifyPropertyChanged for data binding
/// </summary>
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"));
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using GreenshotPlugin.Controls;
using System.ComponentModel;
using System.Windows.Forms;
namespace Greenshot.Controls
{
/// <summary>
/// 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.
/// </summary>
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"));
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using GreenshotPlugin.Controls;
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace Greenshot.Controls
{
/// <summary>
/// Description of ColorButton.
/// </summary>
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"));
}
}
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System.Drawing;
using System.Windows.Forms;
namespace Greenshot.Controls
{
/// <summary>
/// Prevent having a gradient background in the toolstrip, and the overflow button
/// See: http://stackoverflow.com/a/16926979
/// </summary>
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; }
}
}
/// <summary>
/// ToolStripProfessionalRenderer without having a visual artifact
/// See: http://stackoverflow.com/a/16926979 and http://stackoverflow.com/a/13418840
/// </summary>
internal class CustomToolStripProfessionalRenderer : ToolStripProfessionalRenderer
{
public CustomToolStripProfessionalRenderer() : base(new CustomProfessionalColorTable())
{
RoundedEdges = false;
}
/// <summary>
/// By overriding the OnRenderToolStripBorder we can make the ToolStrip without border
/// </summary>
/// <param name="e"></param>
protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e)
{
// Don't draw a border
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace Greenshot.Controls
{
/// <summary>
/// ToolStripComboBox containing installed font families,
/// implementing INotifyPropertyChanged for data binding
/// </summary>
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 ();
}
/// <summary>
/// Helper method to draw the string
/// </summary>
/// <param name="graphics"></param>
/// <param name="fontFamily"></param>
/// <param name="fontStyle"></param>
/// <param name="bounds"></param>
/// <param name="text"></param>
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"));
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System.Windows.Forms;
namespace GreenshotPlugin.Controls
{
/// <summary>
/// FormWithoutActivation is exactly like a normal form, but doesn't activate (steal focus)
/// </summary>
internal class FormWithoutActivation : Form
{
protected override bool ShowWithoutActivation
{
get { return true; }
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System.ComponentModel;
using System.Windows.Forms;
namespace GreenshotPlugin.Controls
{
/// <summary>
/// Description of GreenshotCheckbox.
/// </summary>
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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System.Collections;
using System.Windows.Forms;
namespace GreenshotPlugin.Controls
{
/// <summary>
/// This class is an implementation of the 'IComparer' interface.
/// </summary>
internal class GreenshotColumnSorter : IComparer
{
/// <summary>
/// Specifies the column to be sorted
/// </summary>
private int _columnToSort;
/// <summary>
/// Specifies the order in which to sort (i.e. 'Ascending').
/// </summary>
private SortOrder _orderOfSort;
/// <summary>
/// Case insensitive comparer object
/// </summary>
private readonly CaseInsensitiveComparer _objectCompare;
/// <summary>
/// Class constructor. Initializes various elements
/// </summary>
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();
}
/// <summary>
/// This method is inherited from the IComparer interface. It compares the two objects passed using a case insensitive comparison.
/// </summary>
/// <param name="x">First object to be compared</param>
/// <param name="y">Second object to be compared</param>
/// <returns>The result of the comparison. "0" if equal, negative if 'x' is less than 'y' and positive if 'x' is greater than 'y'</returns>
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;
}
/// <summary>
/// Gets or sets the number of the column to which to apply the sorting operation (Defaults to '0').
/// </summary>
public int SortColumn
{
set
{
_columnToSort = value;
}
get
{
return _columnToSort;
}
}
/// <summary>
/// Gets or sets the order of sorting to apply (for example, 'Ascending' or 'Descending').
/// </summary>
public SortOrder Order
{
set
{
_orderOfSort = value;
}
get
{
return _orderOfSort;
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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;
}
}
/// <summary>
/// This is a method to popululate the ComboBox
/// with the items from the enumeration
/// </summary>
/// <param name="enumType">TEnum to populate with</param>
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);
}
}
/// <summary>
/// Store the selected value internally
/// </summary>
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;
}
/// <summary>
/// Get the selected enum value from the combobox, uses generics
/// </summary>
/// <returns>The enum value of the combobox</returns>
public Enum GetSelectedEnum()
{
return _selectedEnum;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// This form is used for automatically binding the elements of the form to the language
/// </summary>
public class GreenshotForm : Form, IGreenshotLanguageBindable
{
protected static CoreConfiguration coreConfiguration;
private static readonly IDictionary<Type, FieldInfo[]> reflectionCache = new Dictionary<Type, FieldInfo[]>();
private IComponentChangeService m_changeService;
private bool _storeFieldsManually;
private IDictionary<string, Control> _designTimeControls;
private IDictionary<string, ToolStripItem> _designTimeToolStripItems;
static GreenshotForm()
{
if (!IsInDesignMode)
{
coreConfiguration = IniConfig.GetIniSection<CoreConfiguration>();
}
}
[Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
public string LanguageKey
{
get;
set;
}
/// <summary>
/// Used to check the designmode during a constructor
/// </summary>
/// <returns></returns>
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;
}
}
/// <summary>
/// When this is set, the form will be brought to the foreground as soon as it is shown.
/// </summary>
protected bool ToFront
{
get;
set;
}
/// <summary>
/// Code to initialize the language etc during design time
/// </summary>
protected void InitializeForDesigner()
{
if (DesignMode)
{
_designTimeControls = new Dictionary<string, Control>();
_designTimeToolStripItems = new Dictionary<string, ToolStripItem>();
}
}
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);
}
}
/// <summary>
/// Make sure the form is visible, if this is wanted
/// </summary>
/// <param name="e">EventArgs</param>
protected override void OnShown(EventArgs e)
{
base.OnShown(e);
if (ToFront)
{
WindowDetails.ToForeground(Handle);
}
}
/// <summary>
/// check if the form was closed with an OK, if so store the values in the GreenshotControls
/// </summary>
/// <param name="e"></param>
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);
}
/// <summary>
/// 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.
/// </summary>
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);
}
/// <summary>
/// Helper method to cache the fieldinfo values, so we don't need to reflect all the time!
/// </summary>
/// <param name="typeToGetFieldsFor"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Fill all GreenshotControls with the values from the configuration
/// </summary>
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()
{
}
/// <summary>
/// Store all GreenshotControl values to the configuration
/// </summary>
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();
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System.ComponentModel;
using System.Windows.Forms;
namespace GreenshotPlugin.Controls
{
/// <summary>
/// Description of GreenshotCheckbox.
/// </summary>
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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
namespace GreenshotPlugin.Controls
{
internal interface IGreenshotConfigBindable
{
/// <summary>
/// The class where the property-value is stored
/// </summary>
string SectionName
{
get;
set;
}
/// <summary>
/// Path to the property value which will be mapped with this control
/// </summary>
string PropertyName
{
get;
set;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
namespace GreenshotPlugin.Controls
{
/// <summary>
/// This interface describes the designer fields that need to be implemented for Greenshot controls
/// </summary>
internal interface IGreenshotLanguageBindable
{
/// <summary>
/// Language key to use to fill the Text value with
/// </summary>
string LanguageKey
{
get;
set;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Windows.Forms;
namespace Greenshot.Controls
{
/// <summary>
/// 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
/// </summary>
internal class MenuStripEx : MenuStrip
{
private const int WM_MOUSEACTIVATE = 0x21;
private enum NativeConstants : uint
{
MA_ACTIVATE = 1,
MA_ACTIVATEANDEAT = 2,
}
private bool _clickThrough;
/// <summary>
/// Gets or sets whether the ToolStripEx honors item clicks when its containing form does not have input focus.
/// </summary>
/// <remarks>
/// Default value is false, which is the same behavior provided by the base ToolStrip class.
/// </remarks>
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;
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System.Drawing;
using System.Windows.Forms;
namespace GreenshotPlugin.Controls
{
/// <summary>
/// See: http://nickstips.wordpress.com/2010/03/03/c-panel-resets-scroll-position-after-focus-is-lost-and-regained/
/// </summary>
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;
}
/// <summary>
/// Add horizontal scrolling to the panel, when using the wheel and the shift key is pressed
/// </summary>
/// <param name="e">MouseEventArgs</param>
protected override void OnMouseWheel(MouseEventArgs e)
{
if (VScroll && (ModifierKeys & Keys.Shift) == Keys.Shift)
{
VScroll = false;
base.OnMouseWheel(e);
VScroll = true;
}
else
{
base.OnMouseWheel(e);
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using Greenshot.Forms;
using GreenshotPlugin.UnmanagedHelpers;
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace Greenshot.Controls
{
/// <summary>
/// This code was supplied by Hi-Coder as a patch for Greenshot
/// Needed some modifications to be stable.
/// </summary>
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<PipetteUsedArgs> 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);
}
/// <summary>
/// Create a cursor from the supplied bitmap & hotspot coordinates
/// </summary>
/// <param name="bitmap">Bitmap to create an icon from</param>
/// <param name="hotspotX">Hotspot X coordinate</param>
/// <param name="hotspotY">Hotspot Y coordinate</param>
/// <returns>Cursor</returns>
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);
}
}
/// <summary>
/// The bulk of the clean-up code is implemented in Dispose(bool)
/// </summary>
public new void Dispose()
{
Dispose(true);
}
/// <summary>
/// This Dispose is called from the Dispose and the Destructor.
/// </summary>
/// <param name="disposing">When disposing==true all non-managed resources should be freed too!</param>
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);
}
/// <summary>
/// Handle the mouse down on the Pipette "label", we take the capture and move the zoomer to the current location
/// </summary>
/// <param name="e">MouseEventArgs</param>
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);
}
/// <summary>
/// Handle the mouse up on the Pipette "label", we release the capture and fire the PipetteUsed event
/// </summary>
/// <param name="e">MouseEventArgs</param>
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);
}
/// <summary>
/// Handle the mouse Move event, we move the ColorUnderCursor to the current location.
/// </summary>
/// <param name="e">MouseEventArgs</param>
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);
}
/// <summary>
/// Handle the MouseCaptureChanged event
/// </summary>
/// <param name="e"></param>
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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using GreenshotPlugin.Core;
using System;
using System.Threading;
using System.Windows.Forms;
namespace GreenshotPlugin.Controls
{
/// <summary>
/// Description of PleaseWaitForm.
/// </summary>
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();
}
/// <summary>
/// Prevent the close-window button showing
/// </summary>
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;
}
}
/// <summary>
/// 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.
/// </summary>
/// <param name="title">The title of the form (and Thread)</param>
/// <param name="text">The text in the form</param>
/// <param name="waitDelegate">delegate { with your code }</param>
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;
}
}
/// <summary>
/// Called if the cancel button is clicked, will use Thread.Abort()
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void CancelButtonClick(object sender, EventArgs e)
{
LOG.DebugFormat("Cancel clicked on {0}", title);
cancelButton.Enabled = false;
waitFor.Abort();
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
namespace GreenshotPlugin.Controls
{
partial class PleaseWaitForm
{
/// <summary>
/// Designer variable used to keep track of non-visual components.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Disposes resources used by the form.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose(disposing);
}
/// <summary>
/// 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.
/// </summary>
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;
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using Greenshot.IniFile;
using Greenshot.Plugin;
using GreenshotPlugin.Core;
using System;
namespace GreenshotPlugin.Controls
{
/// <summary>
/// Description of JpegQualityDialog.
/// </summary>
internal partial class QualityDialog : GreenshotForm
{
private static readonly CoreConfiguration conf = IniConfig.GetIniSection<CoreConfiguration>();
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();
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
namespace GreenshotPlugin.Controls
{
partial class QualityDialog
{
/// <summary>
/// Designer variable used to keep track of non-visual components.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Disposes resources used by the form.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose(disposing);
}
/// <summary>
/// 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.
/// </summary>
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;
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using Greenshot.IniFile;
using Greenshot.Plugin;
using GreenshotPlugin.Core;
using System;
using System.IO;
using System.Windows.Forms;
namespace GreenshotPlugin.Controls
{
/// <summary>
/// Custom dialog for saving images, wraps SaveFileDialog.
/// For some reason SFD is sealed :(
/// </summary>
internal class SaveImageFileDialog : IDisposable
{
private static readonly CoreConfiguration conf = IniConfig.GetIniSection<CoreConfiguration>();
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);
}
}
/// <summary>
/// filename exactly as typed in the filename field
/// </summary>
public string FileName
{
get { return SaveFileDialog.FileName; }
set { SaveFileDialog.FileName = value; }
}
/// <summary>
/// initial directory of the dialog
/// </summary>
public string InitialDirectory
{
get { return SaveFileDialog.InitialDirectory; }
set { SaveFileDialog.InitialDirectory = value; }
}
/// <summary>
/// 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.
/// </summary>
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);
}
}
/// <summary>
/// gets or sets selected extension
/// </summary>
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;
}
/// <summary>
/// sets InitialDirectory and FileName property of a SaveFileDialog smartly, considering default pattern and last used path
/// </summary>
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;
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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"));
}
}
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Windows.Forms;
namespace Greenshot.Controls
{
/// <summary>
/// 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
/// </summary>
internal class ToolStripEx : ToolStrip
{
private const int WM_MOUSEACTIVATE = 0x21;
private enum NativeConstants : uint
{
MA_ACTIVATE = 1,
MA_ACTIVATEANDEAT = 2,
}
private bool _clickThrough = false;
/// <summary>
/// Gets or sets whether the ToolStripEx honors item clicks when its containing form does not have input focus.
/// </summary>
/// <remarks>
/// Default value is false, which is the same behavior provided by the base ToolStrip class.
/// </remarks>
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;
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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"));
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Runtime.InteropServices;
namespace GreenshotPlugin.Core
{
/// <summary>
/// A helper class which does the mashalling for structs
/// </summary>
public static class BinaryStructHelper
{
/// <summary>
/// Get a struct from a byte array
/// </summary>
/// <typeparam name="T">typeof struct</typeparam>
/// <param name="bytes">byte[]</param>
/// <returns>struct</returns>
public static T FromByteArray<T>(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<T>(ptr);
}
finally
{
if (ptr != IntPtr.Zero)
{
Marshal.FreeHGlobal(ptr);
}
}
}
/// <summary>
/// Get a struct from a byte array
/// </summary>
/// <typeparam name="T">typeof struct</typeparam>
/// <param name="bytes">byte[]</param>
/// <returns>struct</returns>
public static T FromIntPtr<T>(IntPtr intPtr) where T : struct
{
object obj = Marshal.PtrToStructure(intPtr, typeof(T));
return (T)obj;
}
/// <summary>
/// copy a struct to a byte array
/// </summary>
/// <typeparam name="T">typeof struct</typeparam>
/// <param name="obj">struct</param>
/// <returns>byte[]</returns>
public static byte[] ToByteArray<T>(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<T>(ptr);
}
finally
{
if (ptr != IntPtr.Zero)
{
Marshal.FreeHGlobal(ptr);
}
}
}
/// <summary>
/// copy a struct from a pointer to a byte array
/// </summary>
/// <typeparam name="T">typeof struct</typeparam>
/// <param name="ptr">IntPtr to struct</param>
/// <returns>byte[]</returns>
public static byte[] FromPtrToByteArray<T>(IntPtr ptr) where T : struct
{
int size = Marshal.SizeOf(typeof(T));
byte[] bytes = new byte[size];
Marshal.Copy(ptr, bytes, 0, size);
return bytes;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Timers;
namespace GreenshotPlugin.Core
{
/// <summary>
/// Cache class
/// </summary>
/// <typeparam name="TK">Type of key</typeparam>
/// <typeparam name="TV">Type of value</typeparam>
public class Cache<TK, TV>
{
private readonly IDictionary<TK, TV> internalCache = new Dictionary<TK, TV>();
private readonly object lockObject = new object();
private readonly int secondsToExpire = 10;
private readonly CacheObjectExpired expiredCallback = null;
public delegate void CacheObjectExpired(TK key, TV cacheValue);
/// <summary>
/// Initialize the cache
/// </summary>
public Cache()
{
}
/// <summary>
/// Initialize the cache
/// </summary>
/// <param name="expiredCallback"></param>
public Cache(CacheObjectExpired expiredCallback) : this()
{
this.expiredCallback = expiredCallback;
}
/// <summary>
/// Initialize the cache with a expire setting
/// </summary>
/// <param name="secondsToExpire"></param>
public Cache(int secondsToExpire) : this()
{
this.secondsToExpire = secondsToExpire;
}
/// <summary>
/// Initialize the cache with a expire setting
/// </summary>
/// <param name="secondsToExpire"></param>
/// <param name="expiredCallback"></param>
public Cache(int secondsToExpire, CacheObjectExpired expiredCallback) : this(expiredCallback)
{
this.secondsToExpire = secondsToExpire;
}
/// <summary>
/// Enumerable for the values in the cache
/// </summary>
public IEnumerable<TV> Elements
{
get
{
List<TV> elements = new List<TV>();
lock (lockObject)
{
foreach (TV element in internalCache.Values)
{
elements.Add(element);
}
}
foreach (TV element in elements)
{
yield return element;
}
}
}
/// <summary>
/// Get the value by key from the cache
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public TV this[TK key]
{
get
{
TV result = default(TV);
lock (lockObject)
{
if (internalCache.ContainsKey(key))
{
result = internalCache[key];
}
}
return result;
}
}
/// <summary>
/// Contains
/// </summary>
/// <param name="key"></param>
/// <returns>true if the cache contains the key</returns>
public bool Contains(TK key)
{
lock (lockObject)
{
return internalCache.ContainsKey(key);
}
}
/// <summary>
/// Add a value to the cache
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public void Add(TK key, TV value)
{
Add(key, value, null);
}
/// <summary>
/// Add a value to the cache
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="secondsToExpire?">optional value for the seconds to expire</param>
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);
}
}
}
/// <summary>
/// Remove item from cache
/// </summary>
/// <param name="key"></param>
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);
}
}
/// <summary>
/// A cache item
/// </summary>
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;
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System.Drawing;
namespace GreenshotPlugin.Core
{
/// <summary>
/// This is the method signature which is used to capture a rectangle from the screen.
/// </summary>
/// <param name="captureBounds"></param>
/// <returns>Captured Bitmap</returns>
public delegate Bitmap CaptureScreenRectangleHandler(Rectangle captureBounds);
/// <summary>
/// This is a hack to experiment with different screen capture routines
/// </summary>
public static class CaptureHandler
{
/// <summary>
/// By changing this value, null is default
/// </summary>
public static CaptureScreenRectangleHandler CaptureScreenRectangle
{
get;
set;
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// Interface to describe an effect
/// </summary>
public interface IEffect
{
/// <summary>
/// Apply this IEffect to the supplied sourceImage.
/// In the process of applying the supplied matrix will be modified to represent the changes.
/// </summary>
/// <param name="sourceImage">Image to apply the effect to</param>
/// <param name="matrix">Matrix with the modifications like rotate, translate etc. this can be used to calculate the new location of elements on a canvas</param>
/// <returns>new image with applied effect</returns>
Image Apply(Image sourceImage, Matrix matrix);
/// <summary>
/// Reset all values to their defaults
/// </summary>
void Reset();
}
/// <summary>
/// DropShadowEffect
/// </summary>
[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);
}
}
/// <summary>
/// TornEdgeEffect extends on DropShadowEffect
/// </summary>
[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;
}
}
/// <summary>
/// GrayscaleEffect
/// </summary>
public class GrayscaleEffect : IEffect
{
public Image Apply(Image sourceImage, Matrix matrix)
{
return ImageHelper.CreateGrayscale(sourceImage);
}
public void Reset()
{
// No settings to reset
}
}
/// <summary>
/// MonochromeEffect
/// </summary>
public class MonochromeEffect : IEffect
{
private readonly byte _threshold;
/// <param name="threshold">Threshold for monochrome filter (0 - 255), lower value means less black</param>
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);
}
}
/// <summary>
/// AdjustEffect
/// </summary>
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);
}
}
/// <summary>
/// ReduceColorsEffect
/// </summary>
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;
}
}
/// <summary>
/// InvertEffect
/// </summary>
public class InvertEffect : IEffect
{
public Image Apply(Image sourceImage, Matrix matrix)
{
return ImageHelper.CreateNegative(sourceImage);
}
public void Reset()
{
// No settings to reset
}
}
/// <summary>
/// BorderEffect
/// </summary>
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);
}
}
/// <summary>
/// RotateEffect
/// </summary>
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);
}
}
/// <summary>
/// ResizeEffect
/// </summary>
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);
}
}
/// <summary>
/// ResizeCanvasEffect
/// </summary>
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]);
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
namespace GreenshotPlugin.Core
{
public static class EnumerationExtensions
{
public static bool Has<T>(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<T>(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;
}
/// <summary>
/// Add a flag to an enum
/// </summary>
/// <param name="type"></param>
/// <param name="value"></param>
/// <returns></returns>
public static T Add<T>(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));
}
/// <summary>
/// Remove a flag from an enum type
/// </summary>
/// <param name="type"></param>
/// <param name="value"></param>
/// <returns></returns>
public static T Remove<T>(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));
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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;
}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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(@"\${(?<variable>[^:}]+)[:]?(?<parameters>[^}]*)}", RegexOptions.Compiled);
private static readonly Regex CMD_VAR_REGEXP = new Regex(@"%(?<variable>[^%]+)%", 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<CoreConfiguration>();
private const string UNSAFE_REPLACEMENT = "_";
/// <summary>
/// Remove invalid characters from the fully qualified filename
/// </summary>
/// <param name="fullpath">string with the full path to a file</param>
/// <returns>string with the full path to a file, without invalid characters</returns>
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);
}
/// <summary>
/// Remove invalid characters from the filename
/// </summary>
/// <param name="fullpath">string with the full path to a file</param>
/// <returns>string with the full path to a file, without invalid characters</returns>
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;
}
/// <summary>
/// Remove invalid characters from the path
/// </summary>
/// <param name="path">string with the full path to a file</param>
/// <returns>string with the full path to a file, without invalid characters</returns>
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();
}
/// <summary>
/// Return a filename for the current image format (png,jpg etc) with the default file pattern
/// that is specified in the configuration
/// </summary>
/// <param name="format">A string with the format</param>
/// <returns>The filename which should be used to save the image</returns>
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);
}
/// <summary>
/// This method will be called by the regexp.replace as a MatchEvaluator delegate!
/// Will delegate this to the MatchVarEvaluatorInternal and catch any exceptions
/// <param name="match">What are we matching?</param>
/// <param name="captureDetails">The detail, can be null</param>
/// <param name="processVars">Variables from the process</param>
/// <param name="userVars">Variables from the user</param>
/// <param name="machineVars">Variables from the machine</param>
/// <returns>string with the match replacement</returns>
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 "";
}
/// <summary>
/// This method will be called by the regexp.replace as a MatchEvaluator delegate!
/// </summary>
/// <param name="match">What are we matching?</param>
/// <param name="captureDetails">The detail, can be null</param>
/// <returns></returns>
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<string, string> replacements = new Dictionary<string, string>();
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<width>[,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<old string>,<new string>
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>
// 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<start>[,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;
}
/// <summary>
/// "Simply" fill the pattern with environment variables
/// </summary>
/// <param name="pattern">String with pattern %var%</param>
/// <param name="filenameSafeMode">true to make sure everything is filenamesafe</param>
/// <returns>Filled string</returns>
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);
}
);
}
/// <summary>
/// "Simply" fill the pattern with environment variables
/// </summary>
/// <param name="pattern">String with pattern ${var}</param>
/// <param name="filenameSafeMode">true to make sure everything is filenamesafe</param>
/// <returns>Filled string</returns>
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);
}
);
}
/// <summary>
/// Fill the pattern wit the supplied details
/// </summary>
/// <param name="pattern">Pattern</param>
/// <param name="captureDetails">CaptureDetails, can be null</param>
/// <param name="filenameSafeMode">Should the result be made "filename" safe?</param>
/// <returns>Filled pattern</returns>
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;
}
}
/// <summary>
/// Checks whether a directory name is valid in the current file system
/// </summary>
/// <param name="directoryName">directory name (not path!)</param>
/// <returns>true if directory name is valid</returns>
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;
}
/// <summary>
/// Checks whether a filename is valid in the current file system
/// </summary>
/// <param name="filename">name of the file</param>
/// <returns>true if filename is valid</returns>
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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System.ComponentModel;
using System.Drawing;
namespace GreenshotPlugin.Core
{
/// <summary>
/// Centralized storage of the icons & bitmaps
/// </summary>
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");
}
}
}

View file

@ -1,471 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="Greenshot.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPSkpKSisCAAAAAAAAAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFTg9JgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAgAAAgABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAAEAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIA
AAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAA
AKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIA
AAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAA
AKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIA
AAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAA
AKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCKAAAACAAAABA
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
</value>
</data>
<data name="Checkerboard.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAwBQTFRFgICA////
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAODgHVgAAAAlwSFlzAAAOvgAA
Dr4B6kKxwAAAABZJREFUGFdjYAABRhAAs4hlkq4DZDgACywAM12jTsYAAAAASUVORK5CYII=
</value>
</data>
<data name="Email.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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==
</value>
</data>
<data name="Printer.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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==
</value>
</data>
<data name="Clipboard.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
</value>
</data>
<data name="Save.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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=
</value>
</data>
<data name="Close.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAUNJREFUOE+lk79L
QlEcxW9/gqCrm6vg4uYoOAgOrqLk4ioP0r2Glhp0SSjoF1FE0BIUDU3RdIOGoKBVGlpapaHTObeuCPe6
9ITD5fs9n3Pue8JbAWBS/VSQRvPwKR/j3JgaZXVqPv5TzPOXLhYoZDEcQidVWyhw3qzfn3tBAWH7PRjg
uV7HV5JAM6USyX50u86btlrOCwoOCR7Q+Oz1cFcu473dhmbppdFwu8dq1e3EBgU0zB6NXQJvzSaui0U8
VCq4LZWwn8vhLJ+HPDFiowUEzITADsGrQgFHmYzTSTYL7eSJiRZs0timRoTGhC956wXDXtrJEyM2eAIt
t34Be8NgTPLELCuQYe8Z9tK8ZBf+ieuEnxj20rzB26SYF7zCGsGEoVeW6NTMoJFiXlDAkFllqMOwTs2+
IOYFBf/9oFJ9ibr0B4f94vVG3bWDAAAAAElFTkSuQmCC
</value>
</data>
</root>

File diff suppressed because it is too large Load diff

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// Description of ImageOutput.
/// </summary>
public static class ImageOutput
{
private static readonly CoreConfiguration conf = IniConfig.GetIniSection<CoreConfiguration>();
private static readonly int PROPERTY_TAG_SOFTWARE_USED = 0x0131;
private static readonly Cache<string, string> tmpFileCache = new Cache<string, string>(10 * 60 * 60, RemoveExpiredTmpFile);
/// <summary>
/// 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!
/// </summary>
/// <param name="id">ID</param>
/// <param name="text">Text</param>
/// <returns></returns>
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
/// <summary>
/// Saves ISurface to stream with specified output settings
/// </summary>
/// <param name="surface">ISurface to save</param>
/// <param name="stream">Stream to save to</param>
/// <param name="outputSettings">SurfaceOutputSettings</param>
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();
}
}
/// <summary>
/// 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.
/// </summary>
/// <param name="imageToSave">image to save</param>
/// <param name="surface">surface for the elements, needed if the greenshot format is used</param>
/// <param name="stream">Stream to save to</param>
/// <param name="outputSettings">SurfaceOutputSettings</param>
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();
}
}
}
/// <summary>
/// Write the passed Image to a tmp-file and call an external process, than read the file back and write it to the targetStream
/// </summary>
/// <param name="imageToProcess">Image to pass to the external process</param>
/// <param name="targetStream">stream to write the processed image to</param>
/// <returns></returns>
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;
}
/// <summary>
/// Create an image from a surface with the settings from the output settings applied
/// </summary>
/// <param name="surface"></param>
/// <param name="outputSettings"></param>
/// <param name="imageToSave"></param>
/// <returns>true if the image must be disposed</returns>
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;
}
/// <summary>
/// Add the greenshot property!
/// </summary>
/// <param name="imageToSave"></param>
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);
}
}
}
/// <summary>
/// Load a Greenshot surface
/// </summary>
/// <param name="fullPath"></param>
/// <param name="returnSurface"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Saves image to specific path with specified quality
/// </summary>
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);
}
}
/// <summary>
/// Get the OutputFormat for a filename
/// </summary>
/// <param name="fullPath">filename (can be a complete path)</param>
/// <returns>OutputFormat</returns>
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
/// <summary>
/// Save with showing a dialog
/// </summary>
/// <param name="surface"></param>
/// <param name="captureDetails"></param>
/// <returns>Path to filename</returns>
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
/// <summary>
/// Create a tmpfile which has the name like in the configured pattern.
/// Used e.g. by the email export
/// </summary>
/// <param name="surface"></param>
/// <param name="captureDetails"></param>
/// <param name="outputSettings"></param>
/// <returns>Path to image file</returns>
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;
}
/// <summary>
/// Remove a tmpfile which was created by SaveNamedTmpFile
/// Used e.g. by the email export
/// </summary>
/// <param name="tmpfile"></param>
/// <returns>true if it worked</returns>
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;
}
/// <summary>
/// Helper method to create a temp image file
/// </summary>
/// <param name="surface"></param>
/// <param name="outputSettings"></param>
/// <param name="destinationPath"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Cleanup all created tmpfiles
/// </summary>
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);
}
}
/// <summary>
/// Cleanup handler for expired tempfiles
/// </summary>
/// <param name="filekey"></param>
/// <param name="filename"></param>
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);
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// HTTP Method to make sure we have the correct method
/// </summary>
public enum HTTPMethod
{
GET,
POST,
PUT,
DELETE,
HEAD
};
/// <summary>
/// Description of NetworkHelper.
/// </summary>
public static class NetworkHelper
{
private static readonly CoreConfiguration Config = IniConfig.GetIniSection<CoreConfiguration>();
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);
}
}
/// <summary>
/// Download a uri response as string
/// </summary>
/// <param name="uri">An Uri to specify the download location</param>
/// <returns>string with the file content</returns>
public static string GetAsString(Uri uri)
{
return GetResponseAsString(CreateWebRequest(uri));
}
/// <summary>
/// Download the FavIcon as a Bitmap
/// </summary>
/// <param name="baseUri"></param>
/// <returns>Bitmap with the FavIcon</returns>
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;
}
/// <summary>
/// Download the uri into a memorystream, without catching exceptions
/// </summary>
/// <param name="url">Of an image</param>
/// <returns>MemoryStream which is already seeked to 0</returns>
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;
}
}
/// <summary>
/// Download the uri to Bitmap
/// </summary>
/// <param name="url">Of an image</param>
/// <returns>Bitmap</returns>
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;
}
/// <summary>
/// Helper method to create a web request with a lot of default settings
/// </summary>
/// <param name="uri">string with uri to connect to</param>
/// <returns>WebRequest</returns>
public static HttpWebRequest CreateWebRequest(string uri)
{
return CreateWebRequest(new Uri(uri));
}
/// <summary>
/// Helper method to create a web request with a lot of default settings
/// </summary>
/// <param name="uri">string with uri to connect to</param>
/// /// <param name="method">Method to use</param>
/// <returns>WebRequest</returns>
public static HttpWebRequest CreateWebRequest(string uri, HTTPMethod method)
{
return CreateWebRequest(new Uri(uri), method);
}
/// <summary>
/// Helper method to create a web request with a lot of default settings
/// </summary>
/// <param name="uri">Uri with uri to connect to</param>
/// <param name="method">Method to use</param>
/// <returns>WebRequest</returns>
public static HttpWebRequest CreateWebRequest(Uri uri, HTTPMethod method)
{
HttpWebRequest webRequest = CreateWebRequest(uri);
webRequest.Method = method.ToString();
return webRequest;
}
/// <summary>
/// Helper method to create a web request, eventually with proxy
/// </summary>
/// <param name="uri">Uri with uri to connect to</param>
/// <returns>WebRequest</returns>
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;
}
/// <summary>
/// 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
/// </summary>
/// <param name="uri"></param>
/// <returns>IWebProxy filled with all the proxy details or null if none is set/wanted</returns>
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;
}
/// <summary>
/// UrlEncodes a string without the requirement for System.Web
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
// [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;
}
/// <summary>
/// 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
/// </summary>
/// <param name="text"></param>
/// <returns>escaped data string</returns>
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;
}
/// <summary>
/// UrlDecodes a string without requiring System.Web
/// </summary>
/// <param name="text">String to decode.</param>
/// <returns>decoded string</returns>
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);
}
/// <summary>
/// ParseQueryString without the requirement for System.Web
/// </summary>
/// <param name="queryString"></param>
/// <returns>IDictionary string, string</returns>
public static IDictionary<string, string> ParseQueryString(string queryString)
{
IDictionary<string, string> parameters = new SortedDictionary<string, string>();
// 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;
}
/// <summary>
/// Generate the query paramters
/// </summary>
/// <param name="queryParameters">the list of query parameters</param>
/// <returns>a string with the query parameters</returns>
public static string GenerateQueryParameters(IDictionary<string, object> queryParameters)
{
if (queryParameters == null || queryParameters.Count == 0)
{
return string.Empty;
}
queryParameters = new SortedDictionary<string, object>(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();
}
/// <summary>
/// Write Multipart Form Data directly to the HttpWebRequest
/// </summary>
/// <param name="webRequest">HttpWebRequest to write the multipart form data to</param>
/// <param name="postParameters">Parameters to include in the multipart form data</param>
public static void WriteMultipartFormData(HttpWebRequest webRequest, IDictionary<string, object> 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);
}
}
/// <summary>
/// Write Multipart Form Data to the HttpListenerResponse
/// </summary>
/// <param name="response">HttpListenerResponse</param>
/// <param name="postParameters">Parameters to include in the multipart form data</param>
public static void WriteMultipartFormData(HttpListenerResponse response, IDictionary<string, object> postParameters)
{
string boundary = String.Format("----------{0:N}", Guid.NewGuid());
response.ContentType = "multipart/form-data; boundary=" + boundary;
WriteMultipartFormData(response.OutputStream, boundary, postParameters);
}
/// <summary>
/// Write Multipart Form Data to a Stream, content-type should be set before this!
/// </summary>
/// <param name="formDataStream">Stream to write the multipart form data to</param>
/// <param name="boundary">String boundary for the multipart/form-data</param>
/// <param name="postParameters">Parameters to include in the multipart form data</param>
public static void WriteMultipartFormData(Stream formDataStream, string boundary, IDictionary<string, object> 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));
}
/// <summary>
/// Post the parameters "x-www-form-urlencoded"
/// </summary>
/// <param name="webRequest"></param>
/// <param name="parameters"></param>
public static void UploadFormUrlEncoded(HttpWebRequest webRequest, IDictionary<string, object> 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);
}
}
/// <summary>
/// Log the headers of the WebResponse, if IsDebugEnabled
/// </summary>
/// <param name="response">WebResponse</param>
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]);
}
}
/// <summary>
/// Process the web response.
/// </summary>
/// <param name="webRequest">The request object.</param>
/// <returns>The response data.</returns>
/// This method should handle the StatusCode better!
public static string GetResponseAsString(HttpWebRequest webRequest)
{
return GetResponseAsString(webRequest, false);
}
/// <summary>
/// Read the response as string
/// </summary>
/// <param name="response"></param>
/// <returns>string or null</returns>
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;
}
/// <summary>
///
/// </summary>
/// <param name="webRequest"></param>
/// <param name="alsoReturnContentOnError"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Get LastModified for a URI
/// </summary>
/// <param name="uri">Uri</param>
/// <returns>DateTime</returns>
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;
}
}
}
/// <summary>
/// This interface can be used to pass binary information around, like byte[] or Image
/// </summary>
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);
}
/// <summary>
/// A container to supply files to a Multi-part form data upload
/// </summary>
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;
}
/// <summary>
/// Create a Base64String from the byte[]
/// </summary>
/// <returns>string</returns>
public string ToBase64String(Base64FormattingOptions formattingOptions)
{
return Convert.ToBase64String(_file, 0, _fileSize, formattingOptions);
}
/// <summary>
/// Returns the initial byte-array which was supplied when creating the FileParameter
/// </summary>
/// <returns>byte[]</returns>
public byte[] ToByteArray()
{
return _file;
}
/// <summary>
/// Write Multipart Form Data directly to the HttpWebRequest response stream
/// </summary>
/// <param name="boundary">Separator</param>
/// <param name="name">name</param>
/// <param name="formDataStream">Stream to write to</param>
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);
}
/// <summary>
/// A plain "write data to stream"
/// </summary>
/// <param name="dataStream">Stream to write to</param>
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);
}
/// <summary>
/// Upload the file to the webrequest
/// </summary>
/// <param name="webRequest"></param>
public void Upload(HttpWebRequest webRequest)
{
webRequest.ContentType = _contentType;
webRequest.ContentLength = _fileSize;
using (var requestStream = webRequest.GetRequestStream())
{
WriteToStream(requestStream);
}
}
}
/// <summary>
/// A container to supply images to a Multi-part form data upload
/// </summary>
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;
}
/// <summary>
/// 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.
/// </summary>
/// <returns>string</returns>
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);
}
}
/// <summary>
/// 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.
/// </summary>
/// <returns>byte[]</returns>
public byte[] ToByteArray()
{
using (MemoryStream stream = new MemoryStream())
{
ImageOutput.SaveToStream(_bitmap, null, stream, _outputSettings);
return stream.ToArray();
}
}
/// <summary>
/// Write Multipart Form Data directly to the HttpWebRequest response stream
/// </summary>
/// <param name="boundary">Separator</param>
/// <param name="name">Name of the thing/file</param>
/// <param name="formDataStream">Stream to write to</param>
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);
}
/// <summary>
/// A plain "write data to stream"
/// </summary>
/// <param name="dataStream"></param>
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);
}
/// <summary>
/// Upload the image to the webrequest
/// </summary>
/// <param name="webRequest"></param>
public void Upload(HttpWebRequest webRequest)
{
webRequest.ContentType = "image/" + _outputSettings.Format;
using (var requestStream = webRequest.GetRequestStream())
{
WriteToStream(requestStream);
}
}
}
/// <summary>
/// A container to supply surfaces to a Multi-part form data upload
/// </summary>
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;
}
/// <summary>
/// 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.
/// </summary>
/// <returns>string</returns>
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);
}
}
/// <summary>
/// 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.
/// </summary>
/// <returns>byte[]</returns>
public byte[] ToByteArray()
{
using (MemoryStream stream = new MemoryStream())
{
ImageOutput.SaveToStream(_surface, stream, _outputSettings);
return stream.ToArray();
}
}
/// <summary>
/// Write Multipart Form Data directly to the HttpWebRequest response stream
/// </summary>
/// <param name="boundary">Multipart separator</param>
/// <param name="name">Name of the thing</param>
/// <param name="formDataStream">Stream to write to</param>
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);
}
/// <summary>
/// A plain "write data to stream"
/// </summary>
/// <param name="dataStream"></param>
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);
}
/// <summary>
/// Upload the Surface as image to the webrequest
/// </summary>
/// <param name="webRequest"></param>
public void Upload(HttpWebRequest webRequest)
{
webRequest.ContentType = "image/" + _outputSettings.Format.ToString();
using (var requestStream = webRequest.GetRequestStream())
{
WriteToStream(requestStream);
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// Perform a deep Copy of the object.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>The copied object.</returns>
public static T Clone<T>(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<T>(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<T>(IList<T> l1, IList<T> 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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
namespace GreenshotPlugin.Core
{
/// <summary>
/// Extensions to help with querying the Operating System
/// </summary>
public static class OperatingSystemExtensions
{
/// <summary>
/// Test if the current OS is Windows 10
/// </summary>
/// <param name="operatingSystem">OperatingSystem from Environment.OSVersion</param>
/// <returns>true if we are running on Windows 10</returns>
public static bool IsWindows10(this OperatingSystem operatingSystem)
{
return operatingSystem.Version.Major == 10;
}
/// <summary>
/// Test if the current OS is Windows 8(.1)
/// </summary>
/// <param name="operatingSystem">OperatingSystem from Environment.OSVersion</param>
/// <returns>true if we are running on Windows 8(.1)</returns>
public static bool IsWindows8(this OperatingSystem operatingSystem)
{
return operatingSystem.Version.Major == 6 && operatingSystem.Version.Minor >= 2;
}
/// <summary>
/// Test if the current OS is Windows 8 or later
/// </summary>
/// <param name="operatingSystem">OperatingSystem from Environment.OSVersion</param>
/// <returns>true if we are running on Windows 8 or later</returns>
public static bool IsWindows8OrLater(this OperatingSystem operatingSystem)
{
return (operatingSystem.Version.Major == 6 && operatingSystem.Version.Minor >= 2) || operatingSystem.Version.Major >= 6;
}
/// <summary>
/// Test if the current OS is Windows 7 or later
/// </summary>
/// <param name="operatingSystem">OperatingSystem from Environment.OSVersion</param>
/// <returns>true if we are running on Windows 7 or later</returns>
public static bool IsWindows7OrLater(this OperatingSystem operatingSystem)
{
return (operatingSystem.Version.Major == 6 && operatingSystem.Version.Minor >= 1) || operatingSystem.Version.Major >= 6;
}
/// <summary>
/// Test if the current OS is Windows Vista or later
/// </summary>
/// <param name="operatingSystem">OperatingSystem from Environment.OSVersion</param>
/// <returns>true if we are running on Windows Vista or later</returns>
public static bool IsWindowsVistaOrLater(this OperatingSystem operatingSystem)
{
return operatingSystem.Version.Major >= 6;
}
/// <summary>
/// Test if the current OS is Windows XP or later
/// </summary>
/// <param name="operatingSystem">OperatingSystem from Environment.OSVersion</param>
/// <returns>true if we are running on Windows XP or later</returns>
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);
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// Description of PluginUtils.
/// </summary>
public static class PluginUtils
{
private static readonly CoreConfiguration conf = IniConfig.GetIniSection<CoreConfiguration>();
private const string PATH_KEY = @"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\";
private static readonly IDictionary<string, Image> exeIconCache = new Dictionary<string, Image>();
static PluginUtils()
{
conf.PropertyChanged += OnIconSizeChanged;
}
/// <summary>
/// Simple global property to get the Greenshot host
/// </summary>
public static IGreenshotHost Host
{
get;
set;
}
/// <summary>
/// Clear icon cache
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void OnIconSizeChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "IconSize")
{
List<Image> cachedImages = new List<Image>();
lock (exeIconCache)
{
foreach (string key in exeIconCache.Keys)
{
cachedImages.Add(exeIconCache[key]);
}
exeIconCache.Clear();
}
foreach (Image cachedImage in cachedImages)
{
if (cachedImage != null)
{
cachedImage.Dispose();
}
}
}
}
/// <summary>
/// Get the path of an executable
/// </summary>
/// <param name="exeName">e.g. cmd.exe</param>
/// <returns>Path to file</returns>
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;
}
/// <summary>
/// Get icon for executable, from the cache
/// </summary>
/// <param name="path">path to the exe or dll</param>
/// <param name="index">index of the icon</param>
/// <returns>Bitmap with the icon or null if something happended</returns>
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;
}
/// <summary>
/// Get icon for executable
/// </summary>
/// <param name="path">path to the exe or dll</param>
/// <param name="index">index of the icon</param>
/// <returns>Bitmap with the icon or null if something happended</returns>
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;
}
/// <summary>
/// Helper method to add a MenuItem to the File MenuItem of an ImageEditor
/// </summary>
/// <param name="image">Image to display in the menu</param>
/// <param name="text">Text to display in the menu</param>
/// <param name="tag">The TAG value</param>
/// <param name="shortcutKeys">Keys which can be used as shortcut</param>
/// <param name="handler">The onclick handler</param>
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);
}
/// <summary>
/// Helper method to add a MenuItem to the File MenuItem of an ImageEditor
/// </summary>
/// <param name="imageEditor"></param>
/// <param name="item"></param>
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);
}
}
/// <summary>
/// Helper method to add a MenuItem to the Plugin MenuItem of an ImageEditor
/// </summary>
/// <param name="imageEditor"></param>
/// <param name="item"></param>
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);
}
}
/// <summary>
/// Helper method to add a plugin MenuItem to the Greenshot context menu
/// </summary>
/// <param name="imageEditor"></param>
/// <param name="item"></param>
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);
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
namespace GreenshotPlugin.Core
{
internal class WuColorCube
{
/// <summary>
/// Gets or sets the red minimum.
/// </summary>
/// <value>The red minimum.</value>
public Int32 RedMinimum { get; set; }
/// <summary>
/// Gets or sets the red maximum.
/// </summary>
/// <value>The red maximum.</value>
public Int32 RedMaximum { get; set; }
/// <summary>
/// Gets or sets the green minimum.
/// </summary>
/// <value>The green minimum.</value>
public Int32 GreenMinimum { get; set; }
/// <summary>
/// Gets or sets the green maximum.
/// </summary>
/// <value>The green maximum.</value>
public Int32 GreenMaximum { get; set; }
/// <summary>
/// Gets or sets the blue minimum.
/// </summary>
/// <value>The blue minimum.</value>
public Int32 BlueMinimum { get; set; }
/// <summary>
/// Gets or sets the blue maximum.
/// </summary>
/// <value>The blue maximum.</value>
public Int32 BlueMaximum { get; set; }
/// <summary>
/// Gets or sets the cube volume.
/// </summary>
/// <value>The volume.</value>
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;
}
}
}
/// <summary>
/// See <see cref="IColorQuantizer.Prepare"/> for more details.
/// </summary>
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();
}
}
}
/// <summary>
/// See <see cref="IColorQuantizer.Prepare"/> for more details.
/// </summary>
public Int32 GetColorCount()
{
return colorCount;
}
/// <summary>
/// Reindex the 24/32 BPP (A)RGB image to a 8BPP
/// </summary>
/// <returns>Bitmap</returns>
public Bitmap SimpleReindex()
{
List<Color> colors = new List<Color>();
Dictionary<Color, byte> lookup = new Dictionary<Color, byte>();
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;
}
/// <summary>
/// Get the image
/// </summary>
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<Color, byte> lookup = new Dictionary<Color, byte>();
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;
}
/// <summary>
/// Converts the histogram to a series of moments.
/// </summary>
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];
}
}
}
}
/// <summary>
/// Computes the volume of the cube in a specific moment.
/// </summary>
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];
}
/// <summary>
/// Computes the volume of the cube in a specific moment. For the floating-point values.
/// </summary>
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];
}
/// <summary>
/// Splits the cube in given position, and color direction.
/// </summary>
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;
}
}
/// <summary>
/// Splits the cube in a given color direction at its minimum.
/// </summary>
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;
}
}
/// <summary>
/// Calculates statistical variance for a given cube.
/// </summary>
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);
}
/// <summary>
/// Finds the optimal (maximal) position for the cut.
/// </summary>
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;
}
/// <summary>
/// Cuts a cube with another one.
/// </summary>
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;
}
/// <summary>
/// Marks all the tags with a given label.
/// </summary>
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;
}
}
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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";
/// <summary>
/// Format a string with the specified object
/// </summary>
/// <param name="format">String with formatting, like {name}</param>
/// <param name="source">Object used for the formatting</param>
/// <returns>Formatted string</returns>
public static string FormatWith(this string format, object source)
{
return FormatWith(format, null, source);
}
/// <summary>
/// Format the string "format" with the source
/// </summary>
/// <param name="format"></param>
/// <param name="provider"></param>
/// <param name="source">object with properties, if a property has the type IDictionary string,string it can used these parameters too</param>
/// <returns>Formatted string</returns>
public static string FormatWith(this string format, IFormatProvider provider, object source)
{
if (format == null)
{
throw new ArgumentNullException("format");
}
IDictionary<string, object> properties = new Dictionary<string, object>();
foreach (var propertyInfo in source.GetType().GetProperties())
{
if (propertyInfo.CanRead && propertyInfo.CanWrite)
{
object value = propertyInfo.GetValue(source, null);
if (propertyInfo.PropertyType != typeof(IDictionary<string, string>))
{
properties.Add(propertyInfo.Name, value);
}
else
{
IDictionary<string, string> dictionary = (IDictionary<string, string>)value;
foreach (var propertyKey in dictionary.Keys)
{
properties.Add(propertyKey, dictionary[propertyKey]);
}
}
}
}
Regex r = new Regex(@"(?<start>\{)+(?<property>[\w\.\[\]]+)(?<format>:[^}]+)?(?<end>\})+", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
List<object> values = new List<object>();
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());
}
/// <summary>
/// A simply rijndael aes encryption, can be used to store passwords
/// </summary>
/// <param name="ClearText">the string to call upon</param>
/// <returns>an encryped string in base64 form</returns>
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;
}
/// <summary>
/// A simply rijndael aes decryption, can be used to store passwords
/// </summary>
/// <param name="EncryptedText">a base64 encoded rijndael encrypted string</param>
/// <returns>Decrypeted text</returns>
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;
}
/// <summary>
/// Read "streamextensions" :)
/// </summary>
/// <param name="input">Stream</param>
/// <param name="output">Stream</param>
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);
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// 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
/// </summary>
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<string, string> metaData = new Dictionary<string, string>();
public Dictionary<string, string> 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<IDestination> _captureDestinations = new List<IDestination>();
public List<IDestination> 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;
}
}
/// <summary>
/// This class is used to pass an instance of the "Capture" around
/// Having the Bitmap, eventually the Windows Title and cursor all together.
/// </summary>
public class Capture : ICapture
{
private List<ICaptureElement> _elements = new List<ICaptureElement>();
private Rectangle _screenBounds = Rectangle.Empty;
/// <summary>
/// Get/Set the Screenbounds
/// </summary>
public Rectangle ScreenBounds
{
get
{
if (_screenBounds == Rectangle.Empty)
{
_screenBounds = WindowCapture.GetScreenBounds();
}
return _screenBounds;
}
set
{
_screenBounds = value;
}
}
private Image _image;
/// <summary>
/// Get/Set the Image
/// </summary>
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;
/// <summary>
/// Get/Set the image for the Cursor
/// </summary>
public Icon Cursor
{
get
{
return _cursor;
}
set
{
if (_cursor != null)
{
_cursor.Dispose();
}
_cursor = (Icon)value.Clone();
}
}
private bool _cursorVisible;
/// <summary>
/// Set if the cursor is visible
/// </summary>
public bool CursorVisible
{
get { return _cursorVisible; }
set { _cursorVisible = value; }
}
private Point _cursorLocation = Point.Empty;
/// <summary>
/// Get/Set the CursorLocation
/// </summary>
public Point CursorLocation
{
get { return _cursorLocation; }
set { _cursorLocation = value; }
}
private Point _location = Point.Empty;
/// <summary>
/// Get/set the Location
/// </summary>
public Point Location
{
get { return _location; }
set { _location = value; }
}
private CaptureDetails _captureDetails;
/// <summary>
/// Get/set the CaptureDetails
/// </summary>
public ICaptureDetails CaptureDetails
{
get { return _captureDetails; }
set { _captureDetails = (CaptureDetails)value; }
}
/// <summary>
/// Default Constructor
/// </summary>
public Capture()
{
_screenBounds = WindowCapture.GetScreenBounds();
_captureDetails = new CaptureDetails();
}
/// <summary>
/// Constructor with Image
/// Note: the supplied bitmap can be disposed immediately or when constructor is called.
/// </summary>
/// <param name="newImage">Image</param>
public Capture(Image newImage) : this()
{
Image = newImage;
}
/// <summary>
/// Destructor
/// </summary>
~Capture()
{
Dispose(false);
}
/// <summary>
/// The public accessible Dispose
/// Will call the GarbageCollector to SuppressFinalize, preventing being cleaned twice
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// This Dispose is called from the Dispose and the Destructor.
/// When disposing==true all non-managed resources should be freed too!
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (_image != null)
{
_image.Dispose();
}
if (_cursor != null)
{
_cursor.Dispose();
}
}
_image = null;
_cursor = null;
}
/// <summary>
/// Crops the capture to the specified rectangle (with Bitmap coordinates!)
/// </summary>
/// <param name="cropRectangle">Rectangle with bitmap coordinates</param>
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<ICaptureElement> newElements = new List<ICaptureElement>();
foreach (ICaptureElement captureElement in _elements)
{
if (captureElement.Bounds.IntersectsWith(cropRectangle))
{
newElements.Add(captureElement);
}
}
_elements = newElements;
return true;
}
return false;
}
/// <summary>
/// Apply a translate to the mouse location.
/// e.g. needed for crop
/// </summary>
/// <param name="x">x coordinates to move the mouse</param>
/// <param name="y">y coordinates to move the mouse</param>
public void MoveMouseLocation(int x, int y)
{
_cursorLocation.Offset(x, y);
}
// Enable when the elements are usable again.
///// <summary>
///// Apply a translate to the elements
///// e.g. needed for crop
///// </summary>
///// <param name="x">x coordinates to move the elements</param>
///// <param name="y">y coordinates to move the elements</param>
//public void MoveElements(int x, int y) {
// MoveElements(elements, x, y);
//}
//private void MoveElements(List<ICaptureElement> 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);
// }
//}
///// <summary>
///// Add a new element to the capture
///// </summary>
///// <param name="element">CaptureElement</param>
//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);
// }
//}
///// <summary>
///// Returns a list of rectangles which represent object that are on the capture
///// </summary>
//public List<ICaptureElement> Elements {
// get {
// return elements;
// }
// set {
// elements = value;
// }
//}
}
/// <summary>
/// A class representing an element in the capture
/// </summary>
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<ICaptureElement> _children = new List<ICaptureElement>();
public List<ICaptureElement> 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();
}
}
/// <summary>
/// The Window Capture code
/// </summary>
public class WindowCapture
{
private static readonly CoreConfiguration Configuration = IniConfig.GetIniSection<CoreConfiguration>();
/// <summary>
/// Used to cleanup the unmanged resource in the iconInfo for the CaptureCursor method
/// </summary>
/// <param name="hObject"></param>
/// <returns></returns>
[DllImport("gdi32", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DeleteObject(IntPtr hObject);
private WindowCapture()
{
}
/// <summary>
/// Get the bounds of all screens combined.
/// </summary>
/// <returns>A Rectangle of the bounds of the entire display area.</returns>
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)));
}
/// <summary>
/// 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.
/// </summary>
/// <returns>
/// Point with cursor location, relative to the top left corner of the monitor setup (which itself might actually not be on any screen)
/// </returns>
public static Point GetCursorLocationRelativeToScreenBounds()
{
return GetLocationRelativeToScreenBounds(User32.GetCursorLocation());
}
/// <summary>
/// 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.
/// </summary>
/// <param name="locationRelativeToScreenOrigin"></param>
/// <returns></returns>
public static Point GetLocationRelativeToScreenBounds(Point locationRelativeToScreenOrigin)
{
Point ret = locationRelativeToScreenOrigin;
Rectangle bounds = GetScreenBounds();
ret.Offset(-bounds.X, -bounds.Y);
return ret;
}
/// <summary>
/// This method will capture the current Cursor by using User32 Code
/// </summary>
/// <returns>A Capture Object with the Mouse Cursor information in it.</returns>
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;
}
/// <summary>
/// This method will call the CaptureRectangle with the screenbounds, therefor Capturing the whole screen.
/// </summary>
/// <returns>A Capture Object with the Screen as an Image</returns>
public static ICapture CaptureScreen(ICapture capture)
{
if (capture == null)
{
capture = new Capture();
}
return CaptureRectangle(capture, capture.ScreenBounds);
}
/// <summary>
/// Helper method to create an exception that might explain what is wrong while capturing
/// </summary>
/// <param name="method">string with current method</param>
/// <param name="captureBounds">Rectangle of what we want to capture</param>
/// <returns></returns>
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;
}
/// <summary>
/// Helper method to check if it is allowed to capture the process using DWM
/// </summary>
/// <param name="process">Process owning the window</param>
/// <returns>true if it's allowed</returns>
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;
}
/// <summary>
/// Helper method to check if it is allowed to capture the process using GDI
/// </summary>
/// <param name="process">Process owning the window</param>
/// <returns>true if it's allowed</returns>
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;
}
/// <summary>
/// This method will use User32 code to capture the specified captureBounds from the screen
/// </summary>
/// <param name="capture">ICapture where the captured Bitmap will be stored</param>
/// <param name="captureBounds">Rectangle with the bounds to capture</param>
/// <returns>A Capture Object with a part of the Screen as an Image</returns>
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;
}
/// <summary>
/// This method will use User32 code to capture the specified captureBounds from the screen
/// </summary>
/// <param name="capture">ICapture where the captured Bitmap will be stored</param>
/// <param name="captureBounds">Rectangle with the bounds to capture</param>
/// <returns>A Capture Object with a part of the Screen as an Image</returns>
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;
}
/// <summary>
/// This method will use User32 code to capture the specified captureBounds from the screen
/// </summary>
/// <param name="captureBounds">Rectangle with the bounds to capture</param>
/// <returns>Bitmap which is captured from the screen at the location specified by the captureBounds</returns>
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<Screen> screensInsideCapture = new List<Screen>();
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;
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using Greenshot.Drawing.Fields;
using Greenshot.Plugin.Drawing;
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace Greenshot.Drawing
{
/// <summary>
/// Description of LineContainer.
/// </summary>
[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)
{
}
/// <summary>
/// Do not use the base, just override so we have our own defaults
/// </summary>
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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using Greenshot.Drawing.Fields;
using Greenshot.Helpers;
using Greenshot.Plugin.Drawing;
using System.Drawing;
namespace Greenshot.Drawing
{
/// <summary>
/// Description of CropContainer.
/// </summary>
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();
}
/// <summary>
/// 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)
/// </summary>
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;
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// Description of CursorContainer.
/// </summary>
[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;
}
}
/// <summary>
/// This Dispose is called from the Dispose and the Destructor.
/// When disposing==true all non-managed resources should be freed too!
/// </summary>
/// <param name="disposing"></param>
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;
}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// Dispatches most of a DrawableContainer's public properties and methods to a list of DrawableContainers.
/// </summary>
[Serializable]
public class DrawableContainerList : List<IDrawableContainer>
{
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<IDrawableContainer> AsIDrawableContainerList()
{
List<IDrawableContainer> interfaceList = new List<IDrawableContainer>();
foreach (IDrawableContainer container in this)
{
interfaceList.Add(container);
}
return interfaceList;
}
/// <summary>
/// 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.
/// </summary>
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;
}
}
}
/// <summary>
/// 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.
/// </summary>
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;
}
}
}
/// <summary>
/// Make a following bounds change on this containerlist undoable!
/// </summary>
/// <param name="allowMerge">true means allow the moves to be merged</param>
public void MakeBoundsChangeUndoable(bool allowMerge)
{
List<IDrawableContainer> movingList = new List<IDrawableContainer>();
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);
}
}
/// <summary>
/// Apply matrix to all elements
/// </summary>
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;
}
}
/// <summary>
/// Moves all elements in the list by the given amount of pixels.
/// </summary>
/// <param name="dx">pixels to move horizontally</param>
/// <param name="dy">pixels to move vertically</param>
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;
}
}
/// <summary>
/// Hides the grippers of all elements in the list.
/// </summary>
public void HideGrippers()
{
foreach (var dc in this)
{
dc.HideGrippers();
dc.Invalidate();
}
}
/// <summary>
/// Shows the grippers of all elements in the list.
/// </summary>
public void ShowGrippers()
{
foreach (var dc in this)
{
dc.ShowGrippers();
dc.Invalidate();
}
}
/// <summary>
/// Indicates whether on of the elements is clickable at the given location
/// </summary>
/// <param name="x">x coordinate to be checked</param>
/// <param name="y">y coordinate to be checked</param>
/// <returns>true if one of the elements in the list is clickable at the given location, false otherwise</returns>
public bool ClickableAt(int x, int y)
{
bool ret = false;
foreach (var dc in this)
{
ret |= dc.ClickableAt(x, y);
}
return ret;
}
/// <summary>
/// retrieves the topmost element being clickable at the given location
/// </summary>
/// <param name="x">x coordinate to be checked</param>
/// <param name="y">y coordinate to be checked</param>
/// <returns>the topmost element from the list being clickable at the given location, null if there is no clickable element</returns>
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;
}
/// <summary>
/// Dispatches OnDoubleClick to all elements in the list.
/// </summary>
public void OnDoubleClick()
{
foreach (var drawableContainer in this)
{
var dc = (DrawableContainer)drawableContainer;
dc.OnDoubleClick();
}
}
/// <summary>
/// Check if there are any intersecting filters, if so we need to redraw more
/// </summary>
/// <param name="clipRectangle"></param>
/// <returns>true if an filter intersects</returns>
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;
}
/// <summary>
/// Check if any of the drawableContainers are inside the rectangle
/// </summary>
/// <param name="clipRectangle"></param>
/// <returns></returns>
public bool IntersectsWith(Rectangle clipRectangle)
{
foreach (var dc in this)
{
if (dc.DrawingBounds.IntersectsWith(clipRectangle))
{
return true;
}
}
return false;
}
/// <summary>
/// Triggers all elements in the list ot be redrawn.
/// </summary>
/// <param name="g">the to the bitmap related Graphics object</param>
/// <param name="bitmap">Bitmap to draw</param>
/// <param name="renderMode">the rendermode in which the element is to be drawn</param>
/// <param name="clipRectangle"></param>
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);
}
}
}
/// <summary>
/// Pass the field changed event to all elements in the list
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void HandleFieldChangedEvent(object sender, FieldChangedEventArgs e)
{
foreach (var drawableContainer in this)
{
var dc = (DrawableContainer)drawableContainer;
dc.HandleFieldChanged(sender, e);
}
}
/// <summary>
/// Invalidate the bounds of all the DC's in this list
/// </summary>
public void Invalidate()
{
foreach (var dc in this)
{
dc.Invalidate();
}
}
/// <summary>
/// Indicates whether the given list of elements can be pulled up,
/// i.e. whether there is at least one unselected element higher in hierarchy
/// </summary>
/// <param name="elements">list of elements to pull up</param>
/// <returns>true if the elements could be pulled up</returns>
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;
}
/// <summary>
/// Pulls one or several elements up one level in hierarchy (z-index).
/// </summary>
/// <param name="elements">list of elements to pull up</param>
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);
}
}
}
/// <summary>
/// Pulls one or several elements up to the topmost level(s) in hierarchy (z-index).
/// </summary>
/// <param name="elements">of elements to pull to top</param>
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;
}
}
/// <summary>
/// Indicates whether the given list of elements can be pushed down,
/// i.e. whether there is at least one unselected element lower in hierarchy
/// </summary>
/// <param name="elements">list of elements to push down</param>
/// <returns>true if the elements could be pushed down</returns>
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;
}
/// <summary>
/// Pushes one or several elements down one level in hierarchy (z-index).
/// </summary>
/// <param name="elements">list of elements to push down</param>
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);
}
}
}
/// <summary>
/// Pushes one or several elements down to the bottommost level(s) in hierarchy (z-index).
/// </summary>
/// <param name="elements">of elements to push to bottom</param>
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;
}
}
/// <summary>
/// swaps two elements in hierarchy (z-index),
/// checks both indices to be in range
/// </summary>
/// <param name="index1">index of the 1st element</param>
/// <param name="index2">index of the 2nd element</param>
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;
}
/// <summary>
/// Add items to a context menu for the selected item
/// </summary>
/// <param name="menu"></param>
/// <param name="surface"></param>
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<DrawableContainer> containersToDelete = new List<DrawableContainer>();
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<DrawableContainer> containersToDelete = new List<DrawableContainer>();
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;
}
}
}
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using Greenshot.Drawing.Fields;
using Greenshot.Helpers;
using Greenshot.Plugin.Drawing;
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace Greenshot.Drawing
{
/// <summary>
/// Description of EllipseContainer.
/// </summary>
[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);
}
/// <summary>
/// This allows another container to draw an ellipse
/// </summary>
/// <param name="caller"></param>
/// <param name="rect"></param>
/// <param name="graphics"></param>
/// <param name="renderMode"></param>
/// <param name="lineThickness"></param>
/// <param name="lineColor"></param>
/// <param name="fillColor"></param>
/// <param name="shadow"></param>
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);
}
/// <summary>
/// Allow the code to be used externally
/// </summary>
/// <param name="caller"></param>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// Basic IFieldHolder implementation, providing access to a set of fields
/// </summary>
[Serializable]
public abstract class AbstractFieldHolder : IFieldHolder
{
private static readonly EditorConfiguration editorConfiguration = IniConfig.GetIniSection<EditorConfiguration>();
/// <summary>
/// called when a field's value has changed
/// </summary>
[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<FieldType, Field> fieldsByType = new Dictionary<FieldType, Field>();
private readonly List<Field> fields = new List<Field>();
[OnDeserialized]
private void OnDeserialized(StreamingContext context)
{
fieldsByType = new Dictionary<FieldType, Field>();
// 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<Field> 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);
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace Greenshot.Drawing.Fields
{
/// <summary>
/// Basic IFieldHolderWithChildren implementation. Similar to IFieldHolder,
/// but has a List<IFieldHolder> of children.
/// Field values are passed to and from children as well.
/// </summary>
[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<IFieldHolder> Children = new List<IFieldHolder>();
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<Field> GetFields()
{
List<Field> ret = new List<Field>();
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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
namespace Greenshot.Drawing.Fields.Binding
{
/// <summary>
/// Basic IBindingConverter implementation
/// </summary>
public abstract class AbstractBindingConverter<T1, T2> : 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);
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.ComponentModel;
using System.Reflection;
namespace Greenshot.Drawing.Fields.Binding
{
/// <summary>
/// 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
/// </summary>
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;
/// <summary>
/// Whether or not null values are passed on to the other object.
/// </summary>
protected bool AllowSynchronizeNull = true;
/// <summary>
/// Bind properties of two objects bidirectionally
/// </summary>
/// <param name="controlObject">Object containing 1st property to bind</param>
/// <param name="controlPropertyName">Property of 1st object to bind</param>
/// <param name="fieldObject">Object containing 2nd property to bind</param>
/// <param name="fieldPropertyName">Property of 2nd object to bind</param>
public BidirectionalBinding(INotifyPropertyChanged controlObject, string controlPropertyName, INotifyPropertyChanged fieldObject, string fieldPropertyName)
{
_controlObject = controlObject;
_fieldObject = fieldObject;
_controlPropertyName = controlPropertyName;
_fieldPropertyName = fieldPropertyName;
_controlObject.PropertyChanged += ControlPropertyChanged;
_fieldObject.PropertyChanged += FieldPropertyChanged;
}
/// <summary>
/// Bind properties of two objects bidirectionally, converting the values using a converter
/// </summary>
/// <param name="controlObject">Object containing 1st property to bind</param>
/// <param name="controlPropertyName">Property of 1st object to bind</param>
/// <param name="fieldObject">Object containing 2nd property to bind</param>
/// <param name="fieldPropertyName">Property of 2nd object to bind</param>
/// <param name="converter">taking care of converting the synchronized value to the correct target format and back</param>
public BidirectionalBinding(INotifyPropertyChanged controlObject, string controlPropertyName, INotifyPropertyChanged fieldObject, string fieldPropertyName, IBindingConverter converter) : this(controlObject, controlPropertyName, fieldObject, fieldPropertyName)
{
_converter = converter;
}
/// <summary>
/// Bind properties of two objects bidirectionally, converting the values using a converter.
/// Synchronization can be intercepted by adding a validator.
/// </summary>
/// <param name="controlObject">Object containing 1st property to bind</param>
/// <param name="controlPropertyName">Property of 1st object to bind</param>
/// <param name="fieldObject">Object containing 2nd property to bind</param>
/// <param name="fieldPropertyName">Property of 2nd object to bind</param>
/// <param name="validator">validator to intercept synchronization if the value does not match certain criteria</param>
public BidirectionalBinding(INotifyPropertyChanged controlObject, string controlPropertyName, INotifyPropertyChanged fieldObject, string fieldPropertyName, IBindingValidator validator) : this(controlObject, controlPropertyName, fieldObject, fieldPropertyName)
{
_validator = validator;
}
/// <summary>
/// Bind properties of two objects bidirectionally, converting the values using a converter.
/// Synchronization can be intercepted by adding a validator.
/// </summary>
/// <param name="controlObject">Object containing 1st property to bind</param>
/// <param name="controlPropertyName">Property of 1st object to bind</param>
/// <param name="fieldObject">Object containing 2nd property to bind</param>
/// <param name="fieldPropertyName">Property of 2nd object to bind</param>
/// <param name="converter">taking care of converting the synchronized value to the correct target format and back</param>
/// <param name="validator">validator to intercept synchronization if the value does not match certain criteria</param>
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; }
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
namespace Greenshot.Drawing.Fields.Binding
{
/// <summary>
/// Converts decimal to double (%) and vice versa, e.g. 95f <---> 0.95d
/// </summary>
public class DecimalDoublePercentageConverter : AbstractBindingConverter<double, decimal>
{
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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
namespace Greenshot.Drawing.Fields.Binding
{
/// <summary>
/// Converts decimal to float and vice versa.
/// </summary>
public class DecimalFloatConverter : AbstractBindingConverter<float, decimal>
{
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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
namespace Greenshot.Drawing.Fields.Binding
{
/// <summary>
/// Converts decimal to int and vice versa.
/// </summary>
public class DecimalIntConverter : AbstractBindingConverter<int, decimal>
{
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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
namespace Greenshot.Drawing.Fields.Binding
{
/// <summary>
/// Interface for a bidirectional converter, for use with BidirectionalBinding.
/// convert(object) implementation must deal with both directions.
/// see DecimalIntConverter
/// </summary>
public interface IBindingConverter
{
object convert(object o);
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
namespace Greenshot.Drawing.Fields.Binding
{
/// <summary>
/// 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
/// </summary>
public interface IBindingValidator
{
bool validate(object o);
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
namespace Greenshot.Drawing.Fields.Binding
{
/// <summary>
/// Validates a value not to be null.
/// </summary>
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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.ComponentModel;
namespace Greenshot.Drawing.Fields
{
/// <summary>
/// Represents a single field of a drawable element, i.e.
/// line thickness of a rectangle.
/// </summary>
[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;
/// <summary>
/// Constructs a new Field instance, usually you should be using FieldFactory
/// to create Fields.
/// </summary>
/// <param name="fieldType">FieldType of the Field to be created</param>
/// <param name="scope">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))
/// </param>
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;
}
/// <summary>
/// Returns true if this field holds a value other than null.
/// </summary>
public bool HasValue
{
get { return Value != null; }
}
/// <summary>
/// Creates a flat clone of this Field. The fields value itself is not cloned.
/// </summary>
/// <returns></returns>
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);
}
}
/// <summary>
/// EventHandler to be used when a field value changes
/// </summary>
public delegate void FieldChangedEventHandler(object sender, FieldChangedEventArgs e);
/// <summary>
/// EventArgs to be used with FieldChangedEventHandler
/// </summary>
public class FieldChangedEventArgs : EventArgs
{
public readonly Field Field;
public FieldChangedEventArgs(Field field)
{
Field = field;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using Greenshot.Configuration;
using Greenshot.IniFile;
using Greenshot.Plugin.Drawing;
using System.Collections.Generic;
using System.ComponentModel;
namespace Greenshot.Drawing.Fields
{
/// <summary>
/// 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.
/// </summary>
public class FieldAggregator : AbstractFieldHolder
{
private readonly List<IDrawableContainer> boundContainers;
private bool internalUpdateRunning;
private static readonly EditorConfiguration editorConfiguration = IniConfig.GetIniSection<EditorConfiguration>();
public FieldAggregator()
{
foreach (FieldType fieldType in FieldType.Values)
{
Field field = new Field(fieldType, GetType());
AddField(field);
}
boundContainers = new List<IDrawableContainer>();
}
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();
}
/// <summary>
/// sets all field values to null, however does not remove fields
/// </summary>
private void ClearFields()
{
internalUpdateRunning = true;
foreach (Field field in GetFields())
{
field.Value = null;
}
internalUpdateRunning = false;
}
/// <summary>
/// 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.
/// </summary>
private void UpdateFromBoundElements()
{
ClearFields();
internalUpdateRunning = true;
foreach (Field field in FindCommonFields())
{
SetFieldValue(field.FieldType, field.Value);
}
internalUpdateRunning = false;
}
private List<Field> FindCommonFields()
{
List<Field> 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<Field> fieldsToRemove = new List<Field>();
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<Field>();
}
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);
}
}
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
namespace Greenshot.Drawing.Fields
{
/// <summary>
/// Defines all FieldTypes + their default value.
/// (The additional value is why this is not an enum)
/// </summary>
[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);
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System.Collections.Generic;
namespace Greenshot.Drawing.Fields
{
/// <summary>
/// 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.
/// </summary>
public interface IFieldHolder
{
event FieldChangedEventHandler FieldChanged;
void AddField(Field field);
void RemoveField(Field field);
List<Field> GetFields();
Field GetField(FieldType fieldType);
bool HasField(FieldType fieldType);
void SetFieldValue(FieldType fieldType, object value);
}
/// <summary>
/// Extended fieldHolder which has fieldHolder children.
/// Implementations should pass field values to and from
/// their children.
/// AbstractFieldHolderWithChildren is the basic implementation.
/// </summary>
public interface IFieldHolderWithChildren : IFieldHolder
{
void AddChild(IFieldHolder fieldHolder);
void RemoveChild(IFieldHolder fieldHolder);
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using Greenshot.Drawing.Fields;
using Greenshot.Helpers;
using Greenshot.Plugin.Drawing;
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace Greenshot.Drawing
{
/// <summary>
/// empty container for filter-only elements
/// </summary>
[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);
}
}
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using Greenshot.Drawing.Fields;
using Greenshot.Plugin.Drawing;
using System;
using System.ComponentModel;
using System.Drawing;
/// <summary>
/// Graphical filter which can be added to DrawableContainer.
/// Subclasses should fulfill INotifyPropertyChanged contract, i.e. call
/// OnPropertyChanged whenever a public property has been changed.
/// </summary>
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));
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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);
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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);
}
/// <summary>
/// Implements the Apply code for the Brightness Filet
/// </summary>
/// <param name="graphics"></param>
/// <param name="applyBitmap"></param>
/// <param name="rect"></param>
/// <param name="renderMode"></param>
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);
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using Greenshot.Plugin.Drawing;
using GreenshotPlugin.Core;
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
namespace Greenshot.Drawing.Filters
{
/// <summary>
/// Description of GrayscaleFilter.
/// </summary>
[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);
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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);
}
/// <summary>
/// Implements the Apply code for the Brightness Filet
/// </summary>
/// <param name="graphics"></param>
/// <param name="applyBitmap"></param>
/// <param name="rect"></param>
/// <param name="renderMode"></param>
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);
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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; }
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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);
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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<Color> colors = new List<Color>();
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);
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// Description of PathContainer.
/// </summary>
[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<Point> capturePoints = new List<Point>();
private bool isRecalculated;
/// <summary>
/// Constructor
/// </summary>
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();
}
/// <summary>
/// This Dispose is called from the Dispose and the Destructor.
/// </summary>
/// <param name="disposing">When disposing==true all non-managed resources should be freed too!</param>
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
if (freehandPath != null)
{
freehandPath.Dispose();
}
}
freehandPath = null;
}
/// <summary>
/// Called from Surface (the parent) when the drawing begins (mouse-down)
/// </summary>
/// <returns>true if the surface doesn't need to handle the event</returns>
public override bool HandleMouseDown(int mouseX, int mouseY)
{
lastMouse = new Point(mouseX, mouseY);
capturePoints.Add(lastMouse);
return true;
}
/// <summary>
/// Called from Surface (the parent) if a mouse move is made while drawing
/// </summary>
/// <returns>true if the surface doesn't need to handle the event</returns>
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;
}
/// <summary>
/// Called when the surface finishes drawing the element
/// </summary>
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();
}
/// <summary>
/// Here we recalculate the freehand path by smoothing out the lines with Beziers.
/// </summary>
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());
}
/// <summary>
/// Do the drawing of the freehand "stroke"
/// </summary>
/// <param name="graphics"></param>
/// <param name="renderMode"></param>
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);
}
}
}
/// <summary>
/// Draw a selectionborder around the freehand path
/// </summary>
/// <param name="graphics"></param>
/// <param name="linePen"></param>
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);
}
}
}
/// <summary>
/// Get the bounds in which we have something drawn, plus safety margin, these are not the normal bounds...
/// </summary>
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);
}
}
/// <summary>
/// FreehandContainer are regarded equal if they are of the same type and their paths are equal.
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
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();
}
/// <summary>
/// This is overriden to prevent the grippers to be modified.
/// Might not be the best way...
/// </summary>
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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System.Drawing;
using System.Windows.Forms;
namespace Greenshot.Drawing
{
/// <summary>
/// Grippers are the dragable edges of our containers
/// </summary>
public class Gripper : Label
{
/// <summary>
/// Constants for anchor/gripper position:
/// 0 1 2
/// 7 3
/// 6 5 4
/// </summary>
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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using Greenshot.Drawing.Fields;
using Greenshot.Drawing.Filters;
using System;
using System.Runtime.Serialization;
namespace Greenshot.Drawing
{
/// <summary>
/// Description of ObfuscateContainer.
/// </summary>
[Serializable]
public class HighlightContainer : FilterContainer
{
public HighlightContainer(Surface parent) : base(parent)
{
Init();
}
/// <summary>
/// Use settings from base, extend with our own field
/// </summary>
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;
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using Greenshot.Plugin.Drawing;
using GreenshotPlugin;
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
namespace Greenshot.Drawing
{
/// <summary>
/// Description of IconContainer.
/// </summary>
[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;
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// Description of BitmapContainer.
/// </summary>
[Serializable]
public class ImageContainer : DrawableContainer, IImageContainer
{
private Image image;
/// <summary>
/// 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
/// </summary>
[NonSerialized]
private Image _shadowBitmap;
/// <summary>
/// This is the offset for the shadow version of the bitmap
/// Do not serialize, as the offset is recreated
/// </summary>
[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;
}
}
/// <summary>
/// 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!
/// </summary>
/// <param name="disposing"></param>
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;
}
/// <summary>
/// Make sure the content is also transformed.
/// </summary>
/// <param name="matrix"></param>
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);
}
/// <summary>
///
/// </summary>
/// <param name="filename"></param>
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);
}
}
/// <summary>
/// This checks if a shadow is already generated
/// </summary>
/// <param name="shadow"></param>
private void CheckShadow(bool shadow)
{
if (shadow && _shadowBitmap == null)
{
using (var matrix = new Matrix())
{
_shadowBitmap = ImageHelper.ApplyEffect(image, new DropShadowEffect(), matrix);
}
}
}
/// <summary>
/// Draw the actual container to the graphics object
/// </summary>
/// <param name="graphics"></param>
/// <param name="rm"></param>
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;
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// Description of LineContainer.
/// </summary>
[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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using Greenshot.Drawing.Fields;
using Greenshot.Drawing.Filters;
using System;
using System.Runtime.Serialization;
namespace Greenshot.Drawing
{
/// <summary>
/// Description of ObfuscateContainer.
/// </summary>
[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;
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using Greenshot.Drawing.Fields;
using Greenshot.Helpers;
using Greenshot.Plugin.Drawing;
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace Greenshot.Drawing
{
/// <summary>
/// Represents a rectangular shape on the Surface
/// </summary>
[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);
}
/// <summary>
/// This method can also be used from other containers, if the right values are passed!
/// </summary>
/// <param name="rect"></param>
/// <param name="graphics"></param>
/// <param name="rm"></param>
/// <param name="lineThickness"></param>
/// <param name="lineColor"></param>
/// <param name="fillColor"></param>
/// <param name="shadow"></param>
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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// Description of SpeechbubbleContainer.
/// </summary>
[Serializable]
public class SpeechbubbleContainer : TextContainer
{
private Point _initialGripperPoint;
#region TargetGripper serializing code
// Only used for serializing the TargetGripper location
private Point _storedTargetGripperLocation;
/// <summary>
/// Store the current location of the target gripper
/// </summary>
/// <param name="context"></param>
[OnSerializing]
private void SetValuesOnSerializing(StreamingContext context)
{
if (TargetGripper != null)
{
_storedTargetGripperLocation = TargetGripper.Location;
}
}
/// <summary>
/// Restore the target gripper
/// </summary>
/// <param name="context"></param>
[OnDeserialized]
private void SetValuesOnDeserialized(StreamingContext context)
{
InitTargetGripper(Color.Yellow, _storedTargetGripperLocation);
}
#endregion TargetGripper serializing code
public SpeechbubbleContainer(Surface parent)
: base(parent)
{
}
/// <summary>
/// We set our own field values
/// </summary>
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);
}
/// <summary>
/// Called from Surface (the _parent) when the drawing begins (mouse-down)
/// </summary>
/// <returns>true if the surface doesn't need to handle the event</returns>
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);
}
/// <summary>
/// Overriding the HandleMouseMove will help us to make sure the tail is always visible.
/// Should fix BUG-1682
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns>base.HandleMouseMove</returns>
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;
}
/// <summary>
/// The DrawingBound should be so close as possible to the shape, so we don't invalidate to much.
/// </summary>
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;
}
}
/// <summary>
/// Helper method to create the bubble GraphicsPath, so we can also calculate the bounds
/// </summary>
/// <param name="lineThickness"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Helper method to create the tail of the bubble, so we can also calculate the bounds
/// </summary>
/// <returns></returns>
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;
}
/// <summary>
/// This is to draw the actual container
/// </summary>
/// <param name="graphics"></param>
/// <param name="renderMode"></param>
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);
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// 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.
/// </summary>
[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;
}
}
/// <summary>
/// Retrieve the counter before serializing
/// </summary>
/// <param name="context"></param>
[OnSerializing]
private void SetValuesOnSerializing(StreamingContext context)
{
if (Parent != null)
{
Number = ((Surface)Parent).CountStepLabels(this);
}
}
#endregion Number serializing
/// <summary>
/// Restore values that don't serialize
/// </summary>
/// <param name="context"></param>
[OnDeserialized]
private void SetValuesOnDeserialized(StreamingContext context)
{
_stringFormat = new StringFormat();
_stringFormat.Alignment = StringAlignment.Center;
_stringFormat.LineAlignment = StringAlignment.Center;
}
/// <summary>
/// Add the StepLabel to the parent
/// </summary>
/// <param name="newParent"></param>
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;
}
/// <summary>
/// This makes it possible for the label to be placed exactly in the middle of the pointer.
/// </summary>
public override bool HandleMouseDown(int mouseX, int mouseY)
{
return base.HandleMouseDown(mouseX - Width / 2, mouseY - Height / 2);
}
/// <summary>
/// We set our own field values
/// </summary>
protected override void InitializeFields()
{
AddField(GetType(), FieldType.FILL_COLOR, DefaultLineColor);
AddField(GetType(), FieldType.LINE_COLOR, Color.White);
}
/// <summary>
/// Make sure this element is no longer referenced from the surface
/// </summary>
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;
}
/// <summary>
/// Make sure the size of the font is scaled
/// </summary>
/// <param name="matrix"></param>
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;
}
/// <summary>
/// Override the parent, calculate the label number, than draw
/// </summary>
/// <param name="graphics"></param>
/// <param name="rm"></param>
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);
}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// Represents a textbox (extends RectangleContainer for border/background support
/// </summary>
[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;
/// <summary>
/// The StringFormat object is not serializable!!
/// </summary>
[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();
}
/// <summary>
/// Makes textbox background dark if text color is very bright
/// </summary>
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);
}
/// <summary>
/// Make sure the size of the font is scaled
/// </summary>
/// <param name="matrix"></param>
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();
}
/// <summary>
/// Generate the Font-Formal so we can draw correctly
/// </summary>
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);
}
/// <summary>
/// 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...
/// </summary>
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);
}
/// <summary>
/// This method can be used from other containers
/// </summary>
/// <param name="graphics"></param>
/// <param name="drawingRectange"></param>
/// <param name="lineThickness"></param>
/// <param name="fontColor"></param>
/// <param name="drawShadow"></param>
/// <param name="stringFormat"></param>
/// <param name="text"></param>
/// <param name="font"></param>
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);
}
}
}

Some files were not shown because too many files have changed in this diff Show more