/// <summary> /// Assigns words its width and height /// </summary> /// <param name="g"></param> internal void MeasureWordsSize(Graphics g) { // Check if measure white space if not yet done to measure once if (!_wordsSizeMeasured) { MeasureWordSpacing(g); if (HtmlTag != null && HtmlTag.Name == "img") { var image = CssValueParser.GetImage(GetAttribute("src"), HtmlContainer.Bridge); var word = new CssBoxWord(this, image); Words.Clear(); Words.Add(word); } else if (Words.Count > 0) { foreach (var boxWord in Words) { var sf = new StringFormat(); sf.SetMeasurableCharacterRanges(new[] { new CharacterRange(0, boxWord.Text.Length) }); var regions = g.MeasureCharacterRanges(boxWord.Text, ActualFont, new RectangleF(0, 0, float.MaxValue, float.MaxValue), sf); SizeF s = regions[0].GetBounds(g).Size; PointF p = regions[0].GetBounds(g).Location; boxWord.LastMeasureOffset = new PointF(p.X, p.Y); boxWord.Width = s.Width + ActualWordSpacing; boxWord.Height = s.Height; } } _wordsSizeMeasured = true; } }
/// <summary> /// Write the given html tag with all its attributes and styles. /// </summary> /// <param name="sb">the string builder to write html into</param> /// <param name="box">the css box with the html tag to write</param> /// <param name="indent">the indent to use for nice formating</param> /// <param name="styleGen">Controls the way styles are generated when html is generated</param> private static void WriteHtmlTag(StringBuilder sb, CssBox box, int indent, HtmlGenerationStyle styleGen) { sb.Append(new string(' ', indent * 4)); sb.AppendFormat("<{0}", box.HtmlTag.Name); // collect all element style properties incliding from stylesheet var tagStyles = new Dictionary <string, string>(); var tagCssBlock = box.HtmlContainer.CssData.GetCssBlock(box.HtmlTag.Name); if (tagCssBlock != null) { // atodo: handle selectors foreach (var cssBlock in tagCssBlock) { foreach (var prop in cssBlock.Properties) { tagStyles[prop.Key] = prop.Value; } } } if (box.HtmlTag.Attributes.Count > 0) { sb.Append(" "); foreach (var att in box.HtmlTag.Attributes) { // handle image tags by inserting the image using base64 data if (box.HtmlTag.Name == "img" && att.Key == "src" && (att.Value.StartsWith("property") || att.Value.StartsWith("method"))) { var img = CssValueParser.GetImage(att.Value, box.HtmlContainer.Bridge); if (img != null) { using (var buffer = new MemoryStream()) { img.Save(buffer, ImageFormat.Png); var base64 = Convert.ToBase64String(buffer.ToArray()); sb.AppendFormat("{0}=\"data:image/png;base64, {1}\" ", att.Key, base64); } } } else if (styleGen == HtmlGenerationStyle.Inline && att.Key == HtmlConstants.Style) { // if inline style add the styles to the collection var block = CssParser.ParseCssBlockImp(box.HtmlTag.Name, box.HtmlTag.Attributes["style"]); foreach (var prop in block.Properties) { tagStyles[prop.Key] = prop.Value; } } else if (styleGen == HtmlGenerationStyle.Inline && att.Key == HtmlConstants.Class) { // if inline style convert the style class to actual properties and add to collection var cssBlocks = box.HtmlContainer.CssData.GetCssBlock("." + att.Value); if (cssBlocks != null) { // atodo: handle selectors foreach (var cssBlock in cssBlocks) { foreach (var prop in cssBlock.Properties) { tagStyles[prop.Key] = prop.Value; } } } } else { sb.AppendFormat("{0}=\"{1}\" ", att.Key, att.Value); } } sb.Remove(sb.Length - 1, 1); } // if inline style insert the style tag with all collected style properties if (styleGen == HtmlGenerationStyle.Inline && tagStyles.Count > 0) { sb.Append(" style=\""); foreach (var style in tagStyles) { sb.AppendFormat("{0}: {1}; ", style.Key, style.Value); } sb.Remove(sb.Length - 1, 1); sb.Append("\""); } sb.AppendFormat("{0}>", box.HtmlTag.IsSingle ? "/" : ""); sb.AppendLine(); }