using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Media; using ZXing.Common; using ZXing.Rendering; using ZXing; using System.Windows; namespace AIStudio.Wpf.DiagramDesigner.Additionals.Controls { /// /// Renders a barcode into a geometry /// Autor: Rob Fonseca-Ensor /// public class GeometryRenderer : IBarcodeRenderer { /// /// Renders the specified matrix. /// /// The matrix. /// The format. /// The content. /// public Geometry Render(BitMatrix matrix, BarcodeFormat format, string content) { return Render(matrix, format, content, null); } /// /// Renders the specified matrix. /// /// The matrix. /// The format. /// The content. /// The options. /// public Geometry Render(BitMatrix matrix, BarcodeFormat format, string content, EncodingOptions options) { var edges = new HashSet(); var edgeMap = new Dictionary>(); var cols = matrix.Width; var rows = matrix.Height; for (int c = 0; c <= cols; c++) { for (int r = 0; r <= rows; r++) { var cell = GetCell(c, r, matrix); var westCell = GetCell(c - 1, r, matrix); var northCell = GetCell(c, r - 1, matrix); if (northCell != cell) { AddEdge(new Edge(c, r, c + 1, r), edges, edgeMap); } if (westCell != cell) { AddEdge(new Edge(c, r, c, r + 1), edges, edgeMap); } } } var cycles = new List>(); while (edges.Count > 0) { var edge = edges.First(); RemoveEdge(edge, edges, edgeMap); if (IsEdgeLeftHand(matrix, edge)) { edge = edge.Reversed(); } var currentCycle = new List { edge.From, edge.To }; while (edge.To != currentCycle[0]) { var moves = from direction in Turns(edge.From - edge.To) let nextCoordinate = direction + edge.To from e in EdgesFrom(edge.To, edgeMap) where e.To == nextCoordinate || e.From == nextCoordinate select e; var nextEdge = moves.First(); RemoveEdge(nextEdge, edges, edgeMap); edge = nextEdge.To != edge.To ? nextEdge : nextEdge.Reversed(); currentCycle.Add(edge.To); } cycles.Add(currentCycle); } return new PathGeometry(cycles.Select(x => new PathFigure(x.First().ToPoint(1), x.Skip(1).Select(y => new LineSegment(y.ToPoint(1), true)), true))); } private static bool IsEdgeLeftHand(BitMatrix b, Edge edge) { var cell = GetCell(edge.From.Col, edge.From.Row, b); return (edge.From.Row < edge.To.Row && cell) || (!(edge.From.Col < edge.To.Col && cell)); } private static IEnumerable EdgesFrom(Coordinate c, Dictionary> edgeMap) { return edgeMap.ContainsKey(c) ? edgeMap[c] : Enumerable.Empty(); } private static IEnumerable Turns(Coordinate currentDirection) { int index = Array.IndexOf(Coordinate.Directions, currentDirection); return Coordinate.Directions.Skip(index + 1).Concat(Coordinate.Directions.Take(index)); } private static bool GetCell(int c, int r, BitMatrix matrix) { if (r < 0 || r >= matrix.Height) { return false; } if (c < 0 || c >= matrix.Width) { return false; } return matrix[c, r]; } private static void RemoveEdge(Edge e, HashSet edges, Dictionary> edgeMap) { edges.Remove(e); edgeMap[e.From].Remove(e); edgeMap[e.To].Remove(e); } private static void AddEdge(Edge e, HashSet edges, Dictionary> edgeMap) { edges.Add(e); AddCoordinate(e.From, e, edgeMap); AddCoordinate(e.To, e, edgeMap); } private static void AddCoordinate(Coordinate c, Edge e, Dictionary> edgeMap) { List list; if (!edgeMap.TryGetValue(c, out list)) { edgeMap[c] = list = new List(); } list.Add(e); } private struct Coordinate { public readonly int Row, Col; public Coordinate(int col, int row) { Col = col; Row = row; } public bool Equals(Coordinate other) { return other.Row == Row && other.Col == Col; } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (obj.GetType() != typeof(Coordinate)) return false; return Equals((Coordinate)obj); } public override int GetHashCode() { unchecked { return (Row * 397) ^ Col; } } public override string ToString() { var s = ""; if (this == North) s = " n"; if (this == West) s = " w"; if (this == South) s = " s"; if (this == East) s = " e"; return String.Format("({0}, {1}{2})", Col, Row, s); } public static bool operator ==(Coordinate left, Coordinate right) { return left.Equals(right); } public static bool operator !=(Coordinate left, Coordinate right) { return !left.Equals(right); } public static Coordinate operator +(Coordinate c1, Coordinate c2) { return new Coordinate(c1.Col + c2.Col, c1.Row + c2.Row); } public static Coordinate operator -(Coordinate c1, Coordinate c2) { return new Coordinate(c1.Col - c2.Col, c1.Row - c2.Row); } public Point ToPoint(double scale) { return new Point(Col * scale, Row * scale); } private static readonly Coordinate West = new Coordinate(-1, 0); private static readonly Coordinate South = new Coordinate(0, 1); private static readonly Coordinate East = new Coordinate(1, 0); private static readonly Coordinate North = new Coordinate(0, -1); public static readonly Coordinate[] Directions = new[] { West, South, East, North, }; } private struct Edge { public readonly Coordinate From, To; public Edge(Coordinate from, Coordinate to) { From = from; To = to; } public Edge(int fromCol, int fromRow, int toCol, int toRow) : this(new Coordinate(fromCol, fromRow), new Coordinate(toCol, toRow)) { } public bool Equals(Edge other) { return other.From.Equals(From) && other.To.Equals(To); } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (obj.GetType() != typeof(Edge)) return false; return Equals((Edge)obj); } public override int GetHashCode() { unchecked { return (From.GetHashCode() * 397) ^ To.GetHashCode(); } } public override string ToString() { char angle = ' '; if (From.Col == To.Col) { angle = '|'; } if (From.Row == To.Row) { angle = '-'; } return string.Format("[{0} {2} {1}]", From, To, angle); } public static bool operator ==(Edge left, Edge right) { return left.Equals(right); } public static bool operator !=(Edge left, Edge right) { return !left.Equals(right); } public Edge Reversed() { return new Edge(To, From); } } } }