public void DrawText(Graphics zGraphics, ProjectLayoutElement zElement, string sInput) { var zFont = zElement.GetElementFont(); var colorFont = zElement.GetElementColor(); if (null == zFont) // default to something! { // font will show up in red if it's not yet set zFont = FontLoader.DefaultFont; } var zFormat = new StringFormat { LineAlignment = zElement.GetVerticalAlignment(), Alignment = zElement.GetHorizontalAlignment() }; var zBrush = 255 == zElement.opacity ? new SolidBrush(colorFont) : new SolidBrush(Color.FromArgb(zElement.opacity, colorFont)); if (zElement.autoscalefont) { SizeF zSize = zGraphics.MeasureString(sInput, zFont, new SizeF(zElement.width, int.MaxValue), zFormat); if (zSize.Height > zElement.height || zSize.Width > zElement.width) { float newSizeRatio; if ((zSize.Height - zElement.height) > (zSize.Width - zElement.width)) { newSizeRatio = (float)zElement.height / (float)zSize.Height; } else { newSizeRatio = (float)zElement.width / (float)zSize.Width; } var scaledFont = FontLoader.GetFont(zFont.FontFamily, newSizeRatio * zFont.Size, zFont.Style); //Support.IO.Logger.AddLogLine(scaledFont.Size + " was [" + zFont.Size + "]"); zFont = scaledFont; #if true // the preprocessing above will get the font size close but not perfect, the slow code below further refines the size // slow mode - but perfect precision (well arguably with the Graphics.MeasureString) bool bUpscaled = false; if (0 < sInput.Trim().Length) { while (true) { zSize = zGraphics.MeasureString(sInput, zFont, new SizeF(zElement.width, int.MaxValue), zFormat); if (zSize.Height > zElement.height || zSize.Width > zElement.width) { if (zFont.Size == 1) { break; } zFont = FontLoader.GetFont(zFont.FontFamily, zFont.Size - 1, zFont.Style); if (bUpscaled) { break; } } else { zFont = FontLoader.GetFont(zFont.FontFamily, zFont.Size + 1, zFont.Style); bUpscaled = true; } } //Support.IO.Logger.AddLogLine("[" + zFont.Size + "]"); } #endif } // else -- font size is fine for this element } else { zFormat.Trimming = StringTrimming.EllipsisCharacter; } var fEmSize = zFont.Size; switch (zFont.Unit) { case GraphicsUnit.Point: fEmSize = zGraphics.DpiY * (zFont.Size / 72f); break; default: Logger.AddLogLine("This font is using the Unit: {0} (not currently supported)".FormatString(zFont.Unit.ToString())); break; } if (0 == zElement.outlinethickness) { try { zGraphics.DrawString(sInput, zFont, zBrush, new RectangleF(0, 0, zElement.width, zElement.height), zFormat); } catch (Exception) { Logger.AddLogLine("Unable to render text (font issue?)"); } } else { try { var zPath = new GraphicsPath(); zPath.AddString(sInput, zFont.FontFamily, (int)zFont.Style, fEmSize, new RectangleF(0, 0, zElement.width, zElement.height), zFormat); CardRenderer.DrawElementPath(zElement, zGraphics, zPath, zBrush); } catch (Exception) { Logger.AddLogLine("Unable to render text (font issue?)"); } } }
/// <summary> /// Processes the formatted text data into rendered markups. /// </summary> /// <param name="zGraphics">The graphics to use to plan the render</param> /// <param name="zElement">The element</param> /// <param name="fMainFontSize">The font size to use for the default font</param> /// <param name="zFormattedTextData">The processed formatted text data</param> /// <returns>List of markups to be rendered</returns> protected List <MarkupBase> processMarkupDefinition(Graphics zGraphics, ProjectLayoutElement zElement, float fMainFontSize, FormattedTextData zFormattedTextData) { var colorFont = zElement.GetElementColor(); var zBrush = 255 == zElement.opacity ? new SolidBrush(colorFont) : new SolidBrush(Color.FromArgb(zElement.opacity, colorFont)); var zProcessData = new FormattedTextProcessData { FontBrush = zBrush, CurrentLineHeight = zElement.lineheight, CurrentStringAlignment = zElement.GetHorizontalAlignment() }; var zFont = zElement.GetElementFont(); if (null == zFont) // default to something! { // font will show up in red if it's not yet set zFont = FontLoader.DefaultFont; } var zScaledFont = FontLoader.GetFont(zFont.FontFamily, fMainFontSize, zFont.Style); // set the initial font zProcessData.SetFont(zScaledFont, zGraphics); var listPassMarkups = new List <MarkupBase>(); // only contains the markups that will be actively drawn (for caching) // Pass 1: // - Create rectangles // - Configure per-markup settings based on state of markup stack // - Generate list of markups to continue to process (those that are used in the next pass) // - Specify Markup rectanlges // - Generate markup rows (LineNumber is usable AFTER this process) int nIdx; MarkupBase zMarkup; for (nIdx = 0; nIdx < zFormattedTextData.AllMarkups.Count; nIdx++) { zMarkup = zFormattedTextData.AllMarkups[nIdx]; if (zMarkup.ProcessMarkup(zElement, zFormattedTextData, zProcessData, zGraphics)) { zMarkup.LineNumber = zProcessData.CurrentLine; listPassMarkups.Add(zMarkup); } } // Pass 2: // - Trim spaces from line endings if (listPassMarkups.Count > 0) { nIdx = listPassMarkups.Count - 1; zMarkup = listPassMarkups[nIdx]; var currentLineNumber = zMarkup.LineNumber; var bFindNextLine = false; while (nIdx > -1) { zMarkup = listPassMarkups[nIdx]; if (zMarkup.LineNumber != currentLineNumber) { currentLineNumber = zMarkup.LineNumber; bFindNextLine = false; } if (!bFindNextLine && zMarkup is SpaceMarkup && ((SpaceMarkup)zMarkup).Optional) { listPassMarkups.RemoveAt(nIdx); } else { bFindNextLine = true; } nIdx--; } } // Pass 3: // - Align lines (horizontal/vertical) // Reprocess for align (before backgroundcolor is configured) AlignmentController.UpdateAlignment(zElement, listPassMarkups); // Pass 4: process the remaining items nIdx = 0; while (nIdx < listPassMarkups.Count) { zMarkup = listPassMarkups[nIdx]; if (!zMarkup.PostProcessMarkupRectangle(zElement, listPassMarkups, nIdx)) { listPassMarkups.RemoveAt(nIdx); continue; } nIdx++; } return(listPassMarkups); }