/// <summary> /// Splits a node to fit the box. /// </summary> /// <param name="node">The node to split.</param> /// <param name="boxSize">The size of the box.</param> private void SplitNode(BinPackerNode node, Size boxSize) { node.IsOccupied = true; node.BottomNode = new BinPackerNode(node.Size.Width - boxSize.Width, node.Size.Height) { Position = new Point(node.Position.X + boxSize.Width, node.Position.Y) }; node.RightNode = new BinPackerNode(boxSize.Width, node.Size.Height - boxSize.Height) { Position = new Point(node.Position.X, node.Position.Y + boxSize.Height) }; }
/// <summary> /// Pack an enumeration of white space adjusted glyphs into the given canvas. /// </summary> /// <param name="adjustedGlyphs">The enumeration of glyphs.</param> /// <returns>Position information to a glyph.</returns> public IEnumerable <(AdjustedGlyph adjustedGlyph, Point position)> Pack(IEnumerable <AdjustedGlyph> adjustedGlyphs) { var orderedGlyphInformation = adjustedGlyphs .OrderByDescending(CalculateVolume) .Select(x => new { AdjustedGlyph = x, Size = x.WhiteSpaceAdjustment?.GlyphSize ?? x.Glyph.Size }); _rootNode = new BinPackerNode(_canvasSize.Width, _canvasSize.Height); foreach (var glyphInformation in orderedGlyphInformation) { var foundNode = FindNode(_rootNode, glyphInformation.Size); if (foundNode != null) { SplitNode(foundNode, glyphInformation.Size); yield return(glyphInformation.AdjustedGlyph, foundNode.Position); } } }
/// <summary> /// Find a node to fit the box in. /// </summary> /// <param name="node">The current node to search through.</param> /// <param name="boxSize">The size of the box.</param> /// <returns>The found node.</returns> private BinPackerNode FindNode(BinPackerNode node, Size boxSize) { if (node.IsOccupied) { var nextNode = FindNode(node.BottomNode, boxSize) ?? FindNode(node.RightNode, boxSize); return(nextNode); } if (boxSize.Width <= node.Size.Width && boxSize.Height <= node.Size.Height) { return(node); } return(null); }
/// <summary> /// Pack an enumeration of white space adjusted glyphs into the given canvas. /// </summary> /// <param name="adjustedGlyphs">The enumeration of glyphs.</param> /// <returns>Position information to a glyph.</returns> public IEnumerable <(AdjustedGlyph adjustedGlyph, Point position)> Pack(IEnumerable <AdjustedGlyph> adjustedGlyphs) { var orderedGlyphInformation = adjustedGlyphs .OrderByDescending(CalculateVolume) .Select(x => new { AdjustedGlyph = x, Size = GetGlyphSize(x) }); _rootNode = new BinPackerNode(_canvasSize.Width - _margin, _canvasSize.Height - _margin); foreach (var glyphInformation in orderedGlyphInformation) { var foundNode = FindNode(_rootNode, glyphInformation.Size); if (foundNode != null) { SplitNode(foundNode, glyphInformation.Size); yield return(glyphInformation.AdjustedGlyph, new Point(foundNode.Position.X + _margin, foundNode.Position.Y + _margin)); } } }