Beispiel #1
0
 public AtlasNode()
 {
     left        = null;
     right       = null;
     this.bounds = Rectangle.Empty;
     filled      = false;
 }
Beispiel #2
0
        public AtlasNode Insert(Rectangle sBounds)
        {
            if (this.left != null)
            {
                AtlasNode newNode = this.left.Insert(sBounds);
                if (newNode != null)
                {
                    return(newNode);
                }

                return(this.right.Insert(sBounds));
            }
            else
            {
                if (this.filled) // occupied!
                {
                    return(null);
                }
                if (this.bounds.Width < sBounds.Width || this.bounds.Height < sBounds.Height)  // bounds are too small for this image
                {
                    return(null);
                }
                if (this.bounds.Width == sBounds.Width && this.bounds.Height == sBounds.Height)
                {
                    // fits just right!
                    filled = true;
                    return(this);
                }

                //otherwise split and traverse further...
                this.left  = new AtlasNode();
                this.right = new AtlasNode();

                // decide which way to split
                int dw = this.bounds.Width - sBounds.Width;
                int dh = this.bounds.Height - sBounds.Height;
                if (dw > dh)
                {
                    this.left.bounds  = new Rectangle(this.bounds.X, this.bounds.Y, sBounds.Width, this.bounds.Height);
                    this.right.bounds = new Rectangle(this.bounds.X + sBounds.Width, this.bounds.Y, this.bounds.Width - sBounds.Width, this.bounds.Height);
                }
                else
                {
                    this.left.bounds  = new Rectangle(this.bounds.X, this.bounds.Y, this.bounds.Width, sBounds.Height);
                    this.right.bounds = new Rectangle(this.bounds.X, this.bounds.Y + sBounds.Height, this.bounds.Width, this.bounds.Height - sBounds.Height);
                }

                return(this.left.Insert(sBounds));
            }
        }
Beispiel #3
0
        internal void Generate(Face face, int size, int dpi)
        {
            face.SetCharSize(0, new Fixed26Dot6(size), 0, (uint)dpi);
            Name = face.FamilyName;
            face.LoadChar((uint)32, (LoadFlags.Render | LoadFlags.Monochrome | LoadFlags.Pedantic), LoadTarget.Normal);
            SpaceWidth = face.Glyph.Metrics.HorizontalAdvance.ToInt32();
            LineHeight = face.Height >> 6;
            Kerning    = face.HasKerning;
            Size       = size;
            Ascent     = face.Ascender >> 6;
            Descent    = face.Descender >> 6;
            Glyphs     = new List <RFontGlyph>();


            for (int i = 33; i < 126; i++)
            {
                uint charIndex = face.GetCharIndex((uint)i);
                face.LoadGlyph(charIndex, (LoadFlags.Render | LoadFlags.Color | LoadFlags.Pedantic | LoadFlags.CropBitmap), LoadTarget.Normal);
                if (face.Glyph.Bitmap.PixelMode == PixelMode.None)
                {
                    continue;
                }
                RFontGlyph glyph = new RFontGlyph();

                glyph.bitmap    = face.Glyph.Bitmap.ToGdipBitmap(Color.White);
                glyph.Bounds    = new Reactor.Math.Rectangle(0, 0, glyph.bitmap.Width, glyph.bitmap.Height);
                glyph.CharIndex = i;
                glyph.Offset    = new Vector2(face.Glyph.Metrics.HorizontalBearingX.ToInt32(), face.Glyph.Metrics.HorizontalBearingY.ToInt32());
                glyph.Advance   = face.Glyph.Advance.X.ToInt32();

                Glyphs.Add(glyph);
            }
            Glyphs.Sort(new FontGlyphSizeSorter());
            var    missed = -1;
            var    width  = 16;
            Bitmap b      = new Bitmap(1, 1);

            while (missed != 0)
            {
                missed = 0;
                AtlasNode root = new AtlasNode();
                root.bounds = new Reactor.Math.Rectangle(0, 0, width, width);
                b.Dispose();
                b = new Bitmap(width, width);
                Graphics g = Graphics.FromImage(b);
                g.Clear(Color.Transparent);
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                for (var i = 0; i < Glyphs.Count; i++)
                {
                    RFontGlyph glyph  = Glyphs[i];
                    AtlasNode  result = root.Insert(glyph.Bounds);

                    if (result != null)
                    {
                        Reactor.Math.Rectangle bounds = result.bounds;
                        //g.DrawImageUnscaledAndClipped(glyph.bitmap, bounds);
                        g.DrawImage(glyph.bitmap, bounds);
                        glyph.Bounds    = bounds;
                        glyph.UVBounds  = new Vector4((float)bounds.X, (float)bounds.Y, (float)bounds.Width, (float)bounds.Height);
                        glyph.UVBounds /= (float)width;
                        Glyphs[i]       = glyph;
                    }
                    else
                    {
                        missed += 1;
                        break;
                    }
                }
                width += 16;
            }
            Texture = new RTexture2D();
            Texture.LoadFromBitmap(b);
            Texture.SetTextureMagFilter(RTextureMagFilter.Linear);
            Texture.SetTextureMinFilter(RTextureMinFilter.LinearMipmapLinear);
            Texture.SetTextureWrapMode(RTextureWrapMode.ClampToBorder, RTextureWrapMode.ClampToBorder);
            REngine.CheckGLError();
        }
Beispiel #4
0
        public void BuildAtlas(List <RTextureSprite> textures)
        {
            REngine.CheckGLError();
            textures.Sort(new RTextureSizeSorter());
            textures.Reverse();
            Rectangle largest = textures[0].Bounds;
            //int cellSize = System.Math.Max(largest.Width, largest.Height);
            //double sqr = System.Math.Sqrt((double)textures.Count);
            //int remainder = ((int)(sqr*100) % 100);

            /*Rectangle bounds = new Rectangle();
             * foreach(RTextureSprite sprite in textures)
             * {
             *  bounds = Rectangle.Union(bounds, sprite.Bounds);
             * }
             * RTextureSprite previous = null;
             * foreach(RTextureSprite sprite in textures)
             * {
             *  if(previous == null){
             *      sprite.Offset.X = 0;
             *      previous = sprite;
             *  }
             *  else {
             *      sprite.Offset.X = previous.Offset.X + previous.Bounds.Width;
             *      sprite.Bounds.Offset(sprite.Offset);
             *      previous = sprite;
             *  }
             *
             *  bounds = Rectangle.Union(bounds, previous.Bounds);
             * }
             * while(!this.isPowerOfTwo((uint)bounds.Height))
             *  bounds.Height += 1;
             * while(!this.isPowerOfTwo((uint)bounds.Width))
             *  bounds.Width += 1;
             */
            AtlasNode root = new AtlasNode();

            root.bounds = new Rectangle(0, 0, 512, 512);
            Create(512, 512, textures[0].GetPixelFormat(), RSurfaceFormat.Color);
            uint index     = 0;
            int  unclaimed = 0;

            REngine.CheckGLError();
            foreach (RTextureSprite sprite in textures)
            {
                try{
                    AtlasNode node = root.Insert(sprite.Bounds);
                    if (node != null)
                    {
                        RLog.Info(node.ToString());
                        sprite.ScaledBounds = node.bounds;

                        //Pack(sprite, sprite.GetPixelFormat());
                    }
                    else
                    {
                        unclaimed++;
                    }
                }
                catch (Exception e)
                {
                    RLog.Error(e);
                }
                index++;
            }
        }