Skip to content

Commit

Permalink
Added: Ability to load local image files
Browse files Browse the repository at this point in the history
  • Loading branch information
Savas Ziplies committed Mar 16, 2017
1 parent 25d7c41 commit 86d6678
Show file tree
Hide file tree
Showing 6 changed files with 199 additions and 138 deletions.
27 changes: 14 additions & 13 deletions MarkdownViewerPlusPlus/Forms/AbstractRenderer.cs
Expand Up @@ -19,6 +19,7 @@
using System.IO;
using System.Net;
using com.insanitydesign.MarkdownViewerPlusPlus.Helper;
using static com.insanitydesign.MarkdownViewerPlusPlus.MarkdownViewer;

/// <summary>
///
Expand Down Expand Up @@ -58,7 +59,7 @@ public abstract partial class AbstractRenderer : Form
/// <summary>
///
/// </summary>
protected virtual string FileName { get; set; }
protected virtual FileInformation FileInfo { get; set; }

/// <summary>
///
Expand Down Expand Up @@ -135,10 +136,10 @@ protected override void WndProc(ref Message m)
///
/// </summary>
/// <param name="text"></param>
/// <param name="fileName"></param>
public virtual void Render(string text, string fileName)
/// <param name="fileInfo"></param>
public virtual void Render(string text, FileInformation fileInfo)
{
FileName = fileName;
FileInfo = fileInfo;
RawText = text;
ConvertedText = CommonMarkConverter.Convert(text);
}
Expand Down Expand Up @@ -204,7 +205,7 @@ protected virtual void sendAsTextMail_Click(object sender, EventArgs e)
Outlook.Application outlook = new Outlook.Application();
Outlook.MailItem message = (Outlook.MailItem)outlook.CreateItem(Outlook.OlItemType.olMailItem);
//
message.Subject = FileName;
message.Subject = this.FileInfo.FileName;
message.BodyFormat = Outlook.OlBodyFormat.olFormatPlain;
message.Body = RawText;
message.Display();
Expand All @@ -224,9 +225,9 @@ protected virtual void sendAsHTMLMail_Click(object sender, EventArgs e)
Outlook.Application outlook = new Outlook.Application();
Outlook.MailItem message = (Outlook.MailItem)outlook.CreateItem(Outlook.OlItemType.olMailItem);
//
message.Subject = FileName;
message.Subject = this.FileInfo.FileName;
message.BodyFormat = Outlook.OlBodyFormat.olFormatHTML;
message.HTMLBody = BuildHtml(ConvertedText, FileName);
message.HTMLBody = BuildHtml(ConvertedText, this.FileInfo.FileName);
message.Display(true);
}
}
Expand All @@ -241,7 +242,7 @@ protected virtual void exportAsHTMLMenuItem_Click(object sender, EventArgs e)
//Save!
SaveFileDialog saveFileDialog = new SaveFileDialog();
//Default name of the file is the editor file name
saveFileDialog.FileName = Path.GetFileNameWithoutExtension(FileName) + ".html";
saveFileDialog.FileName = Path.GetFileNameWithoutExtension(this.FileInfo.FileName) + ".html";
//The current path
saveFileDialog.InitialDirectory = this.markdownViewer.Notepad.GetCurrentDirectory();
//
Expand All @@ -251,7 +252,7 @@ protected virtual void exportAsHTMLMenuItem_Click(object sender, EventArgs e)
{
using (StreamWriter sw = new StreamWriter(saveFileDialog.FileName))
{
string html = BuildHtml(ConvertedText, FileName);
string html = BuildHtml(ConvertedText, this.FileInfo.FileName);
try
{
html = XDocument.Parse(html).ToString();
Expand All @@ -277,7 +278,7 @@ protected virtual void exportAsPDFMenuItem_Click(object sender, EventArgs e)
//Save!
SaveFileDialog saveFileDialog = new SaveFileDialog();
//Default name of the file is the editor file name
saveFileDialog.FileName = Path.GetFileNameWithoutExtension(FileName) + ".pdf";
saveFileDialog.FileName = Path.GetFileNameWithoutExtension(this.FileInfo.FileName) + ".pdf";
//The current path
saveFileDialog.InitialDirectory = this.markdownViewer.Notepad.GetCurrentDirectory();
//
Expand All @@ -296,7 +297,7 @@ protected virtual void exportAsPDFMenuItem_Click(object sender, EventArgs e)
pdfConfig.MarginRight = MilimiterToPoint(margins[2]);
pdfConfig.MarginBottom = MilimiterToPoint(margins[3]);
//Generate PDF and save
PdfDocument pdf = PdfGenerator.GeneratePdf(BuildHtml(ConvertedText, FileName), pdfConfig, PdfGenerator.ParseStyleSheet(Resources.MarkdownViewerHTML));
PdfDocument pdf = PdfGenerator.GeneratePdf(BuildHtml(ConvertedText, this.FileInfo.FileName), pdfConfig, PdfGenerator.ParseStyleSheet(Resources.MarkdownViewerHTML));
pdf.Save(saveFileDialog.FileName);

//Open if requested
Expand All @@ -322,7 +323,7 @@ protected virtual void sendToPrinter_Click(object sender, EventArgs e)
((WebBrowser)browser).Size = webBrowser.MaximumSize;
((WebBrowser)browser).ShowPrintPreviewDialog();
};
webBrowser.DocumentText = BuildHtml(ConvertedText, FileName);
webBrowser.DocumentText = BuildHtml(ConvertedText, this.FileInfo.FileName);
}

/// <summary>
Expand All @@ -332,7 +333,7 @@ protected virtual void sendToPrinter_Click(object sender, EventArgs e)
/// <param name="e"></param>
protected void sendToClipboard_Click(object sender, EventArgs e)
{
ClipboardHelper.CopyToClipboard(BuildHtml(ConvertedText, FileName), ConvertedText);
ClipboardHelper.CopyToClipboard(BuildHtml(ConvertedText, this.FileInfo.FileName), ConvertedText);
}

/// <summary>
Expand Down
97 changes: 2 additions & 95 deletions MarkdownViewerPlusPlus/Forms/MarkdownViewerHtmlPanel.cs
@@ -1,11 +1,4 @@
using Svg;
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Net;
using TheArtOfDev.HtmlRenderer.Core.Entities;
using TheArtOfDev.HtmlRenderer.WinForms;
using TheArtOfDev.HtmlRenderer.WinForms;

/// <summary>
///
Expand All @@ -30,84 +23,7 @@ public MarkdownViewerHtmlPanel()
this.Name = "markdownViewerHtmlPanel";
this.Size = new System.Drawing.Size(284, 237);
this.TabIndex = 0;
//Add an SVG renderer
this.ImageLoad += OnImageLoad;
}

/// <summary>
/// Custom renderer for SVG images in the markdown as not supported natively.
/// @see https://htmlrenderer.codeplex.com/wikipage?title=Rendering%20SVG%20images
/// </summary>
/// <param name="sender"></param>
/// <param name="imageLoadEvent"></param>
protected void OnImageLoad(object sender, HtmlImageLoadEventArgs imageLoadEvent)
{
try
{
//Get some file information
string src = imageLoadEvent.Src;
Uri uri = new Uri(src);
string extension = Path.GetExtension(src);

//Check if local file or web resource
switch (uri.Scheme.ToLowerInvariant())
{
case "file":
//In case of a local file -> Load directly
if (extension != null && extension.Equals(".svg", StringComparison.OrdinalIgnoreCase))
{
ConvertSvgToBitmap(SvgDocument.Open<SvgDocument>(uri.LocalPath), imageLoadEvent);
}
break;
case "http":
case "https":
//For web resources check extension and parameter, to fetch from e.g. "badge" creating sources
if ((extension != null && extension.Equals(".svg", StringComparison.OrdinalIgnoreCase))
|| uri.ToString().Contains("svg="))
{
//In case of a web resource file -> Load async
using (WebClient webClient = new WebClient())
{
webClient.DownloadDataCompleted += (downloadSender, downloadEvent) => { OnDownloadDataCompleted(downloadEvent, imageLoadEvent); };
webClient.DownloadDataAsync(uri);
imageLoadEvent.Handled = true;
}
}
break;
}

} catch
{
}
}

/// <summary>
///
/// </summary>
/// <param name="svgDocument"></param>
/// <param name="imageLoadEvent"></param>
protected Bitmap ConvertSvgToBitmap(SvgDocument svgDocument, HtmlImageLoadEventArgs imageLoadEvent = null)
{
Bitmap svgImage = new Bitmap((int)svgDocument.Width, (int)svgDocument.Height, PixelFormat.Format32bppArgb);
svgDocument.Draw(svgImage);
if(imageLoadEvent != null)
{
imageLoadEvent.Callback(svgImage);
}
return svgImage;
}

/// <summary>
///
/// </summary>
/// <param name="downloadEvent"></param>
/// <param name="imageLoadEvent"></param>
protected void OnDownloadDataCompleted(DownloadDataCompletedEventArgs downloadEvent, HtmlImageLoadEventArgs imageLoadEvent)
{
using (MemoryStream stream = new MemoryStream(downloadEvent.Result))
{
ConvertSvgToBitmap(SvgDocument.Open<SvgDocument>(stream), imageLoadEvent);
}
this.AvoidImagesLateLoading = false;
}

/// <summary>
Expand Down Expand Up @@ -147,14 +63,5 @@ protected void Redraw()
Invalidate();
InvokeMouseMove();
}

/// <summary>
/// Release the SVGRenderer event
/// </summary>
protected override void Dispose(bool disposing)
{
this.ImageLoad -= OnImageLoad;
base.Dispose(disposing);
}
}
}
145 changes: 135 additions & 10 deletions MarkdownViewerPlusPlus/Forms/MarkdownViewerRenderer.cs
@@ -1,10 +1,12 @@
using com.insanitydesign.MarkdownViewerPlusPlus.Properties;
using PdfSharp.Pdf;
using System;
using System;
using System.IO;
using System.Windows.Forms;
using System.Xml.Linq;
using TheArtOfDev.HtmlRenderer.PdfSharp;
using Svg;
using System.Drawing;
using System.Drawing.Imaging;
using System.Net;
using System.Threading;
using TheArtOfDev.HtmlRenderer.Core.Entities;
using static com.insanitydesign.MarkdownViewerPlusPlus.MarkdownViewer;

/// <summary>
///
Expand Down Expand Up @@ -37,6 +39,8 @@ protected override void Init()
base.Init();
//
this.markdownViewerHtmlPanel = new MarkdownViewerHtmlPanel();
//Add a custom image loader
this.markdownViewerHtmlPanel.ImageLoad += OnImageLoad;
//Add to view
this.Controls.Add(this.markdownViewerHtmlPanel);
}
Expand All @@ -45,11 +49,11 @@ protected override void Init()
///
/// </summary>
/// <param name="text"></param>
/// <param name="fileName"></param>
public override void Render(string text, string fileName)
/// <param name="fileInfo"></param>
public override void Render(string text, FileInformation fileInfo)
{
base.Render(text, fileName);
this.markdownViewerHtmlPanel.Text = BuildHtml(ConvertedText, fileName);
base.Render(text, fileInfo);
this.markdownViewerHtmlPanel.Text = BuildHtml(ConvertedText, fileInfo.FileName);
}

/// <summary>
Expand All @@ -61,5 +65,126 @@ public override void ScrollByRatioVertically(double scrollRatio)
{
this.markdownViewerHtmlPanel.ScrollByRatioVertically(scrollRatio);
}

/// <summary>
/// Custom renderer for SVG images in the markdown as not supported natively.
/// @see https://htmlrenderer.codeplex.com/wikipage?title=Rendering%20SVG%20images
/// </summary>
/// <param name="sender"></param>
/// <param name="imageLoadEvent"></param>
protected void OnImageLoad(object sender, HtmlImageLoadEventArgs imageLoadEvent)
{
try
{
//Get some file information
string src = imageLoadEvent.Src;
Uri uri = new Uri(src);
string extension = Path.GetExtension(src);

//Check if local file or web resource
switch (uri.Scheme.ToLowerInvariant())
{
case "file":
//In case of a local file -> Try to load it directly
imageLoadEvent.Handled = true; //Tell the event it was handled, so no error border is drawn
ThreadPool.QueueUserWorkItem(state => LoadImageFromFile(src, imageLoadEvent));
break;
case "http":
case "https":
//For web resources check extension and parameter, to fetch from e.g. "badge" creating sources
if ((extension != null && extension.Equals(".svg", StringComparison.OrdinalIgnoreCase))
|| uri.ToString().Contains("svg="))
{
//In case of a web resource file -> Load async
using (WebClient webClient = new WebClient())
{
imageLoadEvent.Handled = true; //Tell the event it was handled, so no error border is drawn
webClient.DownloadDataCompleted += (downloadSender, downloadEvent) => { OnDownloadDataCompleted(downloadEvent, imageLoadEvent); };
webClient.DownloadDataAsync(uri);
}
}
break;
}

}
catch
{
}
}

/// <summary>
///
/// </summary>
/// <param name="src"></param>
/// <param name="imageLoadEvent"></param>
protected void LoadImageFromFile(string src, HtmlImageLoadEventArgs imageLoadEvent)
{
try
{
Uri uri = new Uri(src);
//Try to load the file as Image from file
//Remove the scheme first
string srcWithoutScheme = src;
int i = srcWithoutScheme.IndexOf(':');
if (i > 0) srcWithoutScheme = srcWithoutScheme.Substring(i + 1).TrimStart('/');
//If not absolute, add the current file path
if (!Path.IsPathRooted(srcWithoutScheme))
{
uri = new Uri(@"file:///" + this.FileInfo.FileDirectory + "/" + srcWithoutScheme);
}

//For SVG images: Convert to Bitmap
string extension = Path.GetExtension(src);
if (extension != null && extension.Equals(".svg", StringComparison.OrdinalIgnoreCase))
{
ConvertSvgToBitmap(SvgDocument.Open<SvgDocument>(uri.LocalPath), imageLoadEvent);
}
else
{
//Load uri, 8, 1
imageLoadEvent.Callback((Bitmap)Image.FromFile(uri.LocalPath, true));
}
}
catch { } //Not able to handle, refer back to orginal process
}

/// <summary>
///
/// </summary>
/// <param name="svgDocument"></param>
/// <param name="imageLoadEvent"></param>
protected Bitmap ConvertSvgToBitmap(SvgDocument svgDocument, HtmlImageLoadEventArgs imageLoadEvent)
{
Bitmap svgImage = new Bitmap((int)svgDocument.Width, (int)svgDocument.Height, PixelFormat.Format32bppArgb);
svgDocument.Draw(svgImage);
imageLoadEvent.Callback(svgImage);
imageLoadEvent.Handled = true;
return svgImage;
}

/// <summary>
///
/// </summary>
/// <param name="downloadEvent"></param>
/// <param name="imageLoadEvent"></param>
protected void OnDownloadDataCompleted(DownloadDataCompletedEventArgs downloadEvent, HtmlImageLoadEventArgs imageLoadEvent)
{
using (MemoryStream stream = new MemoryStream(downloadEvent.Result))
{
ConvertSvgToBitmap(SvgDocument.Open<SvgDocument>(stream), imageLoadEvent);
}
}

/// <summary>
/// Release the custom loader
/// </summary>
protected override void Dispose(bool disposing)
{
if (this.markdownViewerHtmlPanel != null)
{
this.markdownViewerHtmlPanel.ImageLoad -= OnImageLoad;
}
base.Dispose(disposing);
}
}
}

0 comments on commit 86d6678

Please sign in to comment.