Created
November 1, 2013 21:16
-
-
Save dotMorten/7272085 to your computer and use it in GitHub Desktop.
A XAML based PictureMarkerSymbol for the ArcGIS Runtime .NET SDK
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Esri.ArcGISRuntime.Symbology; | |
using System; | |
using System.IO; | |
using System.Threading.Tasks; | |
using System.Windows; | |
#if NETFX_CORE | |
using Windows.UI.Xaml.Markup; | |
using Windows.UI.Xaml; | |
using Windows.UI.Xaml.Controls; | |
using Windows.Foundation; | |
using Windows.UI.Xaml.Media.Imaging; | |
using System.Threading; | |
using System.Runtime.InteropServices.WindowsRuntime; | |
#else | |
using System.Windows.Controls; | |
using System.Windows.Media; | |
using System.Windows.Media.Imaging; | |
using System.Windows.Markup; | |
#endif | |
namespace MortensGists | |
{ | |
#if NETFX_CORE | |
[ContentProperty(Name = "Template")] | |
#else | |
[ContentProperty("Template")] | |
#endif | |
public class XamlMarkerSymbol : PictureMarkerSymbol | |
{ | |
private DataTemplate m_Template; | |
public XamlMarkerSymbol() | |
{ | |
Dpi = 96f; | |
} | |
public DataTemplate Template | |
{ | |
get { return m_Template; } | |
set | |
{ | |
if (m_Template != value) | |
{ | |
m_Template = value; | |
Task t = RenderAsync(); //TODO: Handle fallback in case task doesn't succeed | |
} | |
} | |
} | |
/* Getting DPI (WPF): | |
System.Windows.Media.Matrix m = | |
PresentationSource.FromVisual(MyMap).CompositionTarget.TransformToDevice; | |
float dpi = 96f & m.M11; | |
*/ | |
public float Dpi { get; set; } | |
private async Task RenderAsync() | |
{ | |
ContentControl content = new ContentControl(); | |
content.Content = this; | |
content.ContentTemplate = this.Template; | |
double w = this.Width / 72 * 96; //convert points to DIPs | |
double h = this.Height / 72 * 96; //convert points to DIPs | |
if (w == 0 || h == 0) | |
{ | |
content.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); | |
w = content.DesiredSize.Width; | |
h = content.DesiredSize.Height; | |
} | |
if (w < 0.5 || h < 0.5) | |
{ | |
#if NETFX_CORE | |
await SetSourceAsync(null as Windows.Storage.Streams.IRandomAccessStream); | |
#else | |
await SetSourceAsync(null as Stream); | |
#endif | |
return; | |
} | |
content.Arrange(new Rect(0, 0, w, h)); | |
int pixelWidth = (int)(w * Dpi / 96); //DIPs to pixel | |
int pixelHeight = (int)(h * Dpi / 96); //DIPs to pixel | |
#if WINDOWS_PHONE | |
WriteableBitmap bmp = new WriteableBitmap(pixelWidth, pixelHeight); | |
bmp.Render(content, null); | |
bmp.Invalidate(); | |
#elif NETFX_CORE | |
RenderTargetBitmap bmp = new RenderTargetBitmap(); | |
await bmp.RenderAsync(content, (int)pixelWidth, (int)pixelHeight).AsTask(); | |
var pixelBuffer = (await bmp.GetPixelsAsync().AsTask().ConfigureAwait(false)).AsStream(); | |
byte[] pixels = new byte[pixelBuffer.Length]; | |
pixelBuffer.Write(pixels, 0, pixels.Length); | |
var png = new MemoryStream().AsRandomAccessStream(); | |
var encoder = await Windows.Graphics.Imaging.BitmapEncoder.CreateAsync(Windows.Graphics.Imaging.BitmapEncoder.PngEncoderId, png).AsTask(); | |
encoder.SetPixelData(Windows.Graphics.Imaging.BitmapPixelFormat.Rgba8, Windows.Graphics.Imaging.BitmapAlphaMode.Straight, | |
(uint)pixelWidth, (uint)pixelHeight, Dpi, Dpi, pixels); | |
await encoder.FlushAsync().AsTask(); | |
await SetSourceAsync(png); | |
#else //WPF | |
RenderTargetBitmap bmp = new RenderTargetBitmap(pixelWidth, pixelHeight, Dpi, Dpi, PixelFormats.Default); | |
bmp.Render(content); | |
PngBitmapEncoder png = new PngBitmapEncoder(); | |
png.Frames.Add(BitmapFrame.Create(bmp)); | |
using (Stream stm = new MemoryStream()) | |
{ | |
png.Save(stm); | |
stm.Seek(0, SeekOrigin.Begin); | |
await SetSourceAsync(stm); | |
} | |
#endif | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment