123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233 |
- using FastReport.Barcode;
- using FastReport.Table;
- using FastReport.Utils;
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Drawing.Imaging;
- using System.IO;
- using System.Runtime.InteropServices;
- using System.Text;
- namespace FastReport.Export.Zpl
- {
- /// <summary>
- /// Represents the Zpl export filter.
- /// </summary>
- public partial class ZplExport : ExportBase
- {
- #region Public properties
- /// <summary>
- /// Enum of ZPL format versions.
- /// </summary>
- public enum ZplVersions
- {
- /// <summary>
- /// Standart ZPL
- /// </summary>
- ZPL1,
- /// <summary>
- /// ZPL II
- /// </summary>
- ZPL2
- }
- /// <summary>
- /// Enum of densty types of Zebra printers.
- /// </summary>
- public enum ZplDensity
- {
- /// <summary>
- /// 6 dpmm(152 dpi)
- /// </summary>
- d6_dpmm_152_dpi,
- /// <summary>
- /// 8 dpmm(203 dpi)
- /// </summary>
- d8_dpmm_203_dpi,
- /// <summary>
- /// 12 dpmm(300 dpi)
- /// </summary>
- d12_dpmm_300_dpi,
- /// <summary>
- /// 24 dpmm(600 dpi)
- /// </summary>
- d24_dpmm_600_dpi
- }
- /// <summary>
- /// Sets the density of printer.
- /// </summary>
- public ZplDensity Density
- {
- get { return density; }
- set { density = value; }
- }
- /// <summary>
- /// Gets or sets the version of ZPL.
- /// </summary>
- public ZplVersions Version
- {
- get { return version; }
- set { version = value; }
- }
- /// <summary>
- /// Sets the init string for sending before printing the document.
- /// </summary>
- public string PrinterInit
- {
- get { return printerInit; }
- set { printerInit = value; }
- }
- /// <summary>
- /// Sets the code page of document. Default is UTF-8 (^CI28).
- /// </summary>
- public string CodePage
- {
- get { return codePage; }
- set { codePage = value; }
- }
- /// <summary>
- /// Sets the string for sending after printing the document.
- /// </summary>
- public string PrinterFinish
- {
- get { return printerFinish; }
- set { printerFinish = value; }
- }
- /// <summary>
- /// Sets the string for sending before printing each page.
- /// </summary>
- public string PageInit
- {
- get { return pageInit; }
- set { pageInit = value; }
- }
- /// <summary>
- /// Sets the scale font size.
- /// </summary>
- public float FontScale
- {
- get { return fontScale / defaultFontScale; }
- set { fontScale = value * defaultFontScale; }
- }
- /// <summary>
- /// Sets the scale barcode size.
- /// </summary>
- public float BarcodeScale
- {
- get { return barcodeScale; }
- set { barcodeScale = value; }
- }
- /// <summary>
- /// Sets the Printer Font, default value is "A".
- /// </summary>
- public string PrinterFont
- {
- get { return font; }
- set { font = value; }
- }
- /// <summary>
- /// Enable or disable export as bitmap.
- /// </summary>
- public bool PrintAsBitmap
- {
- get { return printAsBitmap; }
- set { printAsBitmap = value; }
- }
- #endregion Public properties
- #region Private constants
- private const float millimeters = 3.78f;
- private const float defaultFontScale = 1.4f;
- private const float defaultBarcodeScale = 2f;
- #endregion Private constants
- #region Private Fields
- #if READONLY_STRUCTS
- private readonly struct ZplScale
- #else
- private struct ZplScale
- #endif
- {
- public readonly float PageScale;
- public readonly int TwoDCodeScale;
- public ZplScale(float pageScale, int qrCodeScale)
- {
- PageScale = pageScale;
- TwoDCodeScale = qrCodeScale;
- }
- }
- // scales of X and Y position and sized depend by ZplDensity
- // second value is multiplier for barcode zoom
- private ZplScale[] zplScaleArray =
- {
- //6 dpmm(152 dpi)
- new ZplScale(1.5833f, 7),
- //8 dpmm(203 dpi)
- new ZplScale(2.11458f, 8),
- //12 dpmm(300 dpi)
- new ZplScale(3.16667f, 10),
- //24 dpmm(600 dpi)
- new ZplScale(6.34375f, 10)
- };
- // Enable for Print as Bitmap;
- private bool printAsBitmap = true;
- private ZplDensity density = ZplDensity.d8_dpmm_203_dpi;
- private ZplVersions version = ZplVersions.ZPL1;
- // Printer Init String. Sends before document.
- private string printerInit;
- // Printer Finish String. Sends after document.
- private string printerFinish;
- // Printer page init string. Sends before page.
- private string pageInit;
- // Font scale factor.
- private float fontScale = defaultFontScale;
- // Barcode scale factor (BY..).
- private static float barcodeScale = defaultBarcodeScale;
- // Position in ZipScale array by default (8 dpmm(203 dpi)
- private int scaleIndex = 1;
- private float leftMargin = 0;
- private float topMargin = 0;
- // font
- private string font = "A";
- private string codePage = "^CI28";
- // Bitmap for rendering objects
- private Bitmap pageBitmap = null;
- // Table with counters for compression the bitmaps
- private Dictionary<int, char> countTable;
- private int[] counts;
- #endregion Private Fields
- #region Private Methods
- /// <summary>
- /// Writes the string value in stream.
- /// </summary>
- /// <param name="stream"></param>
- /// <param name="value"></param>
- private void Write(Stream stream, string value)
- {
- if (!String.IsNullOrEmpty(value))
- {
- byte[] buf = Encoding.UTF8.GetBytes(value);
- stream.Write(buf, 0, buf.Length);
- }
- }
- /// <summary>
- /// Writes the string value in stream with CRLF.
- /// </summary>
- /// <param name="stream"></param>
- /// <param name="value"></param>
- private void WriteLn(Stream stream, string value)
- {
- if (!String.IsNullOrEmpty(value))
- {
- byte[] buf = Encoding.UTF8.GetBytes(value);
- stream.Write(buf, 0, buf.Length);
- stream.WriteByte(13);
- stream.WriteByte(10);
- }
- }
- /// <summary>
- /// Gets the left position in zpl units.
- /// </summary>
- /// <param name="left"></param>
- /// <returns></returns>
- private int GetLeft(float left)
- {
- return (int)Math.Round(left * zplScaleArray[scaleIndex].PageScale + leftMargin);
- }
- /// <summary>
- /// Gets the top position in zpl units.
- /// </summary>
- /// <param name="top"></param>
- /// <returns></returns>
- private int GetTop(float top)
- {
- return (int)Math.Round(top * zplScaleArray[scaleIndex].PageScale + topMargin);
- }
- private int GetWidth(float width, float height, int angle)
- {
- if (angle == 90 || angle == 270)
- return (int)Math.Round(height * zplScaleArray[scaleIndex].PageScale);
- else
- return (int)Math.Round(width * zplScaleArray[scaleIndex].PageScale);
- }
- private int GetHeight(float width, float height, int angle)
- {
- if (angle == 90 || angle == 270)
- return (int)Math.Round(width * zplScaleArray[scaleIndex].PageScale);
- else
- return (int)Math.Round(height * zplScaleArray[scaleIndex].PageScale);
- }
- private string GetBarcodeZoom(float zoom, BarcodeBase b)
- {
- return (Math.Round(zoom * barcodeScale) * (b is BarcodePDF417 ? 2 : 1)).ToString();
- }
- private string GetZPLText(string source)
- {
- source = source.Replace("\\", "\\\\").Replace("\r\n", "\\&").Replace("$", "\\$");
- return source;
- }
- private string GetOrientation(int angle)
- {
- if (angle == 90)
- return "^FWR";
- else if (angle == 180)
- return "^FWI";
- else if (angle == 270)
- return "^FWB";
- else
- return "^FWN";
- }
- /// <summary>
- /// Exports the TableObject.
- /// </summary>
- /// <param name="table"></param>
- private void ExportTableObject(TableBase table)
- {
- if (table.ColumnCount > 0 && table.RowCount > 0)
- {
- StringBuilder tableBorder = new StringBuilder(64);
- 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;
- ExportTextObject(tableback);
- }
- AddTable(table);
- }
- }
- 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;
- if (textcell is TextObject)
- ExportTextObject(textcell as TextObject);
- else
- ExportPictureObject(textcell as ReportComponentBase);
- }
- x += (table.Columns[j]).Width;
- }
- y += (table.Rows[i]).Height;
- }
- }
- // Copied from TIFF export with some changes
- private Bitmap ConvertToBitonal(Bitmap original)
- {
- Bitmap source = null;
- if (original.PixelFormat != PixelFormat.Format32bppArgb)
- {
- source = new Bitmap(original.Width, original.Height, PixelFormat.Format32bppArgb);
- source.SetResolution(original.HorizontalResolution, original.VerticalResolution);
- using (Graphics g = Graphics.FromImage(source))
- g.DrawImageUnscaled(original, 0, 0);
- }
- else
- source = original;
- BitmapData sourceData = source.LockBits(new Rectangle(0, 0, source.Width, source.Height),
- ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
- int imageSize = sourceData.Stride * sourceData.Height;
- byte[] sourceBuffer = new byte[imageSize];
- Marshal.Copy(sourceData.Scan0, sourceBuffer, 0, imageSize);
- source.UnlockBits(sourceData);
- Bitmap destination = new Bitmap(source.Width, source.Height, PixelFormat.Format1bppIndexed);
- BitmapData destinationData = destination.LockBits(new Rectangle(0, 0, destination.Width, destination.Height),
- ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed);
- imageSize = destinationData.Stride * destinationData.Height;
- byte[] destinationBuffer = new byte[imageSize];
- int sourceIndex = 0;
- int destinationIndex = 0;
- int pixelTotal = 0;
- byte destinationValue = 0;
- int pixelValue = 128;
- int height = source.Height;
- int width = source.Width;
- int threshold = 500;
- for (int y = 0; y < height; y++)
- {
- sourceIndex = y * sourceData.Stride;
- destinationIndex = y * destinationData.Stride;
- destinationValue = 0;
- pixelValue = 128;
- for (int x = 0; x < width; x++)
- {
- pixelTotal = sourceBuffer[sourceIndex + 1] +
- sourceBuffer[sourceIndex + 2] +
- sourceBuffer[sourceIndex + 3];
- if (pixelTotal > threshold)
- destinationValue += (byte)pixelValue;
- if (pixelValue == 1)
- {
- destinationBuffer[destinationIndex++] = destinationValue;
- destinationValue = 0;
- pixelValue = 128;
- }
- else
- pixelValue >>= 1;
- sourceIndex += 4;
- }
- if (pixelValue != 128)
- destinationBuffer[destinationIndex] = destinationValue;
- }
- Marshal.Copy(destinationBuffer, 0, destinationData.Scan0, imageSize);
- destination.UnlockBits(destinationData);
- if (source != original)
- source.Dispose();
- return destination;
- }
- private void ExportPictureObject(ReportComponentBase pic)
- {
- WriteLn(Stream, SetPosition(GetLeft(pic.AbsLeft), GetTop(pic.AbsTop)));
- Border existingBorder = pic.Border.Clone();
- pic.Border.Lines = BorderLines.None;
- WriteLn(Stream, DrawPictureObject(pic));
- pic.Border = existingBorder;
- DrawBorders(pic.Border, pic.AbsLeft, pic.AbsTop, pic.Width, pic.Height);
- }
- private string DrawPictureObject(ReportComponentBase pic)
- {
- string result = String.Empty;
- if (pic.Width > 0 && pic.Height > 0)
- {
- float zoom = zplScaleArray[scaleIndex].PageScale;
- int picWidth = (int)Math.Ceiling(pic.Width * zoom);
- int picHeight = (int)Math.Ceiling(pic.Height * zoom);
- using (Bitmap image = new Bitmap(picWidth, picHeight, PixelFormat.Format32bppArgb))
- {
- DrawObjectOnBitmap(image, pic, false);
- result = DrawBWPicture(image);
- }
- }
- return result;
- }
- private void DrawObjectOnBitmap(Bitmap image, ReportComponentBase pic, bool usePosition)
- {
- using (Graphics g = Graphics.FromImage(image))
- {
- using (GraphicCache cache = new GraphicCache())
- {
- if (!usePosition)
- g.Clear(Color.White);
- float Left = pic.Width >= 0 ? pic.AbsLeft : pic.AbsLeft + pic.Width;
- float Top = pic.Height >= 0 ? pic.AbsTop : pic.AbsTop + pic.Height;
- float zoom = zplScaleArray[scaleIndex].PageScale;
- if (!usePosition)
- g.TranslateTransform(-Left * zoom, -Top * zoom);
- pic.Draw(new FRPaintEventArgs(g, zoom, zoom, cache));
- }
- }
- }
- private string DrawBWPicture(Bitmap image)
- {
- string result = String.Empty;
- // Convert to BW
- using (Bitmap bwImage = ConvertToBitonal(image))
- // Save in ZPL
- {
- result = CompressBWImage(bwImage);
- }
- return result;
- }
- private string CompressBWImage(Bitmap image)
- {
- BitmapData imgData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height),
- ImageLockMode.ReadOnly, PixelFormat.Format1bppIndexed);
- int imageBitsSize = imgData.Stride * imgData.Height;
- byte[] picBytes = new byte[imageBitsSize];
- Marshal.Copy(imgData.Scan0, picBytes, 0, imageBitsSize);
- image.UnlockBits(imgData);
- int widthInBytes = (int)Math.Ceiling(image.Width / 8f);
- int imageSize = widthInBytes * image.Height;
- int freeBits = 8 - image.Width % 8;
- byte lastByteMask = (byte)((1 << freeBits) - 1);
- StringBuilder zplImage = new StringBuilder(imageSize * 2);
- zplImage.AppendFormat("^GFA,{0},{1},{2},",
- imageSize.ToString(),
- imageSize.ToString(),
- widthInBytes.ToString());
- StringBuilder previousLine = new StringBuilder();
- for (int i = 0; i < image.Height; i++)
- {
- StringBuilder line = new StringBuilder(widthInBytes * 2);
- StringBuilder computedLine = new StringBuilder(widthInBytes);
- bool lastZeros = true;
- for (int j = 0; j < widthInBytes; j++)
- {
- byte b = (byte)~(picBytes[i * imgData.Stride + j]);
- if (j == widthInBytes - 1)
- {
- b = (byte)(b & ~lastByteMask);
- }
- if (b != 0)
- {
- lastZeros = false;
- computedLine.Append(line);
- line.Length = 0;
- }
- else
- {
- if (!lastZeros)
- {
- computedLine.Append(line);
- line.Length = 0;
- }
- lastZeros = true;
- }
- line.Append(b.ToString("X2"));
- }
- if (lastZeros)
- computedLine.Append(",");
- else
- computedLine.Append(line);
- if (previousLine.Equals(computedLine))
- zplImage.Append(":");
- else
- {
- zplImage.Append(CompressLine(computedLine));
- previousLine = computedLine;
- }
- }
- zplImage.Append("^FS");
- return zplImage.ToString();
- }
- private StringBuilder CompressLine(StringBuilder line)
- {
- StringBuilder result = new StringBuilder();
- char previousChar = '-'; // different initial char
- int counter = 0;
- for (int i = 0; i < line.Length; i++)
- {
- char currentChar = line[i]; // this line for better understanding
- if (currentChar == previousChar) // char is repeating
- {
- if (counter == 0) // char is not counted
- {
- result.Length = result.Length - 1; // remove last char and keep count
- counter += 2; // add previous and current
- }
- else
- counter++; // keep count
- }
- else
- {
- if (counter > 0) // current char is different and we have repeated before
- {
- result. // append to result
- Append(GetCount(counter)). // count
- Append(previousChar). // compressed char
- Append(currentChar); // current char
- counter = 0; // reset counter
- }
- else
- result.Append(currentChar); // just add current char to result
- previousChar = currentChar; // save current char as previous
- }
- }
- if (counter > 0)
- {
- result.Append(GetCount(counter)).Append(previousChar);
- }
- return result;
- }
- private StringBuilder GetCount(int counter)
- {
- StringBuilder sb = new StringBuilder();
- int remainder = counter;
- int index = counts.Length - 1;
- while (remainder > 0 && index >= 0)
- {
- if (counts[index] <= remainder)
- {
- sb.Append(countTable[counts[index]]);
- remainder -= counts[index];
- }
- index--;
- }
- return sb;
- }
- /// <summary>
- /// Exports the LineObject.
- /// </summary>
- /// <param name="lineObject"></param>
- private void ExportLineObject(LineObject lineObject)
- {
- if (lineObject.Width == 0 || lineObject.Height == 0)
- ExportRectangle(lineObject.AbsLeft,
- lineObject.AbsTop,
- lineObject.Width,
- lineObject.Height,
- lineObject.Border.Width);
- else
- ExportLine(lineObject.AbsLeft,
- lineObject.AbsTop,
- lineObject.Width,
- lineObject.Height,
- lineObject.Border.Width);
- }
- /// <summary>
- /// Exports the ShapeObject.
- /// </summary>
- /// <param name="shapeObject"></param>
- private void ExportShapeObject(ShapeObject shapeObject)
- {
- if (shapeObject.Shape == ShapeKind.Ellipse) //-V3024
- ExportEllipse(shapeObject.AbsLeft,
- shapeObject.AbsTop,
- shapeObject.Width,
- shapeObject.Height,
- shapeObject.Border.Width);
- else
- ExportRectangle(shapeObject.AbsLeft,
- shapeObject.AbsTop,
- shapeObject.Width,
- shapeObject.Height,
- shapeObject.Border.Width);
- }
- private void ExportRectangle(float Left, float Top, float Width, float Height, float LineWidth)
- {
- int left = Width > 0 ? GetLeft(Left) : GetLeft(Left + Width);
- int top = Height > 0 ? GetLeft(Top) : GetTop(Top + Height);
- int width = (int)Math.Abs(Math.Round(Width * zplScaleArray[scaleIndex].PageScale));
- int height = (int)Math.Abs(Math.Round(Height * zplScaleArray[scaleIndex].PageScale));
- int lineWidth = (int)Math.Round(LineWidth * zplScaleArray[scaleIndex].PageScale);
- WriteLn(Stream, SetPosition(left, top));
- WriteLn(Stream, DrawRectangle(width, height, lineWidth));
- }
- private void ExportEllipse(float Left, float Top, float Width, float Height, float LineWidth)
- {
- int left = Width > 0 ? GetLeft(Left) : GetLeft(Left + Width);
- int top = Height > 0 ? GetLeft(Top) : GetTop(Top + Height);
- int width = (int)Math.Abs(Math.Round(Width * zplScaleArray[scaleIndex].PageScale));
- int height = (int)Math.Abs(Math.Round(Height * zplScaleArray[scaleIndex].PageScale));
- int lineWidth = (int)Math.Round(LineWidth * zplScaleArray[scaleIndex].PageScale);
- WriteLn(Stream, SetPosition(left, top));
- WriteLn(Stream, DrawEllipse(width, height, lineWidth));
- }
- private void ExportLine(float Left, float Top, float Width, float Height, float LineWidth)
- {
- int left = Width > 0 ? GetLeft(Left) : GetLeft(Left + Width);
- int top = Height > 0 ? GetLeft(Top) : GetTop(Top + Height);
- int width = (int)Math.Abs(Math.Round(Width * zplScaleArray[scaleIndex].PageScale));
- int height = (int)Math.Abs(Math.Round(Height * zplScaleArray[scaleIndex].PageScale));
- bool direction = (Width > 0 && Height > 0) || (Width < 0 && Height < 0);
- int lineWidth = (int)Math.Round(LineWidth * zplScaleArray[scaleIndex].PageScale);
- WriteLn(Stream, SetPosition(left, top));
- WriteLn(Stream, DrawLine(width, height, lineWidth, direction));
- }
- /// <summary>
- /// Exports the TextObject.
- /// </summary>
- /// <param name="textObject"></param>
- private void ExportTextObject(TextObject textObject)
- {
- // calc the width of object
- int width = GetWidth(textObject.Width, textObject.Height, textObject.Angle);
- // calc lines count
- // to-do: need fix with AdvancedTextRenderer
- int lines = (int)Math.Round(textObject.Height / Math.Round(textObject.Font.Height * DrawUtils.ScreenDpiFX));
- // calc line height
- int lineHeight = (int)Math.Round(textObject.Font.Height * zplScaleArray[scaleIndex].PageScale);
- // calc font height
- int fontHeight = (int)Math.Round(Math.Round(textObject.Font.Height * DrawUtils.ScreenDpiFX) * zplScaleArray[scaleIndex].PageScale / fontScale);
- // calc font width
- int fontWidth = (int)Math.Round((float)fontHeight / 2);
- // calc top position of text
- int top;
- if (textObject.VertAlign == VertAlign.Top)
- top = GetTop(textObject.AbsTop);
- else if (textObject.VertAlign == VertAlign.Bottom)
- top = GetTop(textObject.AbsTop) +
- GetHeight(textObject.Width, textObject.Height, textObject.Angle) -
- fontHeight * lines;
- else
- top = GetTop(textObject.AbsTop) +
- (int)(GetHeight(textObject.Width, textObject.Height, textObject.Angle) / 2) -
- (int)Math.Round((float)(fontHeight * lines) / 2);
- // set-up position
- //TO DO: for TextObject you need to redo the formula
- //The text moves to the left by 10 points because of this I put +10
- WriteLn(Stream, SetPosition(GetLeft(textObject.AbsLeft) + 10, top));
- // set-up the text attribs
- WriteLn(Stream, SetTextAttributes(width, lines, 0, textObject.HorzAlign, 0));
- WriteLn(Stream, GetOrientation(textObject.Angle));
- // draw text
- WriteLn(Stream, DrawText(fontHeight, fontWidth, textObject.Text));
- // draw borders
- DrawBorders(textObject.Border, textObject.AbsLeft, textObject.AbsTop, textObject.Width, textObject.Height);
- }
- private void DrawBorders(Border border, float AbsLeft, float AbsTop, float Width, float Height)
- {
- if (border.Width > 0)
- {
- if (border.Lines == BorderLines.All)
- ExportRectangle(AbsLeft, AbsTop, Width, Height, border.Width);
- else
- {
- int left = Width > 0 ? GetLeft(AbsLeft) : GetLeft(AbsLeft + Width);
- int top = Height > 0 ? GetLeft(AbsTop) : GetTop(AbsTop + Height);
- int width = (int)Math.Abs(Math.Round(Width * zplScaleArray[scaleIndex].PageScale));
- int height = (int)Math.Abs(Math.Round(Height * zplScaleArray[scaleIndex].PageScale));
- int lineWidth = (int)Math.Round(border.Width * zplScaleArray[scaleIndex].PageScale);
- if ((BorderLines.Top & border.Lines) != 0)
- {
- lineWidth = (int)Math.Round(border.TopLine.Width * zplScaleArray[scaleIndex].PageScale);
- WriteLn(Stream, SetPosition(left, top));
- WriteLn(Stream, DrawRectangle(width, 0, lineWidth));
- }
- if ((BorderLines.Left & border.Lines) != 0)
- {
- lineWidth = (int)Math.Round(border.LeftLine.Width * zplScaleArray[scaleIndex].PageScale);
- WriteLn(Stream, SetPosition(left, top));
- WriteLn(Stream, DrawRectangle(0, height, lineWidth));
- }
- if ((BorderLines.Bottom & border.Lines) != 0)
- {
- lineWidth = (int)Math.Round(border.BottomLine.Width * zplScaleArray[scaleIndex].PageScale);
- WriteLn(Stream, SetPosition(left, top + height));
- WriteLn(Stream, DrawRectangle(width, 0, lineWidth));
- }
- if ((BorderLines.Right & border.Lines) != 0)
- {
- lineWidth = (int)Math.Round(border.RightLine.Width * zplScaleArray[scaleIndex].PageScale);
- WriteLn(Stream, SetPosition(left + width, top));
- WriteLn(Stream, DrawRectangle(0, height, lineWidth));
- }
- }
- }
- }
- private void ExportBarcodeObject(BarcodeObject b)
- {
- int height = GetHeight(b.Width, b.Height, b.Angle);
- WriteLn(Stream, SetPosition(GetLeft(b.AbsLeft), GetTop(b.AbsTop)));
- if (!(b.Barcode is BarcodeQR))
- {
- WriteLn(Stream, "^BY" + GetBarcodeZoom(b.Zoom, b.Barcode) + ",," + height.ToString());
- WriteLn(Stream, GetOrientation(b.Angle));
- char printLine = (b.ShowText ? 'Y' : 'N');
- //TO DO: It makes sense for some barcodes to set the height
- if (b.Barcode is Barcode128 || b.Barcode is BarcodeEAN128)
- WriteLn(Stream, String.Format("^BC,,{0},N,N", printLine));
- else if (b.Barcode is Barcode2of5Industrial)
- WriteLn(Stream, String.Format("^BI,,{0},N", printLine));
- else if (b.Barcode is Barcode2of5Interleaved)
- WriteLn(Stream, String.Format("^B2,,{0},N,N", printLine));
- else if (b.Barcode is Barcode2of5Matrix)
- WriteLn(Stream, String.Format("^BJ,,{0},N", printLine));
- else if (b.Barcode is Barcode39Extended)
- WriteLn(Stream, String.Format("^B3,Y,,{0},N", printLine));
- else if (b.Barcode is Barcode39)
- WriteLn(Stream, String.Format("^B3,N,,{0},N", printLine));
- else if (b.Barcode is Barcode93Extended)
- WriteLn(Stream, String.Format("^BA,,{0},N,N", printLine));
- else if (b.Barcode is Barcode93)
- WriteLn(Stream, String.Format("^BA,,{0},N,N", printLine));
- else if (b.Barcode is BarcodeCodabar)
- WriteLn(Stream, String.Format("^BK,N,{0},N,,", printLine));
- else if (b.Barcode is BarcodeUPC_A)
- WriteLn(Stream, String.Format("^BU,,{0},N,Y", printLine));
- else if (b.Barcode is BarcodeUPC_E0)
- WriteLn(Stream, String.Format("^B9,,{0},N,Y", printLine));
- else if (b.Barcode is BarcodeUPC_E1)
- WriteLn(Stream, String.Format("^B9,,{0},N,Y", printLine));
- else if (b.Barcode is BarcodeEAN8)
- WriteLn(Stream, String.Format("^B8,,{0},N", printLine));
- else if (b.Barcode is BarcodeEAN13)
- WriteLn(Stream, String.Format("^BE,,{0},N", printLine));
- else if (b.Barcode is BarcodeIntelligentMail)
- WriteLn(Stream, String.Format("^BZ,,{0},N,3", printLine));
- else if (b.Barcode is BarcodeMSI)
- WriteLn(Stream, String.Format("^BM,,,{0},N,N", printLine));
- else if (b.Barcode is BarcodePDF417)
- WriteLn(Stream, "^B7,,,,,");
- else if (b.Barcode is BarcodePlessey)
- WriteLn(Stream, String.Format("^BP,,{0},N", printLine));
- else if (b.Barcode is BarcodePostNet)
- WriteLn(Stream, String.Format("^BZ,,{0},N,0", printLine));
- else if (b.Barcode is BarcodeAztec)
- WriteLn(Stream, String.Format("^BO,{0},,,,,",
- zplScaleArray[scaleIndex].TwoDCodeScale.ToString()));
- else if (b.Barcode is BarcodeDatamatrix)
- WriteLn(Stream, "^BX,,,,,,");
- else if (b.Barcode is BarcodeMaxiCode)
- {
- BarcodeMaxiCode maxiCode = b.Barcode as BarcodeMaxiCode;
- WriteLn(Stream, String.Format("^BD{0},,", maxiCode.Mode.ToString()));
- }
- WriteLn(Stream, "^FD" + GetZPLText(b.Text) + "^FS");
- // to-do BarcodeSupplement2, BarcodeSupplement5, BarcodePharmacode - didn't match
- }
- else // QR code
- {
- WriteLn(Stream, "^BY2,2,0");
- WriteLn(Stream, String.Format("^BQ,2,{0}",
- Math.Round((float)zplScaleArray[scaleIndex].TwoDCodeScale * b.Zoom).ToString()));
- WriteLn(Stream, "^FDMA," + GetZPLText(b.Text) + "^FS");
- }
- }
- /// <summary>
- /// Gets the position of object in ZPL code.
- /// </summary>
- /// <param name="left"></param>
- /// <param name="top"></param>
- /// <returns></returns>
- private string SetPosition(int left, int top)
- {
- return String.Format("^FO{0},{1}", left, top);
- }
- /// <summary>
- /// Gets the text attributes in ZPL code.
- /// </summary>
- /// <param name="width"></param>
- /// <param name="lines"></param>
- /// <param name="leading"></param>
- /// <param name="horizAlign"></param>
- /// <param name="gap"></param>
- /// <returns></returns>
- private string SetTextAttributes(int width, int lines, int leading, HorzAlign horizAlign, int gap)
- {
- return String.Format("^FB{0},{1},{2},{3},{4}",
- width,
- lines,
- leading,
- GetHorizAlign(horizAlign),
- gap
- );
- }
- /// <summary>
- /// Gets the text with font width and height in ZPL code.
- /// </summary>
- /// <param name="fontHeight"></param>
- /// <param name="fontWidth"></param>
- /// <param name="text"></param>
- /// <returns></returns>
- private string DrawText(int fontHeight, int fontWidth, string text)
- {
- return String.Format("^A{0},{1},{2}^FD{3}^FS",
- font,
- fontHeight,
- fontWidth,
- GetZPLText(text)
- );
- }
- /// <summary>
- /// Gets the horiz align in ZPL code.
- /// </summary>
- /// <param name="horizAlign"></param>
- /// <returns></returns>
- private string GetHorizAlign(HorzAlign horizAlign)
- {
- switch (horizAlign)
- {
- case HorzAlign.Left:
- return "L";
- case HorzAlign.Center:
- return "C";
- case HorzAlign.Right:
- return "R";
- default:
- return "J";
- }
- }
- /// <summary>
- /// Gets the rectangle in ZPL code.
- /// </summary>
- /// <param name="width"></param>
- /// <param name="height"></param>
- /// <param name="lineWidth"></param>
- /// <returns></returns>
- private string DrawRectangle(int width, int height, int lineWidth)
- {
- return String.Format((version == ZplVersions.ZPL2 ? "^LRN" : "") + "^GB{0},{1},{2}^FS",
- width,
- height,
- lineWidth);
- }
- private string DrawEllipse(int width, int height, int lineWidth)
- {
- return String.Format("^GE{0},{1},{2}^FS",
- width,
- height,
- lineWidth);
- }
- private string DrawLine(int width, int height, int lineWidth, bool direction)
- {
- return String.Format("^GD{0},{1},{2},,{3}^FS",
- width.ToString(),
- height.ToString(),
- lineWidth.ToString(),
- direction ? "L" : "R");
- }
- #endregion Private Methods
- #region Protected Methods
- /// <inheritdoc/>
- protected override void Start()
- {
- base.Start();
- // Init of scale index.
- switch (density)
- {
- case ZplDensity.d6_dpmm_152_dpi:
- scaleIndex = 0;
- break;
- case ZplDensity.d8_dpmm_203_dpi:
- scaleIndex = 1;
- break;
- case ZplDensity.d12_dpmm_300_dpi:
- scaleIndex = 2;
- break;
- case ZplDensity.d24_dpmm_600_dpi:
- scaleIndex = 3;
- break;
- }
- WriteLn(Stream, printerInit);
- }
- /// <inheritdoc/>
- protected override void Finish()
- {
- WriteLn(Stream, printerFinish);
- }
- /// <inheritdoc/>
- protected override string GetFileFilter()
- {
- return new MyRes("FileFilters").Get("ZplFile");
- }
- /// <inheritdoc/>
- protected override void ExportPageBegin(ReportPage page)
- {
- base.ExportPageBegin(page);
- WriteLn(Stream, String.Format("^XA{0}", codePage));
- WriteLn(Stream, pageInit);
- leftMargin = page.LeftMargin * millimeters * zplScaleArray[scaleIndex].PageScale;
- topMargin = page.TopMargin * millimeters * zplScaleArray[scaleIndex].PageScale;
- if (printAsBitmap)
- {
- pageBitmap = new Bitmap(
- (int)Math.Round(ExportUtils.GetPageWidth(page) * millimeters * zplScaleArray[scaleIndex].PageScale),
- (int)Math.Round(ExportUtils.GetPageHeight(page) * millimeters * zplScaleArray[scaleIndex].PageScale),
- PixelFormat.Format32bppArgb);
- using (Graphics g = Graphics.FromImage(pageBitmap))
- g.Clear(Color.White);
- }
- }
- /// <inheritdoc/>
- protected override void ExportPageEnd(ReportPage page)
- {
- if (printAsBitmap)
- {
- WriteLn(Stream, SetPosition((int)leftMargin, (int)topMargin));
- WriteLn(Stream, DrawBWPicture(pageBitmap));
- pageBitmap.Dispose();
- }
- base.ExportPageEnd(page);
- WriteLn(Stream, "^XZ");
- }
- /// <inheritdoc/>
- protected override void ExportBand(BandBase band)
- {
- base.ExportBand(band);
- if (band.Parent == null)
- return;
- if (printAsBitmap)
- DrawObjectOnBitmap(pageBitmap, band, true);
- foreach (Base c in band.ForEachAllConvectedObjects(this))
- {
- if (c is ReportComponentBase && (c as ReportComponentBase).Exportable)
- {
- ReportComponentBase bandObject = c as ReportComponentBase;
- if (printAsBitmap)
- DrawObjectOnBitmap(pageBitmap, bandObject, true);
- else
- {
- if (bandObject is CellularTextObject)
- bandObject = (bandObject as CellularTextObject).GetTable();
- if (bandObject is TableCell)
- continue;
- else if (bandObject is TableBase)
- ExportTableObject(bandObject as TableBase);
- else if (bandObject is TextObject)
- ExportTextObject(bandObject as TextObject);
- else if (bandObject is ShapeObject)
- ExportShapeObject(bandObject as ShapeObject);
- else if (bandObject is LineObject)
- ExportLineObject(bandObject as LineObject);
- else if (bandObject is RFIDLabel)
- ExportRFIDLabel(bandObject as RFIDLabel);
- else if (bandObject is BarcodeObject)
- ExportBarcodeObject(bandObject as BarcodeObject);
- else
- ExportPictureObject(bandObject);
- }
- }
- }
- }
- private void ExportRFIDLabel(RFIDLabel rfidLabel)
- {
- //data
- if (!string.IsNullOrEmpty(rfidLabel.EpcBank.Data))
- {
- //RF parametrs
- // 1. R - read, W - write, S - password
- // 2. Format H - Hex, A - ASCII, E - EPC
- // 3. start block in bank
- // 4. number of bytes to read or write
- // 5. index of bank. 0 - Reserved(passwords), 1 - EPC, 2 - TID, 3 - User, E - EPC 20th bit, A - EPC 20th bit with auto adjust bits
- if (!string.IsNullOrEmpty(rfidLabel.EpcFormat))
- {
- WriteLn(Stream, $"^RB{rfidLabel.EpcFormat}^FS");
- WriteLn(Stream, $"^RFW,E^FD{rfidLabel.EpcBank.Data}^FS");
- }
- else if (rfidLabel.RewriteEPCbank)
- WriteLn(Stream, $"^RFW,{(char)rfidLabel.EpcBank.DataFormat},{rfidLabel.EpcBank.Offset},{rfidLabel.EpcBank.CountByte},1^FD{rfidLabel.EpcBank.Data}^FS");//2,,A/E
- else if (rfidLabel.UseAdjustForEPC)
- WriteLn(Stream, $"^RFW,{(char)rfidLabel.EpcBank.DataFormat},2,,E^FD{rfidLabel.EpcBank.Data}^FS");
- else
- WriteLn(Stream, $"^RFW,{(char)rfidLabel.EpcBank.DataFormat},2,,A^FD{rfidLabel.EpcBank.Data}^FS");
- }
- if (!string.IsNullOrEmpty(rfidLabel.TIDBank.Data))
- {
- WriteLn(Stream, $"^RFW,{(char)rfidLabel.TIDBank.DataFormat},{rfidLabel.TIDBank.Offset},{rfidLabel.TIDBank.CountByte},2^FD{rfidLabel.TIDBank.Data}^FS");
- }
- if (!string.IsNullOrEmpty(rfidLabel.UserBank.Data))
- {
- WriteLn(Stream, $"^RFW,{(char)rfidLabel.UserBank.DataFormat},{rfidLabel.UserBank.CountByte},{rfidLabel.UserBank.CountByte},3^FD{rfidLabel.UserBank.Data}^FS");
- }
- if (!string.IsNullOrEmpty(rfidLabel.AccessPassword) && rfidLabel.AccessPassword != "00000000" || !string.IsNullOrEmpty(rfidLabel.KillPassword) && rfidLabel.KillPassword != "00000000")
- {
- WriteLn(Stream, $"^RFW,H,P^FD{rfidLabel.AccessPassword}{(string.IsNullOrEmpty(rfidLabel.KillPassword) ? "" : $",{rfidLabel.KillPassword}")}^FS");
- }
- if (!string.IsNullOrEmpty(rfidLabel.AccessPassword) && rfidLabel.AccessPassword != "00000000")
- WriteLn(Stream, $"^RLM,{(char)rfidLabel.LockKillPassword},{(char)rfidLabel.LockAccessPassword},{(char)rfidLabel.LockEPCBank},{(char)rfidLabel.LockUserBank}");
- if (rfidLabel.CountPermaLock > 0)
- WriteLn(Stream, $"^RLB{rfidLabel.StartPermaLock},{rfidLabel.CountPermaLock}");
- WriteLn(Stream, $"^RS,,,,{rfidLabel.ErrorHandle}");
- if (rfidLabel.AdaptiveAntenna)
- WriteLn(Stream, "^RR,1");
- if (rfidLabel.ReadPower != 16 || rfidLabel.WritePower != 16)
- {
- WriteLn(Stream, $"^RW{rfidLabel.ReadPower},{rfidLabel.WritePower}^FS");
- }
- if (printAsBitmap)
- DrawObjectOnBitmap(pageBitmap, rfidLabel, true);
- foreach (Base c in rfidLabel.ForEachAllConvectedObjects(this))
- {
- if (c is ReportComponentBase && (c as ReportComponentBase).Exportable)
- {
- ReportComponentBase bandObject = c as ReportComponentBase;
- if (printAsBitmap)
- DrawObjectOnBitmap(pageBitmap, bandObject, true);
- else
- {
- if (bandObject is CellularTextObject)
- bandObject = (bandObject as CellularTextObject).GetTable();
- if (bandObject is TableCell)
- continue;
- else if (bandObject is TableBase)
- ExportTableObject(bandObject as TableBase);
- else if (bandObject is TextObject)
- ExportTextObject(bandObject as TextObject);
- else if (bandObject is ShapeObject)
- ExportShapeObject(bandObject as ShapeObject);
- else if (bandObject is LineObject)
- ExportLineObject(bandObject as LineObject);
- else if (bandObject is RFIDLabel)
- ExportRFIDLabel(bandObject as RFIDLabel);
- else if (bandObject is BarcodeObject)
- ExportBarcodeObject(bandObject as BarcodeObject);
- else
- ExportPictureObject(bandObject);
- }
- }
- }
- }
- #endregion Protected Methods
- #region Public Methods
- /// <inheritdoc/>
- public override void Serialize(FRWriter writer)
- {
- base.Serialize(writer);
- // Options
- writer.WriteValue("Density", Density);
- writer.WriteValue("Version", Version);
- writer.WriteBool("PrintAsBitmap", PrintAsBitmap);
- writer.WriteValue("FontScale", FontScale);
- writer.WriteValue("BarcodeScale", BarcodeScale);
- // end
- }
- #endregion Public Methods
- /// <summary>
- /// Initializes a new instance of the <see cref="ZplExport"/> class.
- /// </summary>
- public ZplExport()
- {
- countTable = new Dictionary<int, char>();
- countTable.Add(1, 'G');
- countTable.Add(2, 'H');
- countTable.Add(3, 'I');
- countTable.Add(4, 'J');
- countTable.Add(5, 'K');
- countTable.Add(6, 'L');
- countTable.Add(7, 'M');
- countTable.Add(8, 'N');
- countTable.Add(9, 'O');
- countTable.Add(10, 'P');
- countTable.Add(11, 'Q');
- countTable.Add(12, 'R');
- countTable.Add(13, 'S');
- countTable.Add(14, 'T');
- countTable.Add(15, 'U');
- countTable.Add(16, 'V');
- countTable.Add(17, 'W');
- countTable.Add(18, 'X');
- countTable.Add(19, 'Y');
- countTable.Add(20, 'g');
- countTable.Add(40, 'h');
- countTable.Add(60, 'i');
- countTable.Add(80, 'j');
- countTable.Add(100, 'k');
- countTable.Add(120, 'l');
- countTable.Add(140, 'm');
- countTable.Add(160, 'n');
- countTable.Add(180, 'o');
- countTable.Add(200, 'p');
- countTable.Add(220, 'q');
- countTable.Add(240, 'r');
- countTable.Add(260, 's');
- countTable.Add(280, 't');
- countTable.Add(300, 'u');
- countTable.Add(320, 'v');
- countTable.Add(340, 'w');
- countTable.Add(360, 'x');
- countTable.Add(380, 'y');
- countTable.Add(400, 'z');
- // prepare for indexed access to keys
- counts = new int[countTable.Count];
- countTable.Keys.CopyTo(counts, 0);
- }
- }
- }
|