using FastReport.Export.Hpgl; using FastReport.Export.Hpgl.Utils; using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.Drawing.Text; using System.Linq; using System.Text; namespace FastReport.Utils { internal class HpglGraphicsRenderer : IGraphics { private HpglDocument hpglDocument; private Graphics measureGraphics; private Bitmap internalImage; private System.Drawing.Drawing2D.Matrix transformMatrix; private HpglFillMode fillMode; private float barcodesGap; float IGraphics.DpiY { get { throw new NotImplementedException(); } } TextRenderingHint IGraphics.TextRenderingHint { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } InterpolationMode IGraphics.InterpolationMode { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } SmoothingMode IGraphics.SmoothingMode { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } Graphics IGraphics.Graphics { get { throw new NotImplementedException(); } } System.Drawing.Drawing2D.Matrix IGraphics.Transform { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } GraphicsUnit IGraphics.PageUnit { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } bool IGraphics.IsClipEmpty { get { throw new NotImplementedException(); } } Region IGraphics.Clip { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } float IGraphics.DpiX { get { throw new NotImplementedException(); } } CompositingQuality IGraphics.CompositingQuality { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } public HpglGraphicsRenderer(HpglDocument hpglDocument, HpglFillMode fillMode, float barcodesGap) { this.internalImage = new Bitmap(1, 1); this.hpglDocument = hpglDocument; this.measureGraphics = Graphics.FromImage(internalImage); transformMatrix = new System.Drawing.Drawing2D.Matrix(); this.fillMode = fillMode; this.barcodesGap = barcodesGap; } private LineStyle GetLineStyle(DashStyle dashStyle) { LineStyle lineStyle; switch (dashStyle) { case DashStyle.Dash: lineStyle = LineStyle.Dash; break; case DashStyle.DashDot: lineStyle = LineStyle.DashDot; break; case DashStyle.DashDotDot: lineStyle = LineStyle.DashDotDot; break; case DashStyle.Dot: lineStyle = LineStyle.Dot; break; case DashStyle.Solid: default: lineStyle = LineStyle.Solid; break; } return lineStyle; } public void Dispose() { //if (hpglDocument != null) //{ // hpglDocument.Clear(); // hpglDocument = null; //} if (measureGraphics != null) { measureGraphics.Dispose(); measureGraphics = null; } } public void DrawEllipse(Pen pen, float left, float top, float width, float height) { LineStyle lineStyle = GetLineStyle(pen.DashStyle); hpglDocument.DrawEllipse(left + transformMatrix.OffsetX, transformMatrix.OffsetY - top, width, height, pen.Color, pen.Width, lineStyle); } private PointF GetOrtogonalPoint(PointF a, PointF b, float bc) { float x2x1 = a.X - b.X; float y2y1 = a.Y - b.Y; float ab = (float)Math.Sqrt(x2x1 * x2x1 + y2y1 * y2y1); float v1x = (b.X - a.X) / ab; float v1y = (b.Y - a.Y) / ab; float v3x = (v1y > 0 ? -v1y : v1y) * bc; float v3y = (v1x > 0 ? v1x : -v1x) * bc; PointF c = new PointF(); c.X = a.X + v3x; c.Y = a.Y + v3y; return c; } public void DrawLine(Pen pen, float x1, float y1, float x2, float y2) { LineStyle lineStyle = GetLineStyle(pen.DashStyle); //if(fillMode != HpglFillMode.Border) // hpglDocument.DrawLine(x1 + transformMatrix.OffsetX, transformMatrix.OffsetY - y1, x2 + transformMatrix.OffsetX, transformMatrix.OffsetY - y2, pen.Color, pen.Width, lineStyle); //else { PointF[] points = new PointF[4]; points[0] = GetOrtogonalPoint(new PointF(x1, y1), new PointF(x2, y2), pen.Width / 2); points[1] = GetOrtogonalPoint(new PointF(x2, y2), new PointF(x1, y1), pen.Width / 2); points[2] = GetOrtogonalPoint(new PointF(x2, y2), new PointF(x1, y1), -pen.Width / 2); points[3] = GetOrtogonalPoint(new PointF(x1, y1), new PointF(x2, y2), -pen.Width / 2); SolidBrush brush = (fillMode == HpglFillMode.Border) ? null : new SolidBrush(pen.Color); hpglDocument.DrawPolygon(transformMatrix.OffsetX, transformMatrix.OffsetY, points.InvertY(), new byte[points.Length], (pen.Brush as SolidBrush).Color, 1 / 100.0f, LineStyle.Solid, brush); } } public void DrawString(string text, Font drawFont, Brush brush, float left, float top) { //ToDo - baseLine DrawStringInternal(text, drawFont, brush, left, top, 0); } public void DrawString(string text, Font drawFont, Brush brush, float left, float top, float baseLine) { DrawStringInternal(text, drawFont, brush, left, top, baseLine); } public void DrawString(string text, Font drawFont, Brush brush, RectangleF rectangleF) { //ToDo - baseLine DrawStringInternal(text, drawFont, brush, rectangleF.X, rectangleF.Y, 0); } private void DrawStringInternal(string text, Font font, Brush brush, float left, float top, float baseLine) { if (!String.IsNullOrEmpty(text)) { GraphicsPath myPath = new GraphicsPath(); PointF origin = new PointF(0, 0); // Add the string to the path. myPath.AddString(text, font.FontFamily, (int)font.Style, font.Size, origin, StringFormat.GenericDefault); if (brush is SolidBrush) AddGraphicsPath(myPath, (brush as SolidBrush).Color, 1 / 100.0f, LineStyle.Solid, transformMatrix.OffsetX + left, transformMatrix.OffsetY - top, true, true, 0, new PointF(0, 0)); } } private void FillGraphicsPath(float x, float y, GraphicsPath path, Brush brush, bool invertY) { List points = new List(); List pTypes = new List(); byte[] pathTypes = path.PathTypes; PointF[] pathPoints = path.PathPoints; if (invertY) pathPoints = pathPoints.InvertY(); for (int i = 0; i < pathTypes.Length; i++) { byte pType = pathTypes[i]; PointF point = pathPoints[i]; if (pType == 0 && points.Count > 0) { if (fillMode == HpglFillMode.Solid) hpglDocument.FillPolygon(x, y, points.ToArray(), pTypes.ToArray(), brush); else hpglDocument.DrawPolygon(x, y, points.ToArray(), pTypes.ToArray(), (brush as SolidBrush).Color, 1 / 100.0f, LineStyle.Solid); points.Clear(); pTypes.Clear(); } points.Add(point); pTypes.Add(pType); if (i == pathTypes.Length - 1) { if (fillMode == HpglFillMode.Solid) hpglDocument.FillPolygon(0, 0, points.ToArray(), pTypes.ToArray(), brush); else hpglDocument.DrawPolygon(0, 0, points.ToArray(), pTypes.ToArray(), (brush as SolidBrush).Color, 1 / 100.0f, LineStyle.Solid); } } } public static PointF[] RotateVector(PointF[] vector, double angle, PointF center) { PointF[] rotatedVector = new PointF[vector.Length]; for (int i = 0; i < vector.Length; i++) { rotatedVector[i].X = (float)(center.X + (vector[i].X - center.X) * Math.Cos(angle) + (center.Y - vector[i].Y) * Math.Sin(angle)); rotatedVector[i].Y = (float)(center.Y + (vector[i].X - center.X) * Math.Sin(angle) + (vector[i].Y - center.Y) * Math.Cos(angle)); } return rotatedVector; } private void AddGraphicsPath(GraphicsPath path, Color borderColor, float borderWith, LineStyle borderLineStyle, float left, float top, bool isClosed, bool invertY, float angle, PointF center) { List points = new List(); List pTypes = new List(); byte[] pathTypes = path.PathTypes; PointF[] pathPoints = path.PathPoints; if (angle != 0) { // rotate pathPoints = RotateVector(pathPoints, angle, center); } if (invertY) pathPoints = pathPoints.InvertY(); for (int i = 0; i < pathTypes.Length; i++) { byte pType = pathTypes[i]; PointF point = pathPoints[i]; if (pType == 0 && points.Count > 0) { AddPath(points.ToArray(), pTypes.ToArray(), borderColor, borderWith, borderLineStyle, left, top, isClosed); points.Clear(); pTypes.Clear(); } points.Add(point); pTypes.Add(pType); if (i == pathTypes.Length - 1) { AddPath(points.ToArray(), pTypes.ToArray(), borderColor, borderWith, borderLineStyle, left, top, isClosed); } } } private void AddPath(PointF[] points, byte[] pointTypes, Color borderColor, float borderWidth, LineStyle borderLineStyle, float left, float top, bool isClosed) { float x = left; float y = top; hpglDocument.DrawPolyLine(x, y, points, pointTypes, borderColor, borderWidth / Units.Millimeters, borderLineStyle, isClosed); } public void FillPath(Brush brush, GraphicsPath path) { if (fillMode == HpglFillMode.Solid && brush is SolidBrush) FillGraphicsPath(transformMatrix.OffsetX, transformMatrix.OffsetY, path, brush, true); else AddGraphicsPath(path, (brush as SolidBrush).Color, 1 / 100.0f, LineStyle.Solid, transformMatrix.OffsetX, transformMatrix.OffsetY, true, true, 0, new PointF(0, 0)); } public void FillPolygon(Brush brush, PointF[] points) { if (fillMode == HpglFillMode.Solid && brush is SolidBrush) hpglDocument.FillPolygon(transformMatrix.OffsetX, transformMatrix.OffsetY, points.InvertY(), new byte[points.Length], brush); else hpglDocument.DrawPolygon(transformMatrix.OffsetX, transformMatrix.OffsetY, points.InvertY(), new byte[points.Length], (brush as SolidBrush).Color, 1 / 100.0f, LineStyle.Solid); //if (brush is SolidBrush) // hpglDocument.FillPolygon(transformMatrix.OffsetX, transformMatrix.OffsetY, points.InvertY(), new byte[points.Length], (brush as SolidBrush).Color); } private void TransformPoints(System.Drawing.Drawing2D.Matrix fTransformMatrix, PointF[] points) { float a = fTransformMatrix.Elements[0]; // scale horizontal float b = fTransformMatrix.Elements[1]; // lean vert float c = fTransformMatrix.Elements[2]; // lean horizontal float d = fTransformMatrix.Elements[3]; //scale vertical float e = fTransformMatrix.Elements[4]; // x offset float f = 0;// fTransformMatrix.Elements[5]; // y offset for (int i = 0; i < points.Length; i++) { float x0 = points[i].X; float y0 = points[i].Y; float x1 = a * x0 + c * y0 + e; float y1 = b * x0 + d * y0 + f; points[i].X = x1; points[i].Y = y1; } } public void FillRectangle(Brush brush, float left, float top, float width, float height) { if (brush is SolidBrush) { //if o degies // hpglDocument.FillRectangle(left + transformMatrix.OffsetX, transformMatrix.OffsetY - top - height, width, height, (brush as SolidBrush).Color); //else PointF[] points = new PointF[4]; points[0] = new PointF(left, top); points[1] = new PointF(left + width, top); points[2] = new PointF(left + width, top + height); points[3] = new PointF(left, top + height); TransformPoints(transformMatrix, points); points = points.InvertY(); if (fillMode == HpglFillMode.Solid && brush is SolidBrush) hpglDocument.FillPolygon(0, transformMatrix.OffsetY, points, new byte[points.Length], brush); else hpglDocument.DrawPolygon(0, transformMatrix.OffsetY, points, new byte[points.Length], (brush as SolidBrush).Color, 1 / 100.0f, LineStyle.Solid); } } public SizeF MeasureString(string text, Font drawFont) { return this.measureGraphics.MeasureString(text, drawFont); } public void Restore(IGraphicsState state) { if (state is HpglFGraphicsRendererState) { HpglFGraphicsRendererState gState = state as HpglFGraphicsRendererState; transformMatrix = gState.Matrix; } } public void RotateTransform(float angle) { transformMatrix.Rotate(angle); } public IGraphicsState Save() { return new HpglFGraphicsRendererState(transformMatrix); } public void TranslateTransform(float left, float top) { transformMatrix.Translate(left, top); } void IGraphics.SetClip(RectangleF textRect) { throw new NotImplementedException(); } void IGraphics.DrawPath(Pen outlinePen, GraphicsPath path) { throw new NotImplementedException(); } void IGraphics.DrawString(string text, Font font, Brush textBrush, RectangleF textRect, StringFormat format) { throw new NotImplementedException(); } void IGraphics.FillEllipse(Brush brush, float x, float y, float dx, float dy) { throw new NotImplementedException(); } void IGraphics.DrawImage(Image image, float x, float y) { throw new NotImplementedException(); } void IGraphics.DrawLines(Pen pen, PointF[] pointFs) { throw new NotImplementedException(); } void IGraphics.FillRectangle(Brush brush, RectangleF drawRect) { throw new NotImplementedException(); } void IGraphics.DrawPolygon(Pen pen, PointF[] diaPoints) { throw new NotImplementedException(); } void IGraphics.DrawRectangle(Pen borderPen, float left, float top, float width, float height) { throw new NotImplementedException(); } void IGraphics.DrawString(string text, Font font, Brush brush, float left, float top, StringFormat format) { throw new NotImplementedException(); } SizeF IGraphics.MeasureString(string text, Font font, SizeF size) { throw new NotImplementedException(); } SizeF IGraphics.MeasureString(string text, Font font, int v, StringFormat format) { throw new NotImplementedException(); } void IGraphics.MeasureString(string text, Font font, SizeF size, StringFormat format, out int charsFit, out int linesFit) { throw new NotImplementedException(); } Region[] IGraphics.MeasureCharacterRanges(string text, Font font, RectangleF textRect, StringFormat format) { throw new NotImplementedException(); } bool IGraphics.IsVisible(RectangleF objRect) { throw new NotImplementedException(); } void IGraphics.ResetClip() { throw new NotImplementedException(); } void IGraphics.ScaleTransform(float scaleX, float scaleY) { throw new NotImplementedException(); } void IGraphics.DrawImage(Image image, RectangleF rect1, RectangleF rect2, GraphicsUnit unit) { throw new NotImplementedException(); } void IGraphics.DrawImage(Image image, RectangleF rect) { throw new NotImplementedException(); } void IGraphics.DrawImage(Image image, float x, float y, float width, float height) { throw new NotImplementedException(); } void IGraphics.SetClip(RectangleF displayRect, CombineMode intersect) { throw new NotImplementedException(); } void IGraphics.FillPolygon(Brush brush, Point[] points) { throw new NotImplementedException(); } void IGraphics.DrawPolygon(Pen pen, Point[] points) { throw new NotImplementedException(); } void IGraphics.MultiplyTransform(System.Drawing.Drawing2D.Matrix matrix, MatrixOrder prepend) { throw new NotImplementedException(); } void IGraphics.DrawLine(Pen pen, PointF p1, PointF p2) { throw new NotImplementedException(); } void IGraphics.DrawImage(Image image, PointF[] points) { throw new NotImplementedException(); } void IGraphics.FillEllipse(Brush brush, RectangleF pointerCircle) { throw new NotImplementedException(); } void IGraphics.DrawEllipse(Pen pen, RectangleF pointerCircle) { throw new NotImplementedException(); } void IGraphics.DrawString(string s, Font font, Brush brush, PointF point, StringFormat format) { throw new NotImplementedException(); } SizeF IGraphics.MeasureString(string text, Font font, SizeF layoutArea, StringFormat stringFormat) { throw new NotImplementedException(); } void IGraphics.DrawImage(Image image, Rectangle destRect, int srcX, int srcY, int srcWidth, int srcHeight, GraphicsUnit srcUnit, ImageAttributes imageAttr) { throw new NotImplementedException(); } void IGraphics.DrawImage(Image image, Rectangle destRect, float srcX, float srcY, float srcWidth, float srcHeight, GraphicsUnit srcUnit, ImageAttributes imageAttrs) { throw new NotImplementedException(); } void IGraphics.DrawImageUnscaled(Image image, Rectangle rect) { throw new NotImplementedException(); } void IGraphics.DrawArc(Pen pen, float x, float y, float dx, float dy, float v1, float v2) { throw new NotImplementedException(); } void IGraphics.DrawCurve(Pen pen, PointF[] points, int offset, int numberOfSegments, float tension) { throw new NotImplementedException(); } void IGraphics.DrawPie(Pen pen, float x, float y, float width, float height, float startAngle, float sweepAngle) { throw new NotImplementedException(); } void IGraphics.DrawRectangle(Pen green, Rectangle rectangle) { throw new NotImplementedException(); } void IGraphics.FillPie(Brush brush, float x, float y, float dx, float dy, float v1, float v2) { throw new NotImplementedException(); } void IGraphics.FillRegion(Brush brush, Region region) { throw new NotImplementedException(); } void IGraphics.SetClip(GraphicsPath path, CombineMode combineMode) { throw new NotImplementedException(); } void IGraphics.FillAndDrawPath(Pen pen, Brush brush, GraphicsPath path) { FillPath(brush, path); ((IGraphics)this).DrawPath(pen, path); } void IGraphics.FillAndDrawEllipse(Pen pen, Brush brush, RectangleF rect) { throw new NotImplementedException(); } void IGraphics.FillAndDrawEllipse(Pen pen, Brush brush, float left, float top, float width, float height) { throw new NotImplementedException(); } void IGraphics.FillAndDrawPolygon(Pen pen, Brush brush, Point[] points) { throw new NotImplementedException(); } void IGraphics.FillAndDrawPolygon(Pen pen, Brush brush, PointF[] points) { throw new NotImplementedException(); } void IGraphics.FillAndDrawRectangle(Pen pen, Brush brush, float left, float top, float width, float height) { throw new NotImplementedException(); } } public class HpglFGraphicsRendererState : IGraphicsState { private System.Drawing.Drawing2D.Matrix matrix; public System.Drawing.Drawing2D.Matrix Matrix { get { return matrix; } } public HpglFGraphicsRendererState(System.Drawing.Drawing2D.Matrix matrix) { this.matrix = matrix; } } }