public void DrawCard(int nX, int nY, Graphics zGraphics, DeckLine zDeckLine, bool bExport, bool bDrawBackground) { List <string> listLine = zDeckLine.LineColumns; // Custom Graphics Setting zGraphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit; zGraphics.SmoothingMode = SmoothingMode.AntiAlias; //zGraphics.SmoothingMode = SmoothingMode.HighQuality; var matrixOriginal = zGraphics.Transform; // Zoom does not apply to export if (!bExport) { zGraphics.ScaleTransform(ZoomLevel, ZoomLevel); // Custom Graphics Setting zGraphics.InterpolationMode = 1.0f != ZoomLevel ? InterpolationMode.NearestNeighbor : InterpolationMode.Bilinear; } //Logger.Clear(); ProjectLayoutElement zSelectedElement = null; if (!bExport) { zSelectedElement = ElementManager.Instance.GetSelectedElement(); } // draw the background if (bDrawBackground) { zGraphics.FillRectangle(Brushes.White, nX, nY, CurrentDeck.CardLayout.width, CurrentDeck.CardLayout.height); } // All drawing is handled in reverse element order if (null != CurrentDeck.CardLayout.Element) { for (var nIdx = CurrentDeck.CardLayout.Element.Length - 1; nIdx > -1; nIdx--) { var zElement = CurrentDeck.CardLayout.Element[nIdx]; if (zElement.enabled) // only add enabled items to draw { IssueManager.Instance.FireChangeElementEvent(zElement.name); // get override Element ProjectLayoutElement zOverrideElement = CurrentDeck.GetOverrideElement(zElement, listLine, zDeckLine, bExport); var zDrawElement = zOverrideElement; // translate any index values in the csv var zElementString = CurrentDeck.TranslateString(zDrawElement.variable, zDeckLine, zDrawElement, bExport); // enabled is re-checked due to possible override of the enabled value if (!zElementString.DrawElement || !zDrawElement.enabled) { continue; } var eType = DrawItem.GetElementType(zDrawElement.type); //NOTE: removed transform backup (draw element resets it anyway...) //if (!bExport) // backup is only necessary for zoomed canvas //{ //matrixPrevious = zGraphics.Transform; //} DrawItem.DrawElement(zGraphics, CurrentDeck, zDrawElement, eType, nX, nY, zElementString.String, bExport); if (!bExport) { //zGraphics.Transform = matrixPrevious; zGraphics.ScaleTransform(ZoomLevel, ZoomLevel); } } } if (!bExport) { // draw all selections and element borders after everything else for (var nIdx = CurrentDeck.CardLayout.Element.Length - 1; nIdx > -1; nIdx--) { ProjectLayoutElement zElement = CurrentDeck.CardLayout.Element[nIdx]; if (zElement.enabled) // only add enabled items to draw { var bDrawSelection = zSelectedElement == zElement; if (CardMakerInstance.DrawElementBorder) { var matrixPrevious = zGraphics.Transform; DrawItem.DrawElementDebugBorder(zGraphics, zElement, nX, nY, bDrawSelection); zGraphics.Transform = matrixPrevious; } } } } } // draw the card border if ((bExport && CardMakerSettings.PrintLayoutBorder) || (!bExport && CurrentDeck.CardLayout.drawBorder)) { // note that the border is inclusive in the width/height consuming 2 pixels (0 to total-1) zGraphics.DrawRectangle(Pens.Black, nX, nY, CurrentDeck.CardLayout.width - 1, CurrentDeck.CardLayout.height - 1); } zGraphics.Transform = matrixOriginal; }
public void DrawText(Graphics zGraphics, ProjectLayoutElement zElement, string sInput, Brush zBrush, Font zFont, Color colorFont) { if (null == zFont) // default to something! { // font will show up in red if it's not yet set zFont = DrawItem.DefaultFont; zBrush = Brushes.Red; } var zFormat = new StringFormat { LineAlignment = zElement.GetVerticalAlignment(), Alignment = zElement.GetHorizontalAlignment() }; if (255 != zElement.opacity) { zBrush = 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 { // prepare to draw text var zPath = new GraphicsPath(); try { zPath.AddString(sInput, zFont.FontFamily, (int)zFont.Style, fEmSize, new RectangleF(0, 0, zElement.width, zElement.height), zFormat); DrawItem.DrawOutline(zElement, zGraphics, zPath); } catch (Exception) { Logger.AddLogLine("Unable to render text (font issue?)"); } // fill in the outline zGraphics.FillPath(zBrush, zPath); } }
public void DrawText(Graphics zGraphics, ProjectLayoutElement zElement, string sInput, Brush zBrush, Font zFont, Color colorFont) { if (null == zFont) // default to something! { // font will show up in red if it's not yet set zFont = DrawItem.DefaultFont; zBrush = Brushes.Red; } TextFormatFlags zFormatFlags = TextFormatFlags.WordBreak | TextFormatFlags.NoClipping; switch (zElement.GetVerticalAlignment()) { case StringAlignment.Center: zFormatFlags |= TextFormatFlags.VerticalCenter; break; case StringAlignment.Far: zFormatFlags |= TextFormatFlags.Bottom; break; } switch (zElement.GetHorizontalAlignment()) { case StringAlignment.Center: zFormatFlags |= TextFormatFlags.HorizontalCenter; break; case StringAlignment.Far: zFormatFlags |= TextFormatFlags.Right; break; } #warning TextRenderer apparently does not support opactiy?! Bitmap zOpacityBitmap = null; if (255 != zElement.opacity) { zOpacityBitmap = new Bitmap(zElement.width, zElement.height, PixelFormat.Format32bppArgb); zOpacityBitmap.SetResolution(zGraphics.DpiY, zGraphics.DpiY); } if (zElement.autoscalefont) { var zSize = TextRenderer.MeasureText(sInput, zFont, new Size(zElement.width, int.MaxValue), zFormatFlags); 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 = new Font(zFont.FontFamily, newSizeRatio * zFont.Size, zFont.Style); 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; const float FONT_SCALE_ADJUST = 0.25f; if (0 < sInput.Trim().Length) { while (true) { zSize = TextRenderer.MeasureText(sInput, zFont, new Size(zElement.width, int.MaxValue), zFormatFlags); if (zSize.Height > zElement.height || zSize.Width > zElement.width) { if (zFont.Size <= 1) { break; } zFont = new Font(zFont.FontFamily, zFont.Size - FONT_SCALE_ADJUST, zFont.Style); Logger.AddLogLine("ADJ A [" + zFont.Size + "]"); if (bUpscaled) { break; } } else { zFont = new Font(zFont.FontFamily, zFont.Size + FONT_SCALE_ADJUST, zFont.Style); Logger.AddLogLine("ADJ B [" + zFont.Size + "]"); bUpscaled = true; } } } #endif } // else -- font size is fine for this element } else { zFormatFlags |= TextFormatFlags.EndEllipsis; } Logger.AddLogLine("[" + zFont.Size + "]"); var arrayDrawLines = new string[] { sInput }; var nLineOffset = 0; 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; } foreach (var sLine in arrayDrawLines) { if (0 == zElement.outlinethickness) { try { if (null != zOpacityBitmap) { // TODO: https://stackoverflow.com/questions/18838037/drawing-text-to-a-bitmap-with-textrenderer #warning too bad this makes the font look terrible #if true var image = new Bitmap(zElement.width, zElement.height, PixelFormat.Format32bppArgb); // create memory buffer from desktop handle that supports alpha channel IntPtr dib; var memoryHdc = CreateMemoryHdc(IntPtr.Zero, image.Width, image.Height, out dib); try { // create memory buffer graphics to use for HTML rendering using (var memoryGraphics = Graphics.FromHdc(memoryHdc)) { // must not be transparent background memoryGraphics.Clear(Color.White); TextRenderer.DrawText(memoryGraphics, sLine, zFont, new Rectangle(0, 0, zElement.width, zElement.height), colorFont, zFormatFlags); } // copy from memory buffer to image using (var imageGraphics = Graphics.FromImage(image)) { var imgHdc = imageGraphics.GetHdc(); BitBlt(imgHdc, 0, 0, image.Width, image.Height, memoryHdc, 0, 0, 0x00CC0020); imageGraphics.ReleaseHdc(imgHdc); } } finally { // release memory buffer DeleteObject(dib); DeleteDC(memoryHdc); } #else var zGraphicsTemp = Graphics.FromImage(zOpacityBitmap); zGraphicsTemp.SmoothingMode = SmoothingMode.AntiAlias; zGraphicsTemp.TextRenderingHint = TextRenderingHint.AntiAliasGridFit; TextRenderer.DrawText(zGraphicsTemp, sLine, zFont, new Rectangle(0, 0, zElement.width, zElement.height), colorFont, zFormatFlags); var zColor = new ColorMatrix { Matrix33 = (float)zElement.opacity / 255.0f }; var zAttrib = new ImageAttributes(); zAttrib.SetColorMatrix(zColor); var zBitmap = new Bitmap(zOpacityBitmap); // target image var zGraphicsX = Graphics.FromImage(zBitmap); zGraphicsTemp.SmoothingMode = SmoothingMode.AntiAlias; zGraphicsTemp.TextRenderingHint = TextRenderingHint.AntiAliasGridFit; // draw the source image into the destination with the desired opacity zGraphicsX.DrawImage(zOpacityBitmap, new Rectangle(0, 0, zBitmap.Width, zBitmap.Height), 0, 0, zBitmap.Width, zBitmap.Height, GraphicsUnit.Pixel, zAttrib); #endif // offset is already applied zGraphics.DrawImageUnscaled(image, 0, 0); } else { TextRenderer.DrawText(zGraphics, sLine, zFont, new Rectangle((int)zGraphics.Transform.OffsetX, (int)zGraphics.Transform.OffsetY, zElement.width, zElement.height), colorFont, zFormatFlags); } } catch (Exception) { Logger.AddLogLine("Unable to render text (font issue?)"); } } else { // prepare to draw text var zPath = new GraphicsPath(); try { #warning is there a path based text renderer thing to use? var zFormat = new StringFormat { LineAlignment = zElement.GetVerticalAlignment(), Alignment = zElement.GetHorizontalAlignment(), Trimming = StringTrimming.None, FormatFlags = StringFormatFlags.NoClip }; zPath.AddString(sLine, zFont.FontFamily, (int)zFont.Style, fEmSize, new RectangleF(0, nLineOffset, zElement.width, zElement.height), zFormat); DrawItem.DrawOutline(zElement, zGraphics, zPath); } catch (Exception) { Logger.AddLogLine("Unable to render text (font issue?)"); } // fill in the outline zGraphics.FillPath(zBrush, zPath); } nLineOffset += zElement.lineheight; } }