using FastReport.Export.Hpgl.Commands; using FastReport.Export.Hpgl.Utils; using FastReport.Utils; using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.Text; namespace FastReport.Export.Hpgl { public partial class HpglExport { private void AddRectangleFill(float x, float y, float width, float height, Brush brush) { if (fillMode == HpglFillMode.Solid) hpglDocument.FillRectangle(x / Units.Millimeters, (y - height) / Units.Millimeters, width / Units.Millimeters, height / Units.Millimeters, brush); else { PointF startPoint = new PointF(0, 0); PointF[] points = new PointF[6]; byte[] pTypes = new byte[4]; points[0] = startPoint; points[1] = new PointF(startPoint.X + width, startPoint.Y); points[2] = new PointF(startPoint.X + width, startPoint.Y - height); points[3] = new PointF(startPoint.X, startPoint.Y - height); AddPath(points, pTypes, (brush as SolidBrush).Color, 1, LineStyle.Solid, x, y, true, brush); } } private void AddRectangleFill(float x, float y, float width, float height, Color color) { AddRectangleFill(x, y, width, height, new SolidBrush(color)); } private void AddBorder(Border border, float left, float top, float width, float height) { //float mWidth = width / Units.Millimeters; //float mHeight = height / Units.Millimeters; //float mTop = top / Units.Millimeters; //float mLeft = left / Units.Millimeters; //float borderWidth = border.Width / Units.Millimeters; //float shadowrWidth = border.ShadowWidth / Units.Millimeters; float oTop = pageHeight * Units.Millimeters - top; if (border.Shadow) { PointF startPoint = new PointF(width + border.ShadowWidth, -height - border.ShadowWidth); PointF[] points = new PointF[6]; points[0] = startPoint; points[1] = new PointF(startPoint.X - width, startPoint.Y); points[2] = new PointF(startPoint.X - width, startPoint.Y + border.ShadowWidth); points[3] = new PointF(startPoint.X - border.ShadowWidth, startPoint.Y + border.ShadowWidth); points[4] = new PointF(startPoint.X - border.ShadowWidth, startPoint.Y + height); points[5] = new PointF(startPoint.X, startPoint.Y + height); byte[] pTypes = new byte[6]; AddPath(points, pTypes, border.ShadowColor, 1, LineStyle.Solid, left, oTop, true, null); // shadows fill AddRectangleFill(left + width, oTop - border.ShadowWidth, border.ShadowWidth, height, border.ShadowColor); AddRectangleFill(left + border.ShadowWidth, oTop - height, width, border.ShadowWidth, border.ShadowColor); } if (border.Lines != BorderLines.None) { if (border.Lines == BorderLines.All && border.LeftLine.Equals(border.RightLine) && border.TopLine.Equals(border.BottomLine) && border.LeftLine.Equals(border.TopLine)) { if (border.Width > 0 && border.Color != Color.Transparent) { PointF[] points = new PointF[4]; points[0] = new PointF(0, 0); points[1] = new PointF(width, 0); points[2] = new PointF(width, height); points[3] = new PointF(0, height); byte[] pTypes = new byte[6]; AddPath(points, pTypes, border.Color, 1, border.Style, left, oTop - height, true, null); if (border.LeftLine.Style == LineStyle.Double) { points = new PointF[4]; points[0] = new PointF(0, 0); points[1] = new PointF(width - 2 * 2, 0); points[2] = new PointF(width - 2 * 2, height - 2 * 2); points[3] = new PointF(0, height - 2 * 2); pTypes = new byte[6]; AddPath(points, pTypes, border.Color, 1, border.Style, left + 2, oTop - height + 2, true, null); } } } else { float Left = left; float Top = top; float Right = left + width; float Bottom = top + height; Top -= 0.1f; Bottom += 0.1f; if ((border.Lines & BorderLines.Left) > 0) { LineObject line = new LineObject(); line.Left = Left; line.Top = Top; line.Width = 0; line.Height = height; line.Border.Color = border.LeftLine.Color; line.Border.Width = border.LeftLine.Width; line.Border.Style = border.LeftLine.Style; AddLine(line); if (border.LeftLine.Style == LineStyle.Double) { LineObject lineD = new LineObject(); lineD.Left = Left + 2; lineD.Top = Top; lineD.Width = 0; lineD.Height = height; lineD.Border.Color = border.LeftLine.Color; lineD.Border.Width = border.LeftLine.Width; lineD.Border.Style = border.LeftLine.Style; AddLine(lineD); } } if ((border.Lines & BorderLines.Right) > 0) { LineObject line = new LineObject(); line.Left = Right; line.Top = Top; line.Width = 0; line.Height = height; line.Border.Color = border.RightLine.Color; line.Border.Width = border.RightLine.Width; line.Border.Style = border.RightLine.Style; AddLine(line); if (border.RightLine.Style == LineStyle.Double) { LineObject lineD = new LineObject(); lineD.Left = Right - 2; lineD.Top = Top; lineD.Width = 0; lineD.Height = height; lineD.Border.Color = border.RightLine.Color; lineD.Border.Width = border.RightLine.Width; lineD.Border.Style = border.RightLine.Style; AddLine(lineD); } } if ((border.Lines & BorderLines.Top) > 0) { LineObject line = new LineObject(); line.Left = Left; line.Top = Top; line.Width = width; line.Height = 0; line.Border.Color = border.TopLine.Color; line.Border.Width = border.TopLine.Width; line.Border.Style = border.TopLine.Style; AddLine(line); if (border.RightLine.Style == LineStyle.Double) { LineObject lineD = new LineObject(); lineD.Left = Left - 2; lineD.Top = Top; lineD.Width = width; lineD.Height = 0; lineD.Border.Color = border.TopLine.Color; lineD.Border.Width = border.TopLine.Width; lineD.Border.Style = border.TopLine.Style; AddLine(lineD); } } if ((border.Lines & BorderLines.Bottom) > 0) { LineObject line = new LineObject(); line.Left = Left; line.Top = Top + height; line.Width = width; line.Height = 0; line.Border.Color = border.BottomLine.Color; line.Border.Width = border.BottomLine.Width; line.Border.Style = border.BottomLine.Style; AddLine(line); if (border.RightLine.Style == LineStyle.Double) { LineObject lineD = new LineObject(); lineD.Left = Left; lineD.Top = Top + height + 2; lineD.Width = width; lineD.Height = 0; lineD.Border.Color = border.BottomLine.Color; lineD.Border.Width = border.BottomLine.Width; lineD.Border.Style = border.BottomLine.Style; AddLine(lineD); } } } } } private void AddUnderlines(TextObject obj) { float lineHeight = obj.LineHeight == 0 ? obj.Font.GetHeight() : obj.LineHeight; float curY = obj.AbsTop + lineHeight; float bottom = obj.AbsBottom; float left = obj.AbsLeft; float right = obj.AbsRight; float width = obj.Border.Width; while (curY < bottom) { LineObject underline = new LineObject(); underline.Left = left; underline.Top = curY; underline.Width = obj.Width; underline.Height = 0; underline.Border = obj.Border; AddLine(underline); curY += lineHeight; } } private void AddArrow(CapSettings Arrow, float lineWidth, float x1, float y1, float x2, float y2, out float x3, out float y3, out float x4, out float y4) { float k1, a, b, c, d; float xp, yp; float wd = Arrow.Width * lineWidth; float ld = Arrow.Height * lineWidth; if (Math.Abs(x2 - x1) > 0) { k1 = (y2 - y1) / (x2 - x1); a = (float)(Math.Pow(k1, 2) + 1); b = 2 * (k1 * ((x2 * y1 - x1 * y2) / (x2 - x1) - y2) - x2); c = (float)(Math.Pow(x2, 2) + Math.Pow(y2, 2) - Math.Pow(ld, 2) + Math.Pow((x2 * y1 - x1 * y2) / (x2 - x1), 2) - 2 * y2 * (x2 * y1 - x1 * y2) / (x2 - x1)); d = (float)(Math.Pow(b, 2) - 4 * a * c); xp = (float)((-b + Math.Sqrt(d)) / (2 * a)); if ((xp > x1) && (xp > x2) || (xp < x1) && (xp < x2)) xp = (float)((-b - Math.Sqrt(d)) / (2 * a)); yp = xp * k1 + (x2 * y1 - x1 * y2) / (x2 - x1); if (y2 != y1) { x3 = (float)(xp + wd * Math.Sin(Math.Atan(k1))); y3 = (float)(yp - wd * Math.Cos(Math.Atan(k1))); x4 = (float)(xp - wd * Math.Sin(Math.Atan(k1))); y4 = (float)(yp + wd * Math.Cos(Math.Atan(k1))); } else { x3 = xp; y3 = yp - wd; x4 = xp; y4 = yp + wd; } } else { xp = x2; yp = y2 - ld; if ((yp > y1) && (yp > y2) || (yp < y1) && (yp < y2)) yp = y2 + ld; x3 = xp - wd; y3 = yp; x4 = xp + wd; y4 = yp; } } /// /// Add Line. /// private void AddLine(LineObject line) { float x1 = line.AbsLeft / Units.Millimeters; float y1 = pageHeight - line.AbsTop / Units.Millimeters; float x2 = x1 + line.Width / Units.Millimeters; float y2 = y1 - line.Height / Units.Millimeters; float Border = line.Border.Width / Units.Millimeters; if (line.StartCap.Style == CapStyle.Arrow) { float x3, y3, x4, y4; AddArrow(line.StartCap, Border, x2, y2, x1, y1, out x3, out y3, out x4, out y4); hpglDocument.DrawLine(x1, y1, x3, y3, line.Border.Color, Border, line.Border.Style); hpglDocument.DrawLine(x1, y1, x4, y4, line.Border.Color, Border, line.Border.Style); } if (line.EndCap.Style == CapStyle.Arrow) { float x3, y3, x4, y4; AddArrow(line.EndCap, Border, x1, y1, x2, y2, out x3, out y3, out x4, out y4); hpglDocument.DrawLine(x2, y2, x3, y3, line.Border.Color, Border, line.Border.Style); hpglDocument.DrawLine(x2, y2, x4, y4, line.Border.Color, Border, line.Border.Style); } hpglDocument.DrawLine(x1, y1, x2, y2, line.Border.Color, Border, line.Border.Style); } private void AddPolyLine(PolyLineObject p) { bool isClosed = (p is PolygonObject) ? true : false; Brush fillBrush = isClosed ? p.Fill.CreateBrush(new RectangleF(0, 0, p.Width, p.Height)) : null; AddPath(p.PointsArray.InvertY(), p.PointTypesArray, p.Border.Color, p.Border.Width, p.Border.Style, p.AbsLeft + p.CenterX, pageHeight * Units.Millimeters - p.AbsTop - p.CenterY, isClosed, fillBrush); } private void AddPath(PointF[] points, byte[] pointTypes, Color borderColor, float borderWidth, LineStyle borderLineStyle, float left, float top, bool isClosed, Brush fillBrush, PolygonType mode) { float x = left / Units.Millimeters; float y = top / Units.Millimeters; ; for (int i = 0; i < points.Length; i++) { points[i].X /= Units.Millimeters; points[i].Y /= Units.Millimeters; } if (FillMode == HpglFillMode.Border) fillBrush = null; hpglDocument.DrawPolyLine(x, y, points, pointTypes, borderColor, borderWidth / Units.Millimeters, borderLineStyle, isClosed, fillBrush, mode); } private void AddPath(PointF[] points, byte[] pointTypes, Color borderColor, float borderWidth, LineStyle borderLineStyle, float left, float top, bool isClosed, Brush fillBrush) { AddPath(points, pointTypes, borderColor, borderWidth, borderLineStyle, left, top, isClosed, fillBrush, PolygonType.Cleared); } 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(); PolygonType mode = PolygonType.Cleared; for (int i = 0; i < pathTypes.Length; i++) { byte pType = pathTypes[i]; PointF point = pathPoints[i]; mode = i > 0 && pathTypes[i - 1] == 163 ? PolygonType.Cleared : PolygonType.Closed; if (pType == 0 && points.Count > 0) { AddPath(points.ToArray(), pTypes.ToArray(), borderColor, borderWith, borderLineStyle, left, top, isClosed, null, mode); 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, null, mode); } } } private void AddPolygon(PolygonObject polygonObject) { AddPolyLine(polygonObject); } private void AddShape(ShapeObject shapeObject) { float shapeWidth = shapeObject.Width;// / Units.Millimeters; float shapeHeight = shapeObject.Height;// / Units.Millimeters; float shapeTop = shapeObject.AbsTop;// / Units.Millimeters; float shapeLeft = shapeObject.AbsLeft;// / Units.Millimeters; float shapeBorderWidth = shapeObject.Border.Width;// / Units.Millimeters; Brush fillBrush = shapeObject.Fill.CreateBrush(new RectangleF(0, 0, shapeObject.Width, shapeObject.Height)); switch (shapeObject.Shape) { case ShapeKind.Rectangle: { PointF[] points = new PointF[4]; points[0] = new PointF(0, 0); points[1] = new PointF(shapeWidth, 0); points[2] = new PointF(shapeWidth, shapeHeight); points[3] = new PointF(0, shapeHeight); byte[] pTypes = new byte[4]; AddPath(points, new byte[4], shapeObject.Border.Color, shapeBorderWidth, shapeObject.Border.Style, shapeLeft, pageHeight * Units.Millimeters - shapeTop - shapeHeight, true, fillBrush); } break; case ShapeKind.Triangle: { PointF[] points = new PointF[3]; points[0] = new PointF(shapeWidth / 2, 0); points[1] = new PointF(shapeWidth, shapeHeight); points[2] = new PointF(0, shapeHeight); byte[] pTypes = new byte[3]; AddPath(points, new byte[3], shapeObject.Border.Color, shapeBorderWidth, shapeObject.Border.Style, shapeLeft, pageHeight * Units.Millimeters - shapeTop - shapeHeight, true, fillBrush); } break; case ShapeKind.Diamond: { PointF[] points = new PointF[4]; points[0] = new PointF(shapeWidth / 2, 0); points[1] = new PointF(shapeWidth, shapeHeight / 2); points[2] = new PointF(shapeWidth / 2, shapeHeight); points[3] = new PointF(0, shapeHeight / 2); byte[] pTypes = new byte[4]; AddPath(points, new byte[4], shapeObject.Border.Color, shapeBorderWidth, shapeObject.Border.Style, shapeLeft, pageHeight * Units.Millimeters - shapeTop - shapeHeight, true, fillBrush); } break; case ShapeKind.Ellipse: { hpglDocument.DrawEllipse(shapeLeft / Units.Millimeters, pageHeight - shapeTop / Units.Millimeters, shapeWidth / Units.Millimeters, shapeHeight / Units.Millimeters, shapeObject.Border.Color, shapeBorderWidth / Units.Millimeters, shapeObject.Border.Style); break; } } } } }