From d09bb30cec2cc36cd99b3a6ea26c64b45f353654 Mon Sep 17 00:00:00 2001 From: Markus Ewald Date: Wed, 16 May 2007 20:28:23 +0000 Subject: [PATCH] Added a small rectangle packing library for optimally arranging smaller rectangles within one larger rectangle git-svn-id: file:///srv/devel/repo-conversion/nusu@19 d2e56fa2-650e-0410-a79f-9358c0239efd --- Nuclex.Support (PC).csproj | 27 ++ Source/Licensing/LicenseKey.cs | 17 +- Source/Packing/ArevaloRectanglePacker.Test.cs | 47 +++ Source/Packing/ArevaloRectanglePacker.cs | 325 ++++++++++++++++++ Source/Packing/CygonRectanglePacker.Test.cs | 47 +++ Source/Packing/CygonRectanglePacker.cs | 92 +++++ Source/Packing/RectanglePacker.Test.cs | 61 ++++ Source/Packing/RectanglePacker.cs | 88 +++++ Source/Scheduling/IAbortable.cs | 19 + Source/Scheduling/Operation.cs | 19 + Source/Scheduling/ThreadedMethodOperation.cs | 19 + 11 files changed, 751 insertions(+), 10 deletions(-) create mode 100644 Source/Packing/ArevaloRectanglePacker.Test.cs create mode 100644 Source/Packing/ArevaloRectanglePacker.cs create mode 100644 Source/Packing/CygonRectanglePacker.Test.cs create mode 100644 Source/Packing/CygonRectanglePacker.cs create mode 100644 Source/Packing/RectanglePacker.Test.cs create mode 100644 Source/Packing/RectanglePacker.cs diff --git a/Nuclex.Support (PC).csproj b/Nuclex.Support (PC).csproj index 3987a0c..c9181b2 100644 --- a/Nuclex.Support (PC).csproj +++ b/Nuclex.Support (PC).csproj @@ -123,6 +123,33 @@ LicenseKey.Test LicenseKey.cs + + false + ArevaloRectanglePacker + + + false + ArevaloRectanglePacker.Test + ArevaloRectanglePacker.cs + + + false + CygonRectanglePacker + + + false + CygonRectanglePacker.Test + CygonRectanglePacker.cs + + + false + RectanglePacker + + + false + RectanglePacker.Test + RectanglePacker.cs + false BinarySerializer.Test diff --git a/Source/Licensing/LicenseKey.cs b/Source/Licensing/LicenseKey.cs index aa94a93..4c49ea5 100644 --- a/Source/Licensing/LicenseKey.cs +++ b/Source/Licensing/LicenseKey.cs @@ -151,10 +151,9 @@ namespace Nuclex.Support.Licensing { for(int j = 0; j < 31; ++j) sequence |= (int)powersOfTwo[j, bits[i * 31 + j] ? 1 : 0]; - // Using 7 bits, a number up to 2.147.483.648 can be represented, + // Using 31 bits, a number up to 2.147.483.648 can be represented, // while 6 alpha-numerical characters allow for 2.176.782.336 possible values, - // which is enough to fit 7 bits into each 6 alpha-numerical characters - // nun in 6 alphanumerische Zeichen zu verpacken. + // which means we can fit 31 bits into every 6 alpha-numerical characters. for(int j = 0; j < 6; ++j) { resultBuilder.Append(codeTable[sequence % 36]); sequence /= 36; @@ -176,13 +175,11 @@ namespace Nuclex.Support.Licensing { ); // Now build a nice, readable string from the decoded characters - string s = resultBuilder.ToString(); - return - s.Substring(0, 5) + "-" + - s.Substring(5, 5) + "-" + - s.Substring(10, 5) + "-" + - s.Substring(15, 5) + "-" + - s.Substring(20, 5); + resultBuilder.Insert(5, '-'); + resultBuilder.Insert(11, '-'); + resultBuilder.Insert(17, '-'); + resultBuilder.Insert(23, '-'); + return resultBuilder.ToString(); } /// Mangles a bit array diff --git a/Source/Packing/ArevaloRectanglePacker.Test.cs b/Source/Packing/ArevaloRectanglePacker.Test.cs new file mode 100644 index 0000000..d6131a9 --- /dev/null +++ b/Source/Packing/ArevaloRectanglePacker.Test.cs @@ -0,0 +1,47 @@ +#region CPL License +/* +Nuclex Framework +Copyright (C) 2002-2007 Nuclex Development Labs + +This library is free software; you can redistribute it and/or +modify it under the terms of the IBM Common Public License as +published by the IBM Corporation; either version 1.0 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +IBM Common Public License for more details. + +You should have received a copy of the IBM Common Public +License along with this library +*/ +#endregion +using System; +using System.Collections.Generic; + +using Microsoft.Xna.Framework; + +#if UNITTEST + +using NUnit.Framework; + +namespace Nuclex.Support.Packing { + + /// Unit test for the arevalo rectangle packer class + [TestFixture] + public class ArevaloRectanglePackerTest : RectanglePackerTest { + + /// Tests the packer's efficiency using a deterministic benchmark + [Test] + public void TestSpaceEfficiency() { + float efficiency = calculateEfficiency(new ArevaloRectanglePacker(70, 70)); + + Assert.GreaterOrEqual(efficiency, 0.75, "Packer achieves 75% efficiency"); + } + + } + +} // namespace Nuclex.Support.Packing + +#endif // UNITTEST diff --git a/Source/Packing/ArevaloRectanglePacker.cs b/Source/Packing/ArevaloRectanglePacker.cs new file mode 100644 index 0000000..5529f39 --- /dev/null +++ b/Source/Packing/ArevaloRectanglePacker.cs @@ -0,0 +1,325 @@ +#region CPL License +/* +Nuclex Framework +Copyright (C) 2002-2007 Nuclex Development Labs + +This library is free software; you can redistribute it and/or +modify it under the terms of the IBM Common Public License as +published by the IBM Corporation; either version 1.0 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +IBM Common Public License for more details. + +You should have received a copy of the IBM Common Public +License along with this library +*/ +#endregion +using System; +using System.Collections.Generic; + +using Microsoft.Xna.Framework; + +namespace Nuclex.Support.Packing { + + /// Rectangle packer using an algorithm by Javier Arevalo + /// + /// + /// You have a bunch of rectangular pieces. You need to arrange them in a + /// rectangular surface so that they don't overlap, keeping the total area of the + /// rectangle as small as possible. This is fairly common when arranging characters + /// in a bitmapped font, lightmaps for a 3D engine, and I guess other situations as + /// well. + /// + /// + /// The idea of this algorithm is that, as we add rectangles, we can pre-select + /// "interesting" places where we can try to add the next rectangles. For optimal + /// results, the rectangles should be added in order. I initially tried using area + /// as a sorting criteria, but it didn't work well with very tall or very flat + /// rectangles. I then tried using the longest dimension as a selector, and it + /// worked much better. So much for intuition... + /// + /// + /// These "interesting" places are just to the right and just below the currently + /// added rectangle. The first rectangle, obviously, goes at the top left, the next + /// one would go either to the right or below this one, and so on. It is a weird way + /// to do it, but it seems to work very nicely. + /// + /// + /// The way we search here is fairly brute-force, the fact being that for most off- + /// line purposes the performance seems more than adequate. I have generated a + /// japanese font with around 8500 characters and all the time was spent generating + /// the bitmaps. + /// + /// + /// Also, for all we care, we could grow the parent rectangle in a different way + /// than power of two. It just happens that power of 2 is very convenient for + /// graphics hardware textures. + /// + /// + /// I'd be interested in hearing of other approaches to this problem. Make sure + /// to post them on http://www.flipcode.com + /// + /// + public class ArevaloRectanglePacker : RectanglePacker { + + #region class AnchorRankComparer + + /// Compares the 'rank' of anchoring points + /// + /// Anchoring points are potential locations for the placement of new rectangles. + /// Each time a rectangle is inserted, an anchor point is generated on its upper + /// right end and another one at its lower left end. The anchor points are kept + /// in a list that is ordered by their closeness to the upper left corner of the + /// packing area (their 'rank') so the packer favors positions that are closer to + /// the upper left for new rectangles. + /// + private class AnchorRankComparer : IComparer { + + /// Provides a default instance for the anchor rank comparer + public static AnchorRankComparer Default = new AnchorRankComparer(); + + /// Compares the rank of two anchors against each other + /// Left anchor point that will be compared + /// Right anchor point that will be compared + /// The relation of the two anchor point's ranks to each other + public int Compare(Point left, Point right) { + return 0; + //return Math.Min(left.X, left.Y) - Math.Min(right.X, right.Y); + //return (left.X + left.Y) - (right.X + right.Y); + } + + } + + #endregion + + /// Initializes a new rectangle packer + /// Maximum width of the packing area + /// Maximum height of the packing area + public ArevaloRectanglePacker(int maxPackingAreaWidth, int maxPackingAreaHeight) + : base(maxPackingAreaWidth, maxPackingAreaHeight) { + + this.packedRectangles = new List(); + this.anchors = new List(); + this.anchors.Add(new Point(0, 0)); + + this.actualPackingAreaWidth = 1; + this.actualPackingAreaHeight = 1; + } + + /// Tries to allocate space for a rectangle in the packing area + /// Width of the rectangle to allocate + /// Height of the rectangle to allocate + /// Output parameter receiving the rectangle's placement + /// True if space for the rectangle could be allocated + public override bool TryAllocate( + int rectangleWidth, int rectangleHeight, out Point placement + ) { + + // Try to find an anchor where the rectangle fits in, enlarging the packing + // area and repeating the search recursively until it fits or the + // maximum allowed size is exceeded. + int anchorIndex = selectAnchorRecursive( + rectangleWidth, rectangleHeight, + this.actualPackingAreaWidth, this.actualPackingAreaHeight + ); + + // No anchor could be found at which the rectangle did fit in + if(anchorIndex == -1) { + placement = Point.Zero; + return false; + } + + placement = this.anchors[anchorIndex]; + + // Remove the used anchor and add new anchors at the upper right and lower left + // positions of the new rectangle + this.anchors.RemoveAt(anchorIndex); + this.anchors.Add(new Point(placement.X + rectangleWidth, placement.Y)); + this.anchors.Add(new Point(placement.X, placement.Y + rectangleHeight)); + + this.packedRectangles.Add( + new Rectangle(placement.X, placement.Y, rectangleWidth, rectangleHeight) + ); + + return true; + + } + + /// + /// Searches for a free anchor and enlarges the packing area if none can be found + /// + /// Width of the rectangle to be placed + /// Height of the rectangle to be placed + /// Total width of the packing area + /// Total height of the packing area + /// + /// Index of the anchor the rectangle is to be placed at or -1 if the rectangle + /// does not fit in the packing area anymore + /// + private int selectAnchorRecursive( + int rectangleWidth, int rectangleHeight, + int packingAreaWidth, int packingAreaHeight + ) { + + // Try to locate an anchor point where the rectangle fits in + int freeAnchorIndex = findFirstFreeAnchor( + rectangleWidth, rectangleHeight, packingAreaWidth, packingAreaHeight + ); + + // If a the rectangle fits without resizing packing area (any further in case + // of a recursive call), take over the new packing area size and return the + // anchor at which the rectangle can be placed. + if(freeAnchorIndex != -1) { + this.actualPackingAreaWidth = packingAreaWidth; + this.actualPackingAreaHeight = packingAreaHeight; + + return freeAnchorIndex; + } + + // If we reach this point, the rectangle did not fit in the current packing + // area and our only choice is to try and enlarge the packing area. + + bool canEnlargeWidth = (packingAreaWidth < MaxPackingAreaWidth); + bool canEnlargeHeight = (packingAreaHeight < MaxPackingAreaHeight); + + // Try to enlarge the smaller of the two dimensions first (unless the smaller + // dimension is already at its maximum size) + if( + ( + (packingAreaHeight < packingAreaWidth) || !canEnlargeWidth + ) && canEnlargeHeight + ) { + + // Try to double the height of the packing area + return selectAnchorRecursive( + rectangleWidth, rectangleHeight, + packingAreaWidth, Math.Min(packingAreaHeight * 2, MaxPackingAreaHeight) + ); + + } else if(canEnlargeWidth) { + + // Try to double the width of the packing area + return selectAnchorRecursive( + rectangleWidth, rectangleHeight, + Math.Min(packingAreaWidth * 2, MaxPackingAreaWidth), packingAreaHeight + ); + + } else { + + // Both dimensions are at the maximum sizes and the rectangle still + // didn't fit. We give up! + return -1; + + } + + } + + /// Locates the first free anchor at which the rectangle fits + /// Width of the rectangle to be placed + /// Height of the rectangle to be placed + /// Total width of the packing area + /// Total height of the packing area + /// The index of the first free anchor or -1 if none is found + private int findFirstFreeAnchor( + int rectangleWidth, int rectangleHeight, + int packingAreaWidth, int packingAreaHeight + ) { + Rectangle potentialLocation = new Rectangle( + 0, 0, rectangleWidth, rectangleHeight + ); + + // Walk over all anchors (which are ordered by their distance to the + // upper left corner of the packing area) until one is discovered that + // can house the new rectangle. + for(int index = 0; index < this.anchors.Count; ++index) { + potentialLocation.X = this.anchors[index].X; + potentialLocation.Y = this.anchors[index].Y; + + // See if the rectangle would fit in at this anchor point + if(isFree(ref potentialLocation, packingAreaWidth, packingAreaHeight)) + return index; + } + + // No anchor points were found where the rectangle would fit in + return -1; + } + + /// + /// Determines whether the rectangle can be placed in the packing area + /// at its current location. + /// + /// Rectangle whose position to check + /// Total width of the packing area + /// Total height of the packing area + /// True if the rectangle can be placed at its current position + private bool isFree( + ref Rectangle rectangle, int packingAreaWidth, int packingAreaHeight + ) { + + bool leavesPackingArea = + (rectangle.X < 0) || + (rectangle.Y < 0) || + (rectangle.Right >= packingAreaWidth) || + (rectangle.Bottom >= packingAreaHeight); + + // If the rectangle is partially or completely outside of the packing + // area, it can't be placed at its current location + if(leavesPackingArea) + return false; + + // Brute-force search whether the rectangle touches any of the other + // rectangles already in the packing area + for(int index = 0; index < this.packedRectangles.Count; ++index) { + + if(this.packedRectangles[index].Intersects(rectangle)) + return false; + + } + + // Success! The rectangle is inside the packing area and doesn't overlap + // with any other rectangles that have already been packed. + return true; + + } + + /// Inserts a new anchor point into the anchor list + /// Anchor point that will be inserted + /// + /// This method tries to keep the anchor list ordered by ranking the anchors + /// depending on the distance from the top left corner in the packing area. + /// + private void insertAnchor(ref Point anchor) { + + // Find out where to insert the new anchor based on its rank (which is + // calculated based on the anchor's distance to the top left corner of + // the packing area). + // + // From MSDN on BinarySearch(): + // "If the List does not contain the specified value, the method returns + // a negative integer. You can apply the bitwise complement operation (~) to + // this negative integer to get the index of the first element that is + // larger than the search value." + int insertIndex = this.anchors.BinarySearch(anchor, AnchorRankComparer.Default); + if(insertIndex < 0) + insertIndex = ~insertIndex; + + // Insert the anchor at the index matching its rank + this.anchors.Insert(insertIndex, anchor); + + } + + /// Current width of the packing area + private int actualPackingAreaWidth; + /// Current height of the packing area + private int actualPackingAreaHeight; + /// Rectangles contained in the packing area + private List packedRectangles; + /// Anchoring points where new rectangles can potentially be placed + private List anchors; + + } + +} // namespace Nuclex.Support.Packing diff --git a/Source/Packing/CygonRectanglePacker.Test.cs b/Source/Packing/CygonRectanglePacker.Test.cs new file mode 100644 index 0000000..bcea2ec --- /dev/null +++ b/Source/Packing/CygonRectanglePacker.Test.cs @@ -0,0 +1,47 @@ +#region CPL License +/* +Nuclex Framework +Copyright (C) 2002-2007 Nuclex Development Labs + +This library is free software; you can redistribute it and/or +modify it under the terms of the IBM Common Public License as +published by the IBM Corporation; either version 1.0 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +IBM Common Public License for more details. + +You should have received a copy of the IBM Common Public +License along with this library +*/ +#endregion +using System; +using System.Collections.Generic; + +using Microsoft.Xna.Framework; + +#if UNITTEST + +using NUnit.Framework; + +namespace Nuclex.Support.Packing { + + /// Unit test for the arevalo rectangle packer class + [TestFixture] + public class CygonRectanglePackerTest : RectanglePackerTest { + + /// Tests the packer's efficiency using a deterministic benchmark + [Test] + public void TestSpaceEfficiency() { + float efficiency = calculateEfficiency(new CygonRectanglePacker(70, 70)); + + Assert.GreaterOrEqual(efficiency, 0.75, "Packer achieves 75% efficiency"); + } + + } + +} // namespace Nuclex.Support.Packing + +#endif // UNITTEST diff --git a/Source/Packing/CygonRectanglePacker.cs b/Source/Packing/CygonRectanglePacker.cs new file mode 100644 index 0000000..ffaf234 --- /dev/null +++ b/Source/Packing/CygonRectanglePacker.cs @@ -0,0 +1,92 @@ +#region CPL License +/* +Nuclex Framework +Copyright (C) 2002-2007 Nuclex Development Labs + +This library is free software; you can redistribute it and/or +modify it under the terms of the IBM Common Public License as +published by the IBM Corporation; either version 1.0 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +IBM Common Public License for more details. + +You should have received a copy of the IBM Common Public +License along with this library +*/ +#endregion +using System; +using System.Collections.Generic; + +using Microsoft.Xna.Framework; + +namespace Nuclex.Support.Packing { + + /// Simplified packer for rectangles which don't vary greatly in size + /// + /// This is a highly performant packer that sacrifices space efficiency for + /// low memory usage and runtime performance. It achieves good results with + /// near-uniform sized rectangles but will waste lots of space with rectangles + /// of varying dimensions. + /// + public class CygonRectanglePacker : RectanglePacker { + + /// Initializes a new rectangle packer + /// Maximum width of the packing area + /// Maximum height of the packing area + public CygonRectanglePacker(int maxPackingAreaWidth, int maxPackingAreaHeight) + : base(maxPackingAreaWidth, maxPackingAreaHeight) { } + + /// Tries to allocate space for a rectangle in the packing area + /// Width of the rectangle to allocate + /// Height of the rectangle to allocate + /// Output parameter receiving the rectangle's placement + /// True if space for the rectangle could be allocated + public override bool TryAllocate( + int rectangleWidth, int rectangleHeight, out Point placement + ) { + + // If the rectangle is larger than the packing area in any dimension, + // it will never fit! + if( + (rectangleWidth > MaxPackingAreaWidth) || (rectangleHeight > MaxPackingAreaHeight) + ) { + placement = Point.Zero; + return false; + } + + // Do we have to start a new line ? + if(this.column + rectangleWidth > MaxPackingAreaWidth) { + this.currentLine += this.lineHeight; + this.lineHeight = 0; + this.column = 0; + } + + // If it doesn't fit vertically now, the packing area is considered full + if(this.currentLine + rectangleHeight > MaxPackingAreaHeight) { + placement = Point.Zero; + return false; + } + + // The rectangle appears to fit at the current location + placement = new Point(this.column, this.currentLine); + + this.column += rectangleWidth; // Can be larger than cache width till next run + if(rectangleHeight > this.lineHeight) + this.lineHeight = rectangleHeight; + + return true; + } + + /// Current packing line + private int currentLine; + /// Height of the current packing line + private int lineHeight; + /// Current column in the current packing line + private int column; + + } + +} // namespace Nuclex.Support.Packing diff --git a/Source/Packing/RectanglePacker.Test.cs b/Source/Packing/RectanglePacker.Test.cs new file mode 100644 index 0000000..7fa13b8 --- /dev/null +++ b/Source/Packing/RectanglePacker.Test.cs @@ -0,0 +1,61 @@ +#region CPL License +/* +Nuclex Framework +Copyright (C) 2002-2007 Nuclex Development Labs + +This library is free software; you can redistribute it and/or +modify it under the terms of the IBM Common Public License as +published by the IBM Corporation; either version 1.0 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +IBM Common Public License for more details. + +You should have received a copy of the IBM Common Public +License along with this library +*/ +#endregion +using System; +using System.Collections.Generic; + +using Microsoft.Xna.Framework; + +namespace Nuclex.Support.Packing { + + /// Base class for unit testing the rectangle packers + public abstract class RectanglePackerTest { + + /// Determines the efficiency of a packer with a packing area of 70x70 + /// Packer with a packing area of 70x70 units + /// The efficiency factor of the packer + /// + /// A perfect packer would achieve an efficiency rating of 1.0. This is + /// impossible however since the 24 squares cannot all be packed into + /// the 70x70 square with no overlap (Bitner & Reingold 1975). The closer + /// the efficiency rating is to 1.0, the better, with 0.99 being the + /// mathematically best rating achievable. + /// + public float calculateEfficiency(RectanglePacker packer) { + // If we take a 1x1 square, a 2x2 square, etc. up to a 24x24 square, + // the sum of the areas of these squares is 4900, which is 70². This + // is the only nontrivial sum of consecutive squares starting with + // one which is a perfect square (Watson 1918). + int areaCovered = 0; + + for(int size = 24; size >= 1; --size) { + Point placement; + + if(packer.TryAllocate(size, size, out placement)) + areaCovered += size * size; + } + + return (float)areaCovered / 4900.0f; + } + + + + } + +} // namespace Nuclex.Support.Packing diff --git a/Source/Packing/RectanglePacker.cs b/Source/Packing/RectanglePacker.cs new file mode 100644 index 0000000..825cfc1 --- /dev/null +++ b/Source/Packing/RectanglePacker.cs @@ -0,0 +1,88 @@ +#region CPL License +/* +Nuclex Framework +Copyright (C) 2002-2007 Nuclex Development Labs + +This library is free software; you can redistribute it and/or +modify it under the terms of the IBM Common Public License as +published by the IBM Corporation; either version 1.0 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +IBM Common Public License for more details. + +You should have received a copy of the IBM Common Public +License along with this library +*/ +#endregion +using System; +using System.Collections.Generic; + +using Microsoft.Xna.Framework; + +namespace Nuclex.Support.Packing { + + /// Base class for rectangle packing algorithms + /// + /// + /// By uniting all rectangle packers under this common base class, you can + /// easily switch between different algorithms to find the most efficient or + /// performant one for a given job. + /// + /// + /// An almost exhaustive list of rectangle packers can be found here: + /// http://www.csc.liv.ac.uk/~epa/surveyhtml.html + /// + /// + public abstract class RectanglePacker { + + /// Initializes a new rectangle packer + /// Maximum width of the packing area + /// Maximum height of the packing area + protected RectanglePacker(int maxPackingAreaWidth, int maxPackingAreaHeight) { + this.maxPackingAreaWidth = maxPackingAreaWidth; + this.maxPackingAreaHeight = maxPackingAreaHeight; + } + + /// Allocates space for a rectangle in the packing area + /// Width of the rectangle to allocate + /// Height of the rectangle to allocate + /// The location at which the rectangle has been placed + public virtual Point Allocate(int rectangleWidth, int rectangleHeight) { + Point point; + + if(!TryAllocate(rectangleWidth, rectangleHeight, out point)) + throw new Exception("Rectangle does not fit in packing area"); + + return point; + } + + /// Tries to allocate space for a rectangle in the packing area + /// Width of the rectangle to allocate + /// Height of the rectangle to allocate + /// Output parameter receiving the rectangle's placement + /// True if space for the rectangle could be allocated + public abstract bool TryAllocate( + int rectangleWidth, int rectangleHeight, out Point placement + ); + + /// Maximum width the packing area is allowed to have + protected int MaxPackingAreaWidth { + get { return this.maxPackingAreaWidth; } + } + + /// Maximum height the packing area is allowed to have + protected int MaxPackingAreaHeight { + get { return this.maxPackingAreaHeight; } + } + + /// Maximum allowed width of the packing area + private int maxPackingAreaWidth; + /// Maximum allowed height of the packing area + private int maxPackingAreaHeight; + + } + +} // namespace Nuclex.Support.Packing diff --git a/Source/Scheduling/IAbortable.cs b/Source/Scheduling/IAbortable.cs index 06489c1..c26beb7 100644 --- a/Source/Scheduling/IAbortable.cs +++ b/Source/Scheduling/IAbortable.cs @@ -1,3 +1,22 @@ +#region CPL License +/* +Nuclex Framework +Copyright (C) 2002-2007 Nuclex Development Labs + +This library is free software; you can redistribute it and/or +modify it under the terms of the IBM Common Public License as +published by the IBM Corporation; either version 1.0 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +IBM Common Public License for more details. + +You should have received a copy of the IBM Common Public +License along with this library +*/ +#endregion using System; using System.Collections.Generic; using System.Text; diff --git a/Source/Scheduling/Operation.cs b/Source/Scheduling/Operation.cs index 594a12e..a190771 100644 --- a/Source/Scheduling/Operation.cs +++ b/Source/Scheduling/Operation.cs @@ -1,3 +1,22 @@ +#region CPL License +/* +Nuclex Framework +Copyright (C) 2002-2007 Nuclex Development Labs + +This library is free software; you can redistribute it and/or +modify it under the terms of the IBM Common Public License as +published by the IBM Corporation; either version 1.0 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +IBM Common Public License for more details. + +You should have received a copy of the IBM Common Public +License along with this library +*/ +#endregion using System; using System.Collections.Generic; using System.Text; diff --git a/Source/Scheduling/ThreadedMethodOperation.cs b/Source/Scheduling/ThreadedMethodOperation.cs index d14eb79..9958cb7 100644 --- a/Source/Scheduling/ThreadedMethodOperation.cs +++ b/Source/Scheduling/ThreadedMethodOperation.cs @@ -1,3 +1,22 @@ +#region CPL License +/* +Nuclex Framework +Copyright (C) 2002-2007 Nuclex Development Labs + +This library is free software; you can redistribute it and/or +modify it under the terms of the IBM Common Public License as +published by the IBM Corporation; either version 1.0 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +IBM Common Public License for more details. + +You should have received a copy of the IBM Common Public +License along with this library +*/ +#endregion using System; using System.Collections.Generic; using System.Text;