/// <summary> /// Produces a mapping to a sprite that has given maximum dimensions. /// If the mapping can not be done inside those dimensions, returns null. /// </summary> /// <param name="images"> /// List of image infos. /// /// This method will not sort this list. /// All images in this collection will be used, regardless of size. /// </param> /// <param name="maxWidth"> /// The sprite won't be wider than this. /// </param> /// <param name="maxHeight"> /// The generated sprite won't be higher than this. /// </param> /// <param name="canvasStats"> /// The statistics produced by the canvas. These numbers are since the last call to its SetCanvasDimensions method. /// </param> /// <param name="lowestFreeHeightDeficitTallestRightFlushedImage"> /// The lowest free height deficit for the images up to and including the tallest rectangle whose right hand border sits furthest to the right /// of all images. /// /// This is the minimum amount by which the height of the canvas needs to be increased to accommodate that rectangle. /// if the width of the canvas is decreased to one less than the width now taken by images. /// /// Note that providing the additional height might get some other (not right flushed) image to be placed higher, thereby /// making room for the flushed right image. /// /// This will be set to Int32.MaxValue if there was never any free height deficit. /// </param> /// <returns> /// The generated sprite. /// /// null if not all the images could be placed within the size limitations. /// </returns> protected virtual Atlas MappingRestrictedBox( IOrderedEnumerable <ImageInfo> images, int maxWidth, int maxHeight, CanvasStats canvasStats, out int lowestFreeHeightDeficitTallestRightFlushedImage) { lowestFreeHeightDeficitTallestRightFlushedImage = 0; _canvas.SetCanvasDimensions(maxWidth, maxHeight); Atlas spriteInfo = new Atlas(); int heightHighestRightFlushedImage = 0; int furthestRightEdge = 0; foreach (ImageInfo image in images) { int xOffset; int yOffset; int lowestFreeHeightDeficit; if (!_canvas.AddRectangle( image.Width, image.Height, out xOffset, out yOffset, out lowestFreeHeightDeficit)) { // Not enough room on the canvas to place the rectangle spriteInfo = null; break; } MappedImageInfo imageLocation = new MappedImageInfo(xOffset, yOffset, image); spriteInfo.AddMappedImage(imageLocation); // Update the lowestFreeHeightDeficitTallestRightFlushedImage int rightEdge = image.Width + xOffset; if ((rightEdge > furthestRightEdge) || ((rightEdge == furthestRightEdge) && (image.Height > heightHighestRightFlushedImage))) { // The image is flushed the furthest right of all images, or it is flushed equally far to the right // as the furthest flushed image but it is taller. lowestFreeHeightDeficitTallestRightFlushedImage = lowestFreeHeightDeficit; heightHighestRightFlushedImage = image.Height; furthestRightEdge = rightEdge; } } _canvas.GetStatistics(canvasStats); return(spriteInfo); }
/// <summary> /// Adds a Rectangle to the SpriteInfo, and updates the width and height of the SpriteInfo. /// </summary> /// <param name="imageLocation"></param> public void AddMappedImage(MappedImageInfo imageLocation) { _mappedImages.Add(imageLocation); ImageInfo newImage = imageLocation.ImageInfo; int highestY = imageLocation.Y + newImage.Height; int rightMostX = imageLocation.X + newImage.Width; if (_height < highestY) { _height = highestY; } if (_width < rightMostX) { _width = rightMostX; } }