FromRawStream() public static method

Loads raw image data from memory.
public static FromRawStream ( Stream stream, int width, int height, PixelFormat format ) : Image
stream Stream Stream containing the raw image data.
width int Width of this image data (in pixels).
height int Height of this image data (in pixels).
format PixelFormat Pixel format used in this texture.
return Image
Example #1
0
        public void LoadResource(Resource res)
        {
            // TODO : Revisit after checking current Imaging support in Mono.
#if !(XBOX || XBOX360 || ANDROID || IPHONE || SILVERLIGHT)
            var current = Environment.CurrentDirectory;

            var ftLibrary = IntPtr.Zero;
            if (FT.FT_Init_FreeType(out ftLibrary) != 0)
            {
                throw new AxiomException("Could not init FreeType library!");
            }

            var face = IntPtr.Zero;
            // Add a gap between letters vert and horz
            // prevents nasty artefacts when letters are too close together
            var char_space = 5;

            // Locate ttf file, load it pre-buffered into memory by wrapping the
            // original DataStream in a MemoryDataStream
            var fileStream = ResourceGroupManager.Instance.OpenResource(Source, Group, true, this);

            var ttfchunk = new byte[fileStream.Length];
            fileStream.Read(ttfchunk, 0, ttfchunk.Length);

            //Load font
            if (FT.FT_New_Memory_Face(ftLibrary, ttfchunk, ttfchunk.Length, 0, out face) != 0)
            {
                throw new AxiomException("Could not open font face!");
            }

            // Convert our point size to freetype 26.6 fixed point format
            var ftSize = this._ttfSize * (1 << 6);

            if (FT.FT_Set_Char_Size(face, ftSize, 0, (uint)this._ttfResolution, (uint)this._ttfResolution) != 0)
            {
                throw new AxiomException("Could not set char size!");
            }

            int max_height = 0, max_width = 0;

            // Backwards compatibility - if codepoints not supplied, assume 33-166
            if (this.codePointRange.Count == 0)
            {
                this.codePointRange.Add(new KeyValuePair <int, int>(33, 166));
            }

            // Calculate maximum width, height and bearing
            var glyphCount = 0;
            foreach (var r in this.codePointRange)
            {
                var range = r;
                for (var cp = range.Key; cp <= range.Value; ++cp, ++glyphCount)
                {
                    FT.FT_Load_Char(face, (uint)cp, 4); //4 == FT_LOAD_RENDER

                    var rec  = face.PtrToStructure <FT_FaceRec>();
                    var glyp = rec.glyph.PtrToStructure <FT_GlyphSlotRec>();

                    if ((2 * (glyp.bitmap.rows << 6) - glyp.metrics.horiBearingY) > max_height)
                    {
                        max_height = (2 * (glyp.bitmap.rows << 6) - glyp.metrics.horiBearingY);
                    }
                    if (glyp.metrics.horiBearingY > this.maxBearingY)
                    {
                        this.maxBearingY = glyp.metrics.horiBearingY;
                    }

                    if ((glyp.advance.x >> 6) + (glyp.metrics.horiBearingX >> 6) > max_width)
                    {
                        max_width = (glyp.advance.x >> 6) + (glyp.metrics.horiBearingX >> 6);
                    }
                }
            }

            // Now work out how big our texture needs to be
            var rawSize = (max_width + char_space) * ((max_height >> 6) + char_space) * glyphCount;

            var tex_side = (int)System.Math.Sqrt((Real)rawSize);

            // just in case the size might chop a glyph in half, add another glyph width/height
            tex_side += System.Math.Max(max_width, (max_height >> 6));
            // Now round up to nearest power of two
            var roundUpSize = (int)Bitwise.FirstPO2From((uint)tex_side);
            // Would we benefit from using a non-square texture (2X width)
            int finalWidth = 0, finalHeight = 0;

            if (roundUpSize * roundUpSize * 0.5 >= rawSize)
            {
                finalHeight = (int)(roundUpSize * 0.5);
            }
            else
            {
                finalHeight = roundUpSize;
            }

            finalWidth = roundUpSize;

            var textureAspec = (Real)finalWidth / (Real)finalHeight;
            var pixelBytes   = 2;
            var dataWidth    = finalWidth * pixelBytes;
            var dataSize     = finalWidth * finalHeight * pixelBytes;

            LogManager.Instance.Write("Font {0} using texture size {1}x{2}", _name, finalWidth.ToString(),
                                      finalHeight.ToString());

            var imageData = new byte[dataSize];
            // Reset content (White, transparent)
            for (var i = 0; i < dataSize; i += pixelBytes)
            {
                imageData[i + 0] = 0xff; // luminance
                imageData[i + 1] = 0x00; // alpha
            }

            int l = 0, m = 0;
            foreach (var r in this.codePointRange)
            {
                var range = r;
                for (var cp = range.Key; cp <= range.Value; ++cp)
                {
                    // Load & render glyph
                    var ftResult = FT.FT_Load_Char(face, (uint)cp, 4); //4 == FT_LOAD_RENDER
                    if (ftResult != 0)
                    {
                        // problem loading this glyph, continue
                        LogManager.Instance.Write("Info: cannot load character '{0}' in font {1}.",
#if (SILVERLIGHT || WINDOWS_PHONE)
                                                  cp,
#else
                                                  char.ConvertFromUtf32(cp),
#endif
                                                  _name);

                        continue;
                    }

                    var rec     = face.PtrToStructure <FT_FaceRec>();
                    var glyp    = rec.glyph.PtrToStructure <FT_GlyphSlotRec>();
                    var advance = glyp.advance.x >> 6;

                    if (glyp.bitmap.buffer == IntPtr.Zero)
                    {
                        LogManager.Instance.Write("Info: Freetype returned null for character '{0} in font {1}.",
#if (SILVERLIGHT || WINDOWS_PHONE)
                                                  cp,
#else
                                                  char.ConvertFromUtf32(cp),
#endif
                                                  _name);
                        continue;
                    }

#if !AXIOM_SAFE_ONLY
                    unsafe
#endif
                    {
                        var buffer          = BufferBase.Wrap(glyp.bitmap.buffer, glyp.bitmap.rows * glyp.bitmap.pitch);
                        var bufferPtr       = buffer.ToBytePointer();
                        var idx             = 0;
                        var imageDataBuffer = BufferBase.Wrap(imageData);
                        var imageDataPtr    = imageDataBuffer.ToBytePointer();
                        var y_bearing       = ((this.maxBearingY >> 6) - (glyp.metrics.horiBearingY >> 6));
                        var x_bearing       = glyp.metrics.horiBearingX >> 6;

                        for (var j = 0; j < glyp.bitmap.rows; j++)
                        {
                            var row   = j + m + y_bearing;
                            var pDest = (row * dataWidth) + (l + x_bearing) * pixelBytes;
                            for (var k = 0; k < glyp.bitmap.width; k++)
                            {
                                if (AntialiasColor)
                                {
                                    // Use the same greyscale pixel for all components RGBA
                                    imageDataPtr[pDest++] = bufferPtr[idx];
                                }
                                else
                                {
                                    // Always white whether 'on' or 'off' pixel, since alpha
                                    // will turn off
                                    imageDataPtr[pDest++] = (byte)0xFF;
                                }
                                // Always use the greyscale value for alpha
                                imageDataPtr[pDest++] = bufferPtr[idx++];
                            } //end k
                        }     //end j

                        buffer.Dispose();
                        imageDataBuffer.Dispose();

                        SetGlyphTexCoords((uint)cp, (Real)l / (Real)finalWidth,                 //u1
                                          (Real)m / (Real)finalHeight,                          //v1
                                          (Real)(l + (glyp.advance.x >> 6)) / (Real)finalWidth, //u2
                                          (m + (max_height >> 6)) / (Real)finalHeight,          //v2
                                          textureAspec);

                        // Advance a column
                        l += (advance + char_space);

                        // If at end of row
                        if (finalWidth - 1 < l + (advance))
                        {
                            m += (max_height >> 6) + char_space;
                            l  = 0;
                        }
                    }
                }
            } //end foreach

            var memStream = new MemoryStream(imageData);
            var img       = Image.FromRawStream(memStream, finalWidth, finalHeight, PixelFormat.BYTE_LA);

            var tex = (Texture)res;
            // Call internal _loadImages, not loadImage since that's external and
            // will determine load status etc again, and this is a manual loader inside load()
            var images = new Image[1];
            images[0] = img;
            tex.LoadImages(images);
            FT.FT_Done_FreeType(ftLibrary);

            //img.Save( "C:" + Path.DirectorySeparatorChar + Name + ".png" );
            //FileStream file = new FileStream( "C:" + Path.DirectorySeparatorChar + Name + ".fontdef", FileMode.Create );
            //StreamWriter str = new StreamWriter( file );
            //str.WriteLine( Name );
            //str.WriteLine( "{" );
            //str.WriteLine( "\ttype\timage" );
            //str.WriteLine( "\tsource\t{0}.png\n", Name );

            //for ( uint i = 0; i < (uint)( END_CHAR - START_CHAR ); i++ )
            //{
            //    char c = (char)( i + START_CHAR );
            //    str.WriteLine( "\tglyph\t{0}\t{1:F6}\t{2:F6}\t{3:F6}\t{4:F6}", c, Glyphs[ c ].uvRect.Top, Glyphs[ c ].uvRect.Left, Glyphs[ c ].uvRect.Bottom, Glyphs[ c ].uvRect.Right );
            //}
            //str.WriteLine( "}" );
            //str.Close();
            //file.Close();
#endif
        }