private InlineUIContainer RenderImage(HTML.Element e, ParagraphSizeTracker pst) { Uri ImageURI; if (e.Attributes.ContainsKey("src") && Uri.TryCreate(e.Attributes["src"], UriKind.RelativeOrAbsolute, out ImageURI)) { Image image = new Image() { Stretch = Stretch.Fill }; BitmapImage bitmapImage = new BitmapImage(); bitmapImage.BeginInit(); bitmapImage.UriSource = ImageURI; bitmapImage.EndInit(); image.Source = bitmapImage; if (ImageSizeCache.ContainsKey(ImageURI)) { Tuple <int, int> size = ImageSizeCache[ImageURI]; image.Width = size.Item1; image.Height = size.Item2; } // This hack forces image size to match pixel size, // which undermines WPF's preference for honoring the // embedded DPI value which leads to upscaled and // mildly blurry images where that doesn't match // the local display. Very high resolution displays // might need another approach. bitmapImage.DownloadCompleted += (s, ee) => { ImageSizeCache[ImageURI] = new Tuple <int, int>(bitmapImage.PixelWidth, bitmapImage.PixelHeight); image.Width = bitmapImage.PixelWidth; image.Height = bitmapImage.PixelHeight; }; // Communicate image size info back up to the container if (pst != null) { pst.Add(image); } if (e.Attributes.ContainsKey("title")) { image.ToolTip = e.Attributes["title"]; } else if (e.Attributes.ContainsKey("alt")) { image.ToolTip = e.Attributes["alt"]; } // TODO arrange to display alt value if image can't be loaded // (or before it has loaded) return(new InlineUIContainer() { Child = image }); } else { return(null); } }
private Inline ConvertInline(HTML.Node n, Context ctx, bool collapseSpace, ParagraphSizeTracker pst) { if (n is HTML.Element) { return(ConvertInlineElement((HTML.Element)n, ctx, collapseSpace, pst)); } else { Inline i = collapseSpace ? ConvertText(((HTML.Cdata)n).Content) : ConvertFixedText(((HTML.Cdata)n).Content); if (i != null) { i.FontSize = ctx.fontSize; i.FontFamily = ctx.fontFamily; i.FontWeight = ctx.fontWeight; i.FontStyle = ctx.fontStyle; } return(i); } }
private Inline ConvertInlineElement(HTML.Element e, Context ctx, bool collapseSpace, ParagraphSizeTracker pst) { Span s; switch (e.Name) { case "b": case "strong": s = new Span(); ctx = new Context(ctx) { fontWeight = FontWeights.Bold }; break; case "i": case "em": s = new Span(); ctx = new Context(ctx) { fontStyle = FontStyles.Italic }; break; case "u": s = new Underline(); break; case "big": { s = new Span(); double newSize = ctx.fontSize * 1.25; ctx = new Context(ctx) { fontSize = newSize }; break; } case "small": { s = new Span(); double newSize = ctx.fontSize / 1.25; ctx = new Context(ctx) { fontSize = newSize }; break; } case "code": case "tt": s = new Span(); ctx = new Context(ctx) { fontFamily = MonospaceFont }; break; case "sub": s = new Span(); s.Typography.Variants = FontVariants.Subscript; break; case "sup": s = new Span(); s.Typography.Variants = FontVariants.Superscript; break; case "a": s = RenderHyperlink(e); break; case "img": return(RenderImage(e, pst)); case "br": return(new LineBreak()); // TODO map, anything else? default: s = new Span(); break; } s.Inlines.AddRange(ConvertInlines(e, ctx, collapseSpace, pst)); return(s); }
private IEnumerable <Inline> ConvertInlines(HTML.Element e, Context ctx, bool collapseSpace, ParagraphSizeTracker pst) { return(from i in (from n in e.Contents select ConvertInline(n, ctx, collapseSpace, pst)) where i != null select i); }