using FastReport.Barcode;
using FastReport.Table;
using FastReport.Utils;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Linq;
using System.Text;
namespace FastReport.Export.Hpgl
{
///
/// Variants of filling
///
public enum HpglFillMode
{
///
/// Solid filling of hatch and solid objects
///
Solid,
///
/// Draw only borders of hatch and solid objects
///
Border
}
public partial class HpglExport : ExportBase
{
#region Fields
private string path;
private string fileNameWOext;
private string extension;
private string pageFileName;
private int currentPage;
private HpglDocument hpglDocument;
private float pageHeight;
private float pageWidth;
private IGraphics hpglMeasureGraphics;
private HpglFillMode fillMode;
private float barcodesGap;
#endregion // Fields
///
/// Gets or sets lines/polygons gap for barcodes object
///
public float BarcodesGap
{
get { return barcodesGap; }
set { barcodesGap = value; }
}
///
/// Gets or sets the hpgl objects fill mode
///
public HpglFillMode FillMode
{
get { return fillMode; }
set { fillMode = value; }
}
///
/// Initializes a new instance of the class.
///
public HpglExport()
{
hpglDocument = new HpglDocument();
HasMultipleFiles = true;
hpglMeasureGraphics = new GdiGraphics(new Bitmap(1, 1));
}
#region Private Methods
///
/// Save hpgl file.
///
private void Save(string filename)
{
string hpglString = hpglDocument.ToString();
File.WriteAllText(filename, hpglString);
}
///
/// Save hpgl stream.
///
private void Save(Stream stream)
{
string hpglString = hpglDocument.ToString();
byte[] encodedDfx = Encoding.UTF8.GetBytes(hpglString);
stream.Write(encodedDfx, 0, encodedDfx.Length);
}
///
/// Add BandObject.
///
private void AddBandObject(BandBase band)
{
using (TextObject newObj = new TextObject())
{
newObj.Left = band.AbsLeft;
newObj.Top = band.AbsTop;
newObj.Width = band.Width;
newObj.Height = band.Height;
newObj.Fill = band.Fill;
newObj.Border = band.Border;
AddTextObject(newObj, true);
}
}
private void AddTable(TableBase table)
{
float y = 0;
for (int i = 0; i < table.RowCount; i++)
{
float x = 0;
for (int j = 0; j < table.ColumnCount; j++)
{
if (!table.IsInsideSpan(table[j, i]))
{
TableCell textcell = table[j, i];
textcell.Left = x;
textcell.Top = y;
Border oldBorder = textcell.Border.Clone();
textcell.Border.Lines = BorderLines.None;
if (textcell is TextObject)
AddTextObject(textcell as TextObject, /*false*/ true);
//else
// AddPictureObject(textcell as ReportComponentBase);
textcell.Border = oldBorder;
AddBorder(textcell.Border, textcell.AbsLeft, textcell.AbsTop, textcell.Width, textcell.Height);
}
x += (table.Columns[j]).Width;
}
y += (table.Rows[i]).Height;
}
}
///
/// Add TextObject.
///
private void AddTextObject(TextObject obj, bool drawBorder)
{
float AbsLeft = obj.AbsLeft;
float AbsTop = pageHeight * Units.Millimeters - obj.AbsTop;
float Width = obj.Width;
float Height = obj.Height;
bool transformNeeded = obj.Angle != 0 || obj.FontWidthRatio != 1;
if (transformNeeded)
return;
// draw background
//if (obj.FillColor != Color.Transparent)
// AddRectangleFill(AbsLeft, AbsTop, Width, Height, obj.FillColor);
// WIP: draw text here
//if (!string.IsNullOrWhiteSpace(obj.Text))
//{
// GraphicsPath myPath = new GraphicsPath();
// // Set up all the string parameters.
// string stringText = obj.Text;
// FontFamily family = obj.Font.FontFamily;
// int fontStyle = (int)obj.Font.Style;
// float emSize = obj.Font.Size;
// PointF origin = new PointF(0, 0);
// StringFormat format = StringFormat.GenericDefault;
// // Add the string to the path.
// myPath.AddString(stringText,
// family,
// fontStyle,
// emSize,
// origin,
// format);
// AddGraphicsPath(myPath, obj.TextColor, 1, LineStyle.Solid, AbsLeft + Width / 2, AbsTop - Height / 2, true, true);
// }
// if (obj.Clip)
if (obj.Underlines)
AddUnderlines(obj);
if (!String.IsNullOrEmpty(obj.Text))
{
using (Font f = new Font(obj.Font.FontFamily, obj.Font.Size, obj.Font.Style))
{
RectangleF textRect = new RectangleF(
obj.AbsLeft + obj.Padding.Left,
obj.AbsTop + obj.Padding.Top,
obj.Width - obj.Padding.Horizontal,
obj.Height - obj.Padding.Vertical);
// break the text to paragraphs, lines, words and runs
StringFormat format = obj.GetStringFormat(Report.GraphicCache /*cache*/, 0);
Brush textBrush = Report.GraphicCache.GetBrush(obj.TextColor);
AdvancedTextRenderer renderer = new AdvancedTextRenderer(obj.Text, hpglMeasureGraphics, f, textBrush, null,
textRect, format, obj.HorzAlign, obj.VertAlign, obj.LineHeight, obj.Angle, obj.FontWidthRatio,
obj.ForceJustify, obj.Wysiwyg, obj.HasHtmlTags, false, Zoom, Zoom, obj.InlineImageCache);
float w = f.Height * 0.1f; // to match .net char X offset
// invert offset in case of rtl
if (obj.RightToLeft)
w = -w;
// we don't need this offset if text is centered
if (obj.HorzAlign == HorzAlign.Center)
w = 0;
//XmlElement textContainer = DrawTextContainer(obj.AbsLeft, obj.AbsTop, f, obj.TextColor);
// transform, rotate and scale coordinates if needed
if (transformNeeded)
{
textRect.X = -textRect.Width / 2;
textRect.Y = -textRect.Height / 2;
float angle = (float)(obj.Angle * Math.PI / 180);
float x = (obj.AbsLeft + obj.Width / 2);
float y = (obj.AbsTop + obj.Height / 2);
//AppndAngle(textContainer, angle, x, y);
}
// render
foreach (AdvancedTextRenderer.Paragraph paragraph in renderer.Paragraphs)
foreach (AdvancedTextRenderer.Line line in paragraph.Lines)
{
float lineOffset = 0;
float lineHeight = line.CalcHeight();
if (lineHeight > obj.Height)
{
if (obj.VertAlign == VertAlign.Center)
lineOffset = -lineHeight / 2;//-
else if (obj.VertAlign == VertAlign.Bottom)
lineOffset = -lineHeight;//-
}
/* foreach (RectangleF rect in line.Underlines)
{
// DrawPDFUnderline(ObjectFontNumber, f, rect.Left, rect.Top, rect.Width, w,
// obj.TextColor, transformNeeded, sb);
}*/
/*foreach (RectangleF rect in line.Strikeouts)
{
DrawStrikeout(f, rect.Left, rect.Top, rect.Width, w, obj.TextColor, transformNeeded);
}*/
foreach (AdvancedTextRenderer.Word word in line.Words)
{
//if (renderer.HtmlTags)
// foreach (AdvancedTextRenderer.Run run in word.Runs)
// using (Font fnt = run.GetFont())
// {
// AppndTspan(textContainer, run.Left, run.Top + lineOffset + lineHeight * 72 / 96/*magic*/,
// w, run.Text, f);
// }
//else
//AppndTspan(textContainer, word.Left, word.Top + lineOffset + lineHeight * 72 / 96/*magic*/,
// w, word.Text, f);
// --
if (!string.IsNullOrWhiteSpace(word.Text))
{
GraphicsPath myPath = new GraphicsPath();
// Set up all the string parameters.
string stringText = word.Text;
FontFamily family = obj.Font.FontFamily;
int fontStyle = (int)obj.Font.Style;
float emSize = obj.Font.Size;
PointF origin = new PointF(0, 0 /*+ lineOffset + lineHeight*//*magic*/);
// StringFormat format = StringFormat.GenericDefault;
// Add the string to the path.
myPath.AddString(stringText,
family,
fontStyle,
emSize,
origin,
StringFormat.GenericDefault);
float x = word.Left + w + (transformNeeded ? obj.AbsLeft : 0);
float y = pageHeight * Units.Millimeters - word.Top - lineOffset - (transformNeeded ? obj.AbsTop : 0);
float centerX = (obj.Width / 2) / Units.Millimeters;
float centerY = (obj.Height / 2) / Units.Millimeters;
PointF center = new PointF(centerX, centerY);
float angle = (float)(obj.Angle * Math.PI / 180);
AddGraphicsPath(myPath, obj.TextColor, 1 / 100.0f, LineStyle.Solid, x,
y, true, true, angle, center);
}
// --
}
}
}
}
if (drawBorder)
AddBorder(obj.Border, obj.AbsLeft, obj.AbsTop, obj.Width, obj.Height);
}
#endregion // Private Methods
#region Protected Methods
///
protected override void Start()
{
currentPage = 0;
GeneratedStreams = new List();
if (FileName != "" && FileName != null)
{
path = Path.GetDirectoryName(FileName);
fileNameWOext = Path.GetFileNameWithoutExtension(FileName);
extension = Path.GetExtension(FileName);
}
else
fileNameWOext = "hpglReport";
}
///
/// Begin exporting of page
///
///
protected override void ExportPageBegin(ReportPage page)
{
base.ExportPageBegin(page);
pageHeight = ExportUtils.GetPageHeight(page);
pageWidth = ExportUtils.GetPageWidth(page);
hpglDocument = new HpglDocument();
hpglDocument.Start(new SizeF(4000, 4000));
// page borders
if (page.Border.Lines != BorderLines.None)
{
using (TextObject pageBorder = new TextObject())
{
pageBorder.Border = page.Border;
pageBorder.Left = 0;
pageBorder.Top = 0;
pageBorder.Width = (pageWidth - page.LeftMargin - page.RightMargin);
pageBorder.Height = (pageHeight - page.TopMargin - page.BottomMargin);
// AddTextObject(pageBorder, true);
}
}
if (path != null && path != "")
pageFileName = Path.Combine(path, fileNameWOext + currentPage.ToString() + extension);
else
pageFileName = null;
}
///
/// Export of Band
///
///
protected override void ExportBand(BandBase band)
{
base.ExportBand(band);
ExportObj(band);
foreach (Base c in band.ForEachAllConvectedObjects(this))
{
ExportObj(c);
}
}
///
/// End exporting
///
///
protected override void ExportPageEnd(ReportPage page)
{
base.ExportPageEnd(page);
//hpglDocument.Finish();
if (HasMultipleFiles)
{
//export to MultipleFiles
if (Directory.Exists(path) && !string.IsNullOrEmpty(FileName))
{
// desktop mode
if (currentPage == 0)
{
// save first page in parent Stream
Save(Stream);
Stream.Position = 0;
GeneratedStreams.Add(Stream);
GeneratedFiles.Add(FileName);
}
else
{
// save all page after first in files
Save(pageFileName);
GeneratedFiles.Add(pageFileName);
}
}
else if (string.IsNullOrEmpty(path))
{
if (currentPage == 0)
{
// save first page in parent Stream
Save(Stream);
Stream.Position = 0;
GeneratedStreams.Add(Stream);
GeneratedFiles.Add(FileName);
}
else
{
// server mode, save in internal stream collection
MemoryStream pageStream = new MemoryStream();
Save(pageStream);
pageStream.Position = 0;
GeneratedStreams.Add(pageStream);
GeneratedFiles.Add(pageFileName);
}
}
}
// increment page number
currentPage++;
}
///
protected override void Finish()
{
if (!HasMultipleFiles)
{
Save(Stream);
Stream.Position = 0;
GeneratedFiles.Add(FileName);
}
GeneratedFiles.Clear();
GeneratedStreams.Clear();
}
///
protected override string GetFileFilter()
{
return new MyRes("FileFilters").Get("HpglFile");
}
#endregion
///
public override void Serialize(FRWriter writer)
{
base.Serialize(writer);
writer.WriteBool("HasMultipleFiles", HasMultipleFiles);
writer.WriteValue("FillMode", FillMode);
}
///
/// Export all report objects
///
///
public virtual void ExportObj(Base c)
{
if (c is ReportComponentBase && (c as ReportComponentBase).Exportable)
{
ReportComponentBase obj = c as ReportComponentBase;
if (obj is CellularTextObject)
obj = (obj as CellularTextObject).GetTable();
if (obj is TableCell) return;
else if (obj is TableBase)
{
TableBase table = obj as TableBase;
if (table.ColumnCount > 0 && table.RowCount > 0)
{
using (TextObject tableback = new TextObject())
{
tableback.Border = table.Border;
tableback.Fill = table.Fill;
tableback.FillColor = table.FillColor;
tableback.Left = table.AbsLeft;
tableback.Top = table.AbsTop;
float tableWidth = 0;
float tableHeight = 0;
for (int i = 0; i < table.ColumnCount; i++)
tableWidth += table[i, 0].Width;
for (int i = 0; i < table.RowCount; i++)
tableHeight += table.Rows[i].Height;
tableback.Width = (tableWidth < table.Width) ? tableWidth : table.Width;
tableback.Height = tableHeight;
//AddTextObject(tableback, false);
// draw table border
// AddBorder(tableback.Border, tableback.AbsLeft, tableback.AbsTop, tableback.Width, tableback.Height);
}
// draw cells
AddTable(table);
}
}
else if (obj is TextObject)
AddTextObject(obj as TextObject, true);
else if (obj is BandBase)
AddBandObject(obj as BandBase);
else if (obj is LineObject)
AddLine(obj as LineObject);
else if (obj is PolygonObject)
AddPolygon(obj as PolygonObject);
else if (obj is PolyLineObject)
AddPolyLine(obj as PolyLineObject);
else if (obj is ShapeObject)
AddShape(obj as ShapeObject);
//#if DOTNET_4
// else if (obj is SVGObject)
// AddBarcodeFromSvg(obj as BarcodeObject);
//#endif
else if (obj is BarcodeObject)
AddBarcode(obj as BarcodeObject);
//#if DOTNET_4
// else if (obj is SVGObject)
// AddSVGObject(c as SVGObject);
//#endif
// else
// AddPictureObject(obj);
}
}
private void AddBarcode(BarcodeObject barcodeObject)
{
using (var renderer = new HpglGraphicsRenderer(hpglDocument, fillMode, BarcodesGap))
{
bool error = false;
string errorText = "";
if (string.IsNullOrEmpty(barcodeObject.Text))
{
error = true;
errorText = barcodeObject.NoDataText;
}
else
try
{
// That line makes barcode not an invalid
barcodeObject.UpdateAutoSize();
}
catch (Exception ex)
{
error = true;
errorText = ex.Message;
}
if (!error)
barcodeObject.Barcode.DrawBarcode(renderer, new RectangleF(barcodeObject.AbsLeft / Units.Millimeters,
pageHeight - barcodeObject.AbsTop / Units.Millimeters, barcodeObject.Width / Units.Millimeters, barcodeObject.Height / Units.Millimeters));
else
{
renderer.DrawString(errorText, DrawUtils.DefaultReportFont, Brushes.Red,
new RectangleF(0, 0, barcodeObject.Width, barcodeObject.Height));
}
//barcodeObject.Barcode.DrawBarcode(renderer, new RectangleF(barcodeObject.AbsLeft,
// barcodeObject.AbsTop, barcodeObject.Width, barcodeObject.Height));
}
}
private string FloatToString(double flt)
{
return ExportUtils.FloatToString(flt);
}
}
}