BlitMask() public static method

Blits a block of a bitmap data from source to destination, using the luminance of the source to determine the alpha of the target. Source must be 24-bit, target must be 32-bit.
public static BlitMask ( BitmapData source, BitmapData target, int srcPx, int srcPy, int srcW, int srcH, int px, int py ) : void
source System.Drawing.Imaging.BitmapData
target System.Drawing.Imaging.BitmapData
srcPx int
srcPy int
srcW int
srcH int
px int
py int
return void
Ejemplo n.º 1
0
        private static List <QBitmap> GenerateBitmapSheetsAndRepack(QFontGlyph[] sourceGlyphs, BitmapData[] sourceBitmaps, int destSheetWidth, int destSheetHeight, out QFontGlyph[] destGlyphs, int destMargin)
        {
            var pages = new List <QBitmap>();

            destGlyphs = new QFontGlyph[sourceGlyphs.Length];

            QBitmap currentPage = null;

            int maxY = 0;

            foreach (var glph in sourceGlyphs)
            {
                maxY = Math.Max(glph.rect.Height, maxY);
            }

            int finalPageIndex          = 0;
            int finalPageRequiredWidth  = 0;
            int finalPageRequiredHeight = 0;

            for (int k = 0; k < 2; k++)
            {
                bool pre = k == 0;  //first iteration is simply to determine the required size of the final page, so that we can crop it in advance

                int xPos       = 0;
                int yPos       = 0;
                int maxYInRow  = 0;
                int totalTries = 0;

                for (int i = 0; i < sourceGlyphs.Length; i++)
                {
                    if (!pre && currentPage == null)
                    {
                        if (finalPageIndex == pages.Count)
                        {
                            int width  = Math.Min(destSheetWidth, finalPageRequiredWidth);
                            int height = Math.Min(destSheetHeight, finalPageRequiredHeight);

                            currentPage = new QBitmap(new Bitmap(width, height, PixelFormat.Format32bppArgb));
                            currentPage.Clear32(255, 255, 255, 0); //clear to white, but totally transparent
                        }
                        else
                        {
                            currentPage = new QBitmap(new Bitmap(destSheetWidth, destSheetHeight, PixelFormat.Format32bppArgb));
                            currentPage.Clear32(255, 255, 255, 0); //clear to white, but totally transparent
                        }
                        pages.Add(currentPage);
                    }

                    totalTries++;

                    if (totalTries > 10 * sourceGlyphs.Length)
                    {
                        throw new Exception("Failed to fit font into texture pages");
                    }

                    var rect = sourceGlyphs[i].rect;

                    if (xPos + rect.Width + 2 * destMargin <= destSheetWidth && yPos + rect.Height + 2 * destMargin <= destSheetHeight)
                    {
                        if (!pre)
                        {
                            //add to page
                            if (sourceBitmaps[sourceGlyphs[i].page].PixelFormat == PixelFormat.Format32bppArgb)
                            {
                                QBitmap.Blit(sourceBitmaps[sourceGlyphs[i].page], currentPage.bitmapData, rect.X, rect.Y, rect.Width, rect.Height, xPos + destMargin, yPos + destMargin);
                            }
                            else
                            {
                                QBitmap.BlitMask(sourceBitmaps[sourceGlyphs[i].page], currentPage.bitmapData, rect.X, rect.Y, rect.Width, rect.Height, xPos + destMargin, yPos + destMargin);
                            }

                            destGlyphs[i] = new QFontGlyph(pages.Count - 1, new Rectangle(xPos + destMargin, yPos + destMargin, rect.Width, rect.Height), sourceGlyphs[i].yOffset, sourceGlyphs[i].character);
                        }
                        else
                        {
                            finalPageRequiredWidth  = Math.Max(finalPageRequiredWidth, xPos + rect.Width + 2 * destMargin);
                            finalPageRequiredHeight = Math.Max(finalPageRequiredHeight, yPos + rect.Height + 2 * destMargin);
                        }

                        xPos     += rect.Width + 2 * destMargin;
                        maxYInRow = Math.Max(maxYInRow, rect.Height);

                        continue;
                    }

                    if (xPos + rect.Width + 2 * destMargin > destSheetWidth)
                    {
                        i--;

                        yPos += maxYInRow + 2 * destMargin;
                        xPos  = 0;

                        if (yPos + maxY + 2 * destMargin > destSheetHeight)
                        {
                            yPos = 0;

                            if (!pre)
                            {
                                currentPage = null;
                            }
                            else
                            {
                                finalPageRequiredWidth  = 0;
                                finalPageRequiredHeight = 0;
                                finalPageIndex++;
                            }
                        }
                        continue;
                    }
                }
            }

            return(pages);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Generates the final bitmap sheet for the font
        /// </summary>
        /// <param name="sourceGlyphs">A collection of <see cref="QFontGlyph"/>s. These are written to the final bitmap</param>
        /// <param name="sourceBitmaps"> The source bitmaps for the font (initial bitmap)</param>
        /// <param name="destSheetWidth">The destination bitmap width</param>
        /// <param name="destSheetHeight">The destination bitmap height</param>
        /// <param name="destGlyphs">A collection of <see cref="QFontGlyph"/>s that are placed on the final bitmap sheet</param>
        /// <param name="destMargin">The margin for the final bitmap sheet</param>
        /// <returns>A collection of <see cref="QBitmap"/>s. These are the final bitmap sheets</returns>
        private static List <QBitmap> GenerateBitmapSheetsAndRepack(QFontGlyph[] sourceGlyphs, BitmapData[] sourceBitmaps, int destSheetWidth, int destSheetHeight, out QFontGlyph[] destGlyphs, int destMargin)
        {
            var pages = new List <QBitmap>();

            destGlyphs = new QFontGlyph[sourceGlyphs.Length];

            QBitmap currentPage = null;

            int maxY = 0;

            foreach (var glph in sourceGlyphs)
            {
                maxY = Math.Max(glph.Rect.Height, maxY);
            }

            int finalPageIndex          = 0;
            int finalPageRequiredWidth  = 0;
            int finalPageRequiredHeight = 0;

            // We loop through the whole process twice. The first time is to determine
            // the size of the final page, so that we can crop it in advance
            for (int k = 0; k < 2; k++)
            {
                // Whether this is the pre-processing step
                bool pre = k == 0;

                int xPos       = 0;
                int yPos       = 0;
                int maxYInRow  = 0;
                int totalTries = 0;

                // Loop through all the glyphs
                for (int i = 0; i < sourceGlyphs.Length; i++)
                {
                    // If this is the second stage and we don't already have a bitmap page, create one
                    if (!pre && currentPage == null)
                    {
                        if (finalPageIndex == pages.Count)
                        {
                            int width  = Math.Min(destSheetWidth, finalPageRequiredWidth);
                            int height = Math.Min(destSheetHeight, finalPageRequiredHeight);

                            currentPage = new QBitmap(new Bitmap(width, height, PixelFormat.Format32bppArgb));
                            currentPage.Clear32(255, 255, 255, 0); //clear to white, but totally transparent
                        }
                        else
                        {
                            currentPage = new QBitmap(new Bitmap(destSheetWidth, destSheetHeight, PixelFormat.Format32bppArgb));
                            currentPage.Clear32(255, 255, 255, 0); //clear to white, but totally transparent
                        }
                        pages.Add(currentPage);
                    }

                    // Keep track of the number of times we've tried to fit the font onto the texture page
                    totalTries++;

                    if (totalTries > 10 * sourceGlyphs.Length)
                    {
                        throw new Exception("Failed to fit font into texture pages");
                    }

                    var rect = sourceGlyphs[i].Rect;

                    // If we can fit the glyph onto the page, place it
                    if (xPos + rect.Width + 2 * destMargin <= destSheetWidth && yPos + rect.Height + 2 * destMargin <= destSheetHeight)
                    {
                        if (!pre)
                        {
                            // Add to page
                            if (sourceBitmaps[sourceGlyphs[i].Page].PixelFormat == PixelFormat.Format32bppArgb)
                            {
                                QBitmap.Blit(sourceBitmaps[sourceGlyphs[i].Page], currentPage.BitmapData, rect.X, rect.Y, rect.Width, rect.Height, xPos + destMargin, yPos + destMargin);
                            }
                            else
                            {
                                QBitmap.BlitMask(sourceBitmaps[sourceGlyphs[i].Page], currentPage.BitmapData, rect.X, rect.Y, rect.Width, rect.Height, xPos + destMargin, yPos + destMargin);
                            }

                            // Add to destination glyph collection
                            destGlyphs[i] = new QFontGlyph(pages.Count - 1, new Rectangle(xPos + destMargin, yPos + destMargin, rect.Width, rect.Height), sourceGlyphs[i].YOffset, sourceGlyphs[i].Character);
                        }
                        else
                        {
                            // Update the final dimensions
                            finalPageRequiredWidth  = Math.Max(finalPageRequiredWidth, xPos + rect.Width + 2 * destMargin);
                            finalPageRequiredHeight = Math.Max(finalPageRequiredHeight, yPos + rect.Height + 2 * destMargin);
                        }

                        // Update the current x position
                        xPos += rect.Width + 2 * destMargin;

                        // Update the maximum row height so far
                        maxYInRow = Math.Max(maxYInRow, rect.Height);

                        continue;
                    }

                    // If we reach this, haven't been able to fit glyph onto row
                    // Move down one row and try again
                    if (xPos + rect.Width + 2 * destMargin > destSheetWidth)
                    {
                        // Retry the current glyph on the next row
                        i--;

                        // Change coordinates to next row
                        yPos += maxYInRow + 2 * destMargin;
                        xPos  = 0;

                        // Is the next row off the bitmap sheet?
                        if (yPos + maxY + 2 * destMargin > destSheetHeight)
                        {
                            // Reset y position
                            yPos = 0;

                            if (!pre)
                            {
                                // If this is not the second stage, reset the currentPage
                                // This will create a new one on next loop
                                currentPage = null;
                            }
                            else
                            {
                                // If this is the pre-processing stage, update
                                // the finalPageIndex. Reset width and height
                                // since we clearly need one full page and extra
                                finalPageRequiredWidth  = 0;
                                finalPageRequiredHeight = 0;
                                finalPageIndex++;
                            }
                        }
                    }
                }
            }

            return(pages);
        }