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;
}
}
}
}
}