using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.ComponentModel;
using FastReport.Barcode.QRCode;
using FastReport.Utils;
using System.Drawing.Drawing2D;
namespace FastReport.Barcode
{
///
/// Specifies the QR code error correction level.
///
public enum QRCodeErrorCorrection
{
///
/// L = ~7% correction.
///
L,
///
/// M = ~15% correction.
///
M,
///
/// Q = ~25% correction.
///
Q,
///
/// H = ~30% correction.
///
H
}
///
/// Specifies the QR Code encoding.
///
public enum QRCodeEncoding
{
///
/// UTF-8 encoding.
///
UTF8,
///
/// ISO 8859-1 encoding.
///
ISO8859_1,
///
/// Shift_JIS encoding.
///
Shift_JIS,
///
/// Windows-1251 encoding.
///
Windows_1251,
///
/// cp866 encoding.
///
cp866
}
///
/// Generates the 2D QR code barcode.
///
public class BarcodeQR : Barcode2DBase
{
#region Fields
private QRCodeErrorCorrection errorCorrection;
private QRCodeEncoding encoding;
private bool quietZone;
private ByteMatrix matrix;
private const int PixelSize = 4;
#endregion
#region Properties
///
/// Gets or sets the error correction.
///
[DefaultValue(QRCodeErrorCorrection.L)]
public QRCodeErrorCorrection ErrorCorrection
{
get { return errorCorrection; }
set { errorCorrection = value; }
}
///
/// Gets or sets the encoding used for text conversion.
///
[DefaultValue(QRCodeEncoding.UTF8)]
public QRCodeEncoding Encoding
{
get { return encoding; }
set { encoding = value; }
}
///
/// Gets or sets the value indicating that quiet zone must be shown.
///
[DefaultValue(true)]
public bool QuietZone
{
get { return quietZone; }
set { quietZone = value; }
}
#endregion
#region Private Methods
private ErrorCorrectionLevel GetErrorCorrectionLevel()
{
switch (errorCorrection)
{
case QRCodeErrorCorrection.L:
return ErrorCorrectionLevel.L;
case QRCodeErrorCorrection.M:
return ErrorCorrectionLevel.M;
case QRCodeErrorCorrection.Q:
return ErrorCorrectionLevel.Q;
case QRCodeErrorCorrection.H:
return ErrorCorrectionLevel.H;
}
return ErrorCorrectionLevel.L;
}
private string GetEncoding()
{
switch (encoding)
{
case QRCodeEncoding.UTF8:
return "UTF-8";
case QRCodeEncoding.ISO8859_1:
return "ISO-8859-1";
case QRCodeEncoding.Shift_JIS:
return "Shift_JIS";
case QRCodeEncoding.Windows_1251:
return "Windows-1251";
case QRCodeEncoding.cp866:
return "cp866";
}
return "";
}
#endregion
#region Public Methods
///
public override void Assign(BarcodeBase source)
{
base.Assign(source);
BarcodeQR src = source as BarcodeQR;
ErrorCorrection = src.ErrorCorrection;
Encoding = src.Encoding;
QuietZone = src.QuietZone;
}
internal override void Serialize(FastReport.Utils.FRWriter writer, string prefix, BarcodeBase diff)
{
base.Serialize(writer, prefix, diff);
BarcodeQR c = diff as BarcodeQR;
if (c == null || ErrorCorrection != c.ErrorCorrection)
writer.WriteValue(prefix + "ErrorCorrection", ErrorCorrection);
if (c == null || Encoding != c.Encoding)
writer.WriteValue(prefix + "Encoding", Encoding);
if (c == null || QuietZone != c.QuietZone)
writer.WriteBool(prefix + "QuietZone", QuietZone);
}
internal override void Initialize(string text, bool showText, int angle, float zoom)
{
base.Initialize(text, showText, angle, zoom);
matrix = QRCodeWriter.encode(base.text, 0, 0, GetErrorCorrectionLevel(), GetEncoding(), QuietZone);
}
internal override SizeF CalcBounds()
{
int textAdd = showText ? 18 : 0;
return new SizeF(matrix.Width * PixelSize, matrix.Height * PixelSize + textAdd);
}
internal override void Draw2DBarcode(IGraphics g, float kx, float ky)
{
Brush dark = new SolidBrush(Color);
for (int y = 0; y < matrix.Height; y++)
{
for (int x = 0; x < matrix.Width; x++)
{
if (matrix.get_Renamed(x, y) == 0)
{
g.FillRectangle(dark, new RectangleF(
x * PixelSize * kx,
y * PixelSize * ky,
PixelSize * kx,
PixelSize * ky
));
}
}
}
if (text.StartsWith("SPC"))
{
ErrorCorrection = QRCodeErrorCorrection.M;
}
dark.Dispose();
}
#endregion
///
/// Initializes a new instance of the class with default settings.
///
public BarcodeQR()
{
Encoding = QRCodeEncoding.UTF8;
QuietZone = true;
}
}
}