Beispiel #1
0
            private unsafe DynamicAtlas <Color> .Reservation Upload(FTBitmap bitmap)
            {
                bool foundRoom = false;

                DynamicAtlas <Color> .Reservation result = default(DynamicAtlas <Color> .Reservation);

                int width = bitmap.Width, rows = bitmap.Rows, pitch = bitmap.Pitch;

                var widthW  = width + (Font.GlyphMargin * 2);
                var heightW = rows + (Font.GlyphMargin * 2);

                foreach (var atlas in Atlases)
                {
                    if (atlas.TryReserve(widthW, heightW, out result))
                    {
                        foundRoom = true;
                        break;
                    }
                }

                var surfaceFormat = Font.sRGB ? Evil.TextureUtils.ColorSrgbEXT : SurfaceFormat.Color;

                if (!foundRoom)
                {
                    var isFirstAtlas = (Atlases.Count == 0) && (_SizePoints < SmallFirstAtlasThreshold);
                    var newAtlas     = new DynamicAtlas <Color>(
                        Font.RenderCoordinator, isFirstAtlas ? FirstAtlasWidth : AtlasWidth, isFirstAtlas ? FirstAtlasHeight : AtlasHeight,
                        surfaceFormat, 4, Font.MipMapping ? PickMipGenerator(Font) : null, tag: $"{Font.Face.FamilyName} {SizePoints}pt"
                        );
                    Atlases.Add(newAtlas);
                    if (!newAtlas.TryReserve(widthW, heightW, out result))
                    {
                        throw new InvalidOperationException("Character too large for atlas");
                    }
                }

                var pSrc = (byte *)bitmap.Buffer;

                fixed(Color *pPixels = result.Atlas.Pixels)
                {
                    var pDest = (byte *)pPixels;

                    switch (bitmap.PixelMode)
                    {
                    case PixelMode.Gray:
                        var table = Font.GammaRamp?.GammaTable;
                        var srgb  = (surfaceFormat != SurfaceFormat.Color);

                        for (var y = 0; y < rows; y++)
                        {
                            var rowOffset = result.Atlas.Width * (y + result.Y + Font.GlyphMargin) + (result.X + Font.GlyphMargin);
                            var pDestRow  = pDest + (rowOffset * 4);
                            int yPitch    = y * pitch;

                            if (table == null)
                            {
                                for (var x = 0; x < width; x++)
                                {
                                    var a = pSrc[x + yPitch];
                                    var g = srgb ? ColorSpace.LinearByteTosRGBByteTable[a] : a;

                                    pDestRow[3] = a;
                                    pDestRow[2] = pDestRow[1] = pDestRow[0] = g;
                                    pDestRow   += 4;
                                }
                            }
                            else
                            {
                                for (var x = 0; x < width; x++)
                                {
                                    var a = table[pSrc[x + yPitch]];
                                    var g = srgb ? ColorSpace.LinearByteTosRGBByteTable[a] : a;

                                    pDestRow[3] = a;
                                    pDestRow[2] = pDestRow[1] = pDestRow[0] = g;
                                    pDestRow   += 4;
                                }
                            }
                        }
                        break;

                    case PixelMode.Mono:
                        for (var y = 0; y < rows; y++)
                        {
                            var rowOffset = result.Atlas.Width * (y + result.Y + Font.GlyphMargin) + (result.X + Font.GlyphMargin);
                            var pDestRow  = pDest + (rowOffset * 4);
                            int yPitch    = y * pitch;

                            for (int x = 0; x < pitch; x++, pDestRow += (8 * 4))
                            {
                                var bits = pSrc[x + yPitch];

                                for (int i = 0; i < 8; i++)
                                {
                                    int  iy   = 7 - i;
                                    byte g    = ((bits & (1 << iy)) != 0) ? (byte)255 : (byte)0;
                                    var  pElt = pDestRow + (i * 4);
                                    pElt[3] = pElt[2] = pElt[1] = pElt[0] = g;
                                }
                            }
                        }
                        break;

                    default:
                        throw new NotImplementedException("Unsupported pixel mode: " + bitmap.PixelMode);
                    }
                }

                result.Invalidate();
                return(result);
            }
Beispiel #2
0
            private unsafe DynamicAtlas <Color> .Reservation Upload(FTBitmap bitmap)
            {
                bool foundRoom = false;

                DynamicAtlas <Color> .Reservation result = default(DynamicAtlas <Color> .Reservation);

                int width = bitmap.Width, rows = bitmap.Rows, pitch = bitmap.Pitch;

                var widthW  = width + (Font.GlyphMargin * 2);
                var heightW = rows + (Font.GlyphMargin * 2);

                foreach (var atlas in Atlases)
                {
                    if (atlas.TryReserve(widthW, heightW, out result))
                    {
                        foundRoom = true;
                        break;
                    }
                }

                if (!foundRoom)
                {
                    var newAtlas = new DynamicAtlas <Color>(
                        Font.RenderCoordinator, AtlasWidth, AtlasHeight,
                        SurfaceFormat.Color, 4, Font.MipMapping ? PickMipGenerator(Font) : null
                        );
                    Atlases.Add(newAtlas);
                    if (!newAtlas.TryReserve(widthW, heightW, out result))
                    {
                        throw new InvalidOperationException("Character too large for atlas");
                    }
                }

                var pSrc = (byte *)bitmap.Buffer;

                fixed(Color *pPixels = result.Atlas.Pixels)
                {
                    var pDest = (byte *)pPixels;

                    switch (bitmap.PixelMode)
                    {
                    case PixelMode.Gray:
                        var table = Font.GammaTable;

                        for (var y = 0; y < rows; y++)
                        {
                            var rowOffset = result.Atlas.Width * (y + result.Y + Font.GlyphMargin) + (result.X + Font.GlyphMargin);
                            var pDestRow  = pDest + (rowOffset * 4);
                            int yPitch    = y * pitch;

                            for (var x = 0; x < width; x++)
                            {
                                var g = table[pSrc[x + yPitch]];
                                pDestRow[3] = pDestRow[2] = pDestRow[1] = pDestRow[0] = g;
                                pDestRow   += 4;
                            }
                        }
                        break;

                    case PixelMode.Mono:
                        for (var y = 0; y < rows; y++)
                        {
                            var rowOffset = result.Atlas.Width * (y + result.Y + Font.GlyphMargin) + (result.X + Font.GlyphMargin);
                            var pDestRow  = pDest + (rowOffset * 4);
                            int yPitch    = y * pitch;

                            for (int x = 0; x < pitch; x++, pDestRow += (8 * 4))
                            {
                                var bits = pSrc[x + yPitch];

                                for (int i = 0; i < 8; i++)
                                {
                                    int  iy   = 7 - i;
                                    byte g    = ((bits & (1 << iy)) != 0) ? (byte)255 : (byte)0;
                                    var  pElt = pDestRow + (i * 4);
                                    pElt[3] = pElt[2] = pElt[1] = pElt[0] = g;
                                }
                            }
                        }
                        break;

                    default:
                        throw new NotImplementedException("Unsupported pixel mode: " + bitmap.PixelMode);
                    }
                }

                return(result);
            }