Skip to content

Commit 86d6678

Browse files
author
Savas Ziplies
committed
Added: Ability to load local image files
1 parent 25d7c41 commit 86d6678

File tree

6 files changed

+199
-138
lines changed

6 files changed

+199
-138
lines changed

MarkdownViewerPlusPlus/Forms/AbstractRenderer.cs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
using System.IO;
2020
using System.Net;
2121
using com.insanitydesign.MarkdownViewerPlusPlus.Helper;
22+
using static com.insanitydesign.MarkdownViewerPlusPlus.MarkdownViewer;
2223

2324
/// <summary>
2425
///
@@ -58,7 +59,7 @@ public abstract partial class AbstractRenderer : Form
5859
/// <summary>
5960
///
6061
/// </summary>
61-
protected virtual string FileName { get; set; }
62+
protected virtual FileInformation FileInfo { get; set; }
6263

6364
/// <summary>
6465
///
@@ -135,10 +136,10 @@ protected override void WndProc(ref Message m)
135136
///
136137
/// </summary>
137138
/// <param name="text"></param>
138-
/// <param name="fileName"></param>
139-
public virtual void Render(string text, string fileName)
139+
/// <param name="fileInfo"></param>
140+
public virtual void Render(string text, FileInformation fileInfo)
140141
{
141-
FileName = fileName;
142+
FileInfo = fileInfo;
142143
RawText = text;
143144
ConvertedText = CommonMarkConverter.Convert(text);
144145
}
@@ -204,7 +205,7 @@ protected virtual void sendAsTextMail_Click(object sender, EventArgs e)
204205
Outlook.Application outlook = new Outlook.Application();
205206
Outlook.MailItem message = (Outlook.MailItem)outlook.CreateItem(Outlook.OlItemType.olMailItem);
206207
//
207-
message.Subject = FileName;
208+
message.Subject = this.FileInfo.FileName;
208209
message.BodyFormat = Outlook.OlBodyFormat.olFormatPlain;
209210
message.Body = RawText;
210211
message.Display();
@@ -224,9 +225,9 @@ protected virtual void sendAsHTMLMail_Click(object sender, EventArgs e)
224225
Outlook.Application outlook = new Outlook.Application();
225226
Outlook.MailItem message = (Outlook.MailItem)outlook.CreateItem(Outlook.OlItemType.olMailItem);
226227
//
227-
message.Subject = FileName;
228+
message.Subject = this.FileInfo.FileName;
228229
message.BodyFormat = Outlook.OlBodyFormat.olFormatHTML;
229-
message.HTMLBody = BuildHtml(ConvertedText, FileName);
230+
message.HTMLBody = BuildHtml(ConvertedText, this.FileInfo.FileName);
230231
message.Display(true);
231232
}
232233
}
@@ -241,7 +242,7 @@ protected virtual void exportAsHTMLMenuItem_Click(object sender, EventArgs e)
241242
//Save!
242243
SaveFileDialog saveFileDialog = new SaveFileDialog();
243244
//Default name of the file is the editor file name
244-
saveFileDialog.FileName = Path.GetFileNameWithoutExtension(FileName) + ".html";
245+
saveFileDialog.FileName = Path.GetFileNameWithoutExtension(this.FileInfo.FileName) + ".html";
245246
//The current path
246247
saveFileDialog.InitialDirectory = this.markdownViewer.Notepad.GetCurrentDirectory();
247248
//
@@ -251,7 +252,7 @@ protected virtual void exportAsHTMLMenuItem_Click(object sender, EventArgs e)
251252
{
252253
using (StreamWriter sw = new StreamWriter(saveFileDialog.FileName))
253254
{
254-
string html = BuildHtml(ConvertedText, FileName);
255+
string html = BuildHtml(ConvertedText, this.FileInfo.FileName);
255256
try
256257
{
257258
html = XDocument.Parse(html).ToString();
@@ -277,7 +278,7 @@ protected virtual void exportAsPDFMenuItem_Click(object sender, EventArgs e)
277278
//Save!
278279
SaveFileDialog saveFileDialog = new SaveFileDialog();
279280
//Default name of the file is the editor file name
280-
saveFileDialog.FileName = Path.GetFileNameWithoutExtension(FileName) + ".pdf";
281+
saveFileDialog.FileName = Path.GetFileNameWithoutExtension(this.FileInfo.FileName) + ".pdf";
281282
//The current path
282283
saveFileDialog.InitialDirectory = this.markdownViewer.Notepad.GetCurrentDirectory();
283284
//
@@ -296,7 +297,7 @@ protected virtual void exportAsPDFMenuItem_Click(object sender, EventArgs e)
296297
pdfConfig.MarginRight = MilimiterToPoint(margins[2]);
297298
pdfConfig.MarginBottom = MilimiterToPoint(margins[3]);
298299
//Generate PDF and save
299-
PdfDocument pdf = PdfGenerator.GeneratePdf(BuildHtml(ConvertedText, FileName), pdfConfig, PdfGenerator.ParseStyleSheet(Resources.MarkdownViewerHTML));
300+
PdfDocument pdf = PdfGenerator.GeneratePdf(BuildHtml(ConvertedText, this.FileInfo.FileName), pdfConfig, PdfGenerator.ParseStyleSheet(Resources.MarkdownViewerHTML));
300301
pdf.Save(saveFileDialog.FileName);
301302

302303
//Open if requested
@@ -322,7 +323,7 @@ protected virtual void sendToPrinter_Click(object sender, EventArgs e)
322323
((WebBrowser)browser).Size = webBrowser.MaximumSize;
323324
((WebBrowser)browser).ShowPrintPreviewDialog();
324325
};
325-
webBrowser.DocumentText = BuildHtml(ConvertedText, FileName);
326+
webBrowser.DocumentText = BuildHtml(ConvertedText, this.FileInfo.FileName);
326327
}
327328

328329
/// <summary>
@@ -332,7 +333,7 @@ protected virtual void sendToPrinter_Click(object sender, EventArgs e)
332333
/// <param name="e"></param>
333334
protected void sendToClipboard_Click(object sender, EventArgs e)
334335
{
335-
ClipboardHelper.CopyToClipboard(BuildHtml(ConvertedText, FileName), ConvertedText);
336+
ClipboardHelper.CopyToClipboard(BuildHtml(ConvertedText, this.FileInfo.FileName), ConvertedText);
336337
}
337338

338339
/// <summary>
Lines changed: 2 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,4 @@
1-
using Svg;
2-
using System;
3-
using System.Drawing;
4-
using System.Drawing.Imaging;
5-
using System.IO;
6-
using System.Net;
7-
using TheArtOfDev.HtmlRenderer.Core.Entities;
8-
using TheArtOfDev.HtmlRenderer.WinForms;
1+
using TheArtOfDev.HtmlRenderer.WinForms;
92

103
/// <summary>
114
///
@@ -30,84 +23,7 @@ public MarkdownViewerHtmlPanel()
3023
this.Name = "markdownViewerHtmlPanel";
3124
this.Size = new System.Drawing.Size(284, 237);
3225
this.TabIndex = 0;
33-
//Add an SVG renderer
34-
this.ImageLoad += OnImageLoad;
35-
}
36-
37-
/// <summary>
38-
/// Custom renderer for SVG images in the markdown as not supported natively.
39-
/// @see https://htmlrenderer.codeplex.com/wikipage?title=Rendering%20SVG%20images
40-
/// </summary>
41-
/// <param name="sender"></param>
42-
/// <param name="imageLoadEvent"></param>
43-
protected void OnImageLoad(object sender, HtmlImageLoadEventArgs imageLoadEvent)
44-
{
45-
try
46-
{
47-
//Get some file information
48-
string src = imageLoadEvent.Src;
49-
Uri uri = new Uri(src);
50-
string extension = Path.GetExtension(src);
51-
52-
//Check if local file or web resource
53-
switch (uri.Scheme.ToLowerInvariant())
54-
{
55-
case "file":
56-
//In case of a local file -> Load directly
57-
if (extension != null && extension.Equals(".svg", StringComparison.OrdinalIgnoreCase))
58-
{
59-
ConvertSvgToBitmap(SvgDocument.Open<SvgDocument>(uri.LocalPath), imageLoadEvent);
60-
}
61-
break;
62-
case "http":
63-
case "https":
64-
//For web resources check extension and parameter, to fetch from e.g. "badge" creating sources
65-
if ((extension != null && extension.Equals(".svg", StringComparison.OrdinalIgnoreCase))
66-
|| uri.ToString().Contains("svg="))
67-
{
68-
//In case of a web resource file -> Load async
69-
using (WebClient webClient = new WebClient())
70-
{
71-
webClient.DownloadDataCompleted += (downloadSender, downloadEvent) => { OnDownloadDataCompleted(downloadEvent, imageLoadEvent); };
72-
webClient.DownloadDataAsync(uri);
73-
imageLoadEvent.Handled = true;
74-
}
75-
}
76-
break;
77-
}
78-
79-
} catch
80-
{
81-
}
82-
}
83-
84-
/// <summary>
85-
///
86-
/// </summary>
87-
/// <param name="svgDocument"></param>
88-
/// <param name="imageLoadEvent"></param>
89-
protected Bitmap ConvertSvgToBitmap(SvgDocument svgDocument, HtmlImageLoadEventArgs imageLoadEvent = null)
90-
{
91-
Bitmap svgImage = new Bitmap((int)svgDocument.Width, (int)svgDocument.Height, PixelFormat.Format32bppArgb);
92-
svgDocument.Draw(svgImage);
93-
if(imageLoadEvent != null)
94-
{
95-
imageLoadEvent.Callback(svgImage);
96-
}
97-
return svgImage;
98-
}
99-
100-
/// <summary>
101-
///
102-
/// </summary>
103-
/// <param name="downloadEvent"></param>
104-
/// <param name="imageLoadEvent"></param>
105-
protected void OnDownloadDataCompleted(DownloadDataCompletedEventArgs downloadEvent, HtmlImageLoadEventArgs imageLoadEvent)
106-
{
107-
using (MemoryStream stream = new MemoryStream(downloadEvent.Result))
108-
{
109-
ConvertSvgToBitmap(SvgDocument.Open<SvgDocument>(stream), imageLoadEvent);
110-
}
26+
this.AvoidImagesLateLoading = false;
11127
}
11228

11329
/// <summary>
@@ -147,14 +63,5 @@ protected void Redraw()
14763
Invalidate();
14864
InvokeMouseMove();
14965
}
150-
151-
/// <summary>
152-
/// Release the SVGRenderer event
153-
/// </summary>
154-
protected override void Dispose(bool disposing)
155-
{
156-
this.ImageLoad -= OnImageLoad;
157-
base.Dispose(disposing);
158-
}
15966
}
16067
}

MarkdownViewerPlusPlus/Forms/MarkdownViewerRenderer.cs

Lines changed: 135 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
using com.insanitydesign.MarkdownViewerPlusPlus.Properties;
2-
using PdfSharp.Pdf;
3-
using System;
1+
using System;
42
using System.IO;
5-
using System.Windows.Forms;
6-
using System.Xml.Linq;
7-
using TheArtOfDev.HtmlRenderer.PdfSharp;
3+
using Svg;
4+
using System.Drawing;
5+
using System.Drawing.Imaging;
6+
using System.Net;
7+
using System.Threading;
8+
using TheArtOfDev.HtmlRenderer.Core.Entities;
9+
using static com.insanitydesign.MarkdownViewerPlusPlus.MarkdownViewer;
810

911
/// <summary>
1012
///
@@ -37,6 +39,8 @@ protected override void Init()
3739
base.Init();
3840
//
3941
this.markdownViewerHtmlPanel = new MarkdownViewerHtmlPanel();
42+
//Add a custom image loader
43+
this.markdownViewerHtmlPanel.ImageLoad += OnImageLoad;
4044
//Add to view
4145
this.Controls.Add(this.markdownViewerHtmlPanel);
4246
}
@@ -45,11 +49,11 @@ protected override void Init()
4549
///
4650
/// </summary>
4751
/// <param name="text"></param>
48-
/// <param name="fileName"></param>
49-
public override void Render(string text, string fileName)
52+
/// <param name="fileInfo"></param>
53+
public override void Render(string text, FileInformation fileInfo)
5054
{
51-
base.Render(text, fileName);
52-
this.markdownViewerHtmlPanel.Text = BuildHtml(ConvertedText, fileName);
55+
base.Render(text, fileInfo);
56+
this.markdownViewerHtmlPanel.Text = BuildHtml(ConvertedText, fileInfo.FileName);
5357
}
5458

5559
/// <summary>
@@ -61,5 +65,126 @@ public override void ScrollByRatioVertically(double scrollRatio)
6165
{
6266
this.markdownViewerHtmlPanel.ScrollByRatioVertically(scrollRatio);
6367
}
68+
69+
/// <summary>
70+
/// Custom renderer for SVG images in the markdown as not supported natively.
71+
/// @see https://htmlrenderer.codeplex.com/wikipage?title=Rendering%20SVG%20images
72+
/// </summary>
73+
/// <param name="sender"></param>
74+
/// <param name="imageLoadEvent"></param>
75+
protected void OnImageLoad(object sender, HtmlImageLoadEventArgs imageLoadEvent)
76+
{
77+
try
78+
{
79+
//Get some file information
80+
string src = imageLoadEvent.Src;
81+
Uri uri = new Uri(src);
82+
string extension = Path.GetExtension(src);
83+
84+
//Check if local file or web resource
85+
switch (uri.Scheme.ToLowerInvariant())
86+
{
87+
case "file":
88+
//In case of a local file -> Try to load it directly
89+
imageLoadEvent.Handled = true; //Tell the event it was handled, so no error border is drawn
90+
ThreadPool.QueueUserWorkItem(state => LoadImageFromFile(src, imageLoadEvent));
91+
break;
92+
case "http":
93+
case "https":
94+
//For web resources check extension and parameter, to fetch from e.g. "badge" creating sources
95+
if ((extension != null && extension.Equals(".svg", StringComparison.OrdinalIgnoreCase))
96+
|| uri.ToString().Contains("svg="))
97+
{
98+
//In case of a web resource file -> Load async
99+
using (WebClient webClient = new WebClient())
100+
{
101+
imageLoadEvent.Handled = true; //Tell the event it was handled, so no error border is drawn
102+
webClient.DownloadDataCompleted += (downloadSender, downloadEvent) => { OnDownloadDataCompleted(downloadEvent, imageLoadEvent); };
103+
webClient.DownloadDataAsync(uri);
104+
}
105+
}
106+
break;
107+
}
108+
109+
}
110+
catch
111+
{
112+
}
113+
}
114+
115+
/// <summary>
116+
///
117+
/// </summary>
118+
/// <param name="src"></param>
119+
/// <param name="imageLoadEvent"></param>
120+
protected void LoadImageFromFile(string src, HtmlImageLoadEventArgs imageLoadEvent)
121+
{
122+
try
123+
{
124+
Uri uri = new Uri(src);
125+
//Try to load the file as Image from file
126+
//Remove the scheme first
127+
string srcWithoutScheme = src;
128+
int i = srcWithoutScheme.IndexOf(':');
129+
if (i > 0) srcWithoutScheme = srcWithoutScheme.Substring(i + 1).TrimStart('/');
130+
//If not absolute, add the current file path
131+
if (!Path.IsPathRooted(srcWithoutScheme))
132+
{
133+
uri = new Uri(@"file:///" + this.FileInfo.FileDirectory + "/" + srcWithoutScheme);
134+
}
135+
136+
//For SVG images: Convert to Bitmap
137+
string extension = Path.GetExtension(src);
138+
if (extension != null && extension.Equals(".svg", StringComparison.OrdinalIgnoreCase))
139+
{
140+
ConvertSvgToBitmap(SvgDocument.Open<SvgDocument>(uri.LocalPath), imageLoadEvent);
141+
}
142+
else
143+
{
144+
//Load uri, 8, 1
145+
imageLoadEvent.Callback((Bitmap)Image.FromFile(uri.LocalPath, true));
146+
}
147+
}
148+
catch { } //Not able to handle, refer back to orginal process
149+
}
150+
151+
/// <summary>
152+
///
153+
/// </summary>
154+
/// <param name="svgDocument"></param>
155+
/// <param name="imageLoadEvent"></param>
156+
protected Bitmap ConvertSvgToBitmap(SvgDocument svgDocument, HtmlImageLoadEventArgs imageLoadEvent)
157+
{
158+
Bitmap svgImage = new Bitmap((int)svgDocument.Width, (int)svgDocument.Height, PixelFormat.Format32bppArgb);
159+
svgDocument.Draw(svgImage);
160+
imageLoadEvent.Callback(svgImage);
161+
imageLoadEvent.Handled = true;
162+
return svgImage;
163+
}
164+
165+
/// <summary>
166+
///
167+
/// </summary>
168+
/// <param name="downloadEvent"></param>
169+
/// <param name="imageLoadEvent"></param>
170+
protected void OnDownloadDataCompleted(DownloadDataCompletedEventArgs downloadEvent, HtmlImageLoadEventArgs imageLoadEvent)
171+
{
172+
using (MemoryStream stream = new MemoryStream(downloadEvent.Result))
173+
{
174+
ConvertSvgToBitmap(SvgDocument.Open<SvgDocument>(stream), imageLoadEvent);
175+
}
176+
}
177+
178+
/// <summary>
179+
/// Release the custom loader
180+
/// </summary>
181+
protected override void Dispose(bool disposing)
182+
{
183+
if (this.markdownViewerHtmlPanel != null)
184+
{
185+
this.markdownViewerHtmlPanel.ImageLoad -= OnImageLoad;
186+
}
187+
base.Dispose(disposing);
188+
}
64189
}
65190
}

0 commit comments

Comments
 (0)