Class representing an image file.
The Image class usually holds uncompressed image data and is the only object that can be loaded in a texture. Image objects handle image data decoding themselves by the means of locating the correct ICodec implementation for each data type.
Inheritance: DisposableObject
示例#1
0
 /// <summary>
 /// Load an alternate image into the scene for the given texture name.
 /// Future movies that play should look for this texture and unload it
 /// if it exists.
 /// </summary>
 /// <param name="name">
 /// The name of the texture to replace.
 /// </param>
 /// <param name="file">
 /// The name of the file in the Textures directory to display.
 /// </param>
 /// <returns>
 /// True if the texture was created, false if it wasn't.
 /// </returns>
 public static bool ShowAltImage(string name, string file)
 {
     Axiom.Core.Texture texture = TextureManager.Instance.GetByName(name);
     if (texture != null)
     {
         if (texture.IsLoaded)
         {
             texture.Unload();
         }
         TextureManager.Instance.Remove(name);
     }
     try
     {
         Axiom.Media.Image img = Axiom.Media.Image.FromFile(file);
         if (img != null)
         {
             texture = TextureManager.Instance.LoadImage(name, img);
             return(texture != null);
         }
     }
     catch (Exception e)
     {
         LogUtil.ExceptionLog.ErrorFormat("Exception: {0}", e);
         return(false);
     }
     return(false);
 }
        public EditableImage(string name, int width, int height, PixelFormat format, ColorEx color, int numMipMaps, bool isAlpha)
        {
            this.width = width;
            this.height = height;
            this.format = format;
            this.textureName = name;
            this.numMipMaps = numMipMaps;
            this.isAlpha = isAlpha;

            bytesPerPixel = PixelUtil.GetNumElemBytes(format);
            stride = bytesPerPixel * width;

            pixelData = new byte[width * height * bytesPerPixel];

            // this will pin the buffer
            image = Image.FromDynamicImage(pixelData, width, height, format);

            Fill(0, 0, width, height, color);
        }
示例#3
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
		}
示例#4
0
文件: Font.cs 项目: axiom3d/axiom
        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
        }
示例#5
0
文件: Font.cs 项目: WolfgangSt/axiom
		public void LoadResource( Resource resource )
		{
			// TODO : Revisit after checking current Imaging support in Mono.
			
#if !( XBOX || XBOX360 || ANDROID || IPHONE)
			string current = Environment.CurrentDirectory;

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

			IntPtr face = IntPtr.Zero;
			int char_space = 5;

			Stream fileStream = ResourceGroupManager.Instance.OpenResource( Source, Group );

			byte[] data = new byte[ fileStream.Length ];
			fileStream.Read( data, 0, data.Length );
			//Load font
			int success = FT.FT_New_Memory_Face( ftLibrary, data, data.Length, 0, out face );
			if ( success != 0 )
			{
				throw new AxiomException( "Could not open font face!" );
			}

			// Convert our point size to freetype 26.6 fixed point format
			int ttfSize = _ttfSize * ( 1 << 6 );

			success = FT.FT_Set_Char_Size( face, ttfSize, 0, (uint)_ttfResolution, (uint)_ttfResolution );
			if ( success != 0 )
			{
				{
					throw new AxiomException( "Could not set char size!" );
				}
			}
			int max_height = 0, max_width = 0;
			List<KeyValuePair<int, int>> codePointRange = new List<KeyValuePair<int, int>>();
			// Backwards compatibility - if codepoints not supplied, assume 33-166
			if ( codePointRange.Count == 0 )
			{
				codePointRange.Add( new KeyValuePair<int, int>( 33, 166 ) );
			}

			int glyphCount = 0;
			foreach ( KeyValuePair<int, int> r in codePointRange )
			{
				KeyValuePair<int, int> range = r;
				for ( int cp = range.Key; cp <= range.Value; ++cp, ++glyphCount )
				{
					FT.FT_Load_Char( face, (uint)cp, 4 ); //4 == FT_LOAD_RENDER
					FT_FaceRec rec = (FT_FaceRec)Marshal.PtrToStructure( face, typeof( FT_FaceRec ) );
					FT_GlyphSlotRec glyp = (FT_GlyphSlotRec)Marshal.PtrToStructure( rec.glyph, typeof( 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 > maxBearingY )
						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
			int rawSize = ( max_width + char_space ) *
				( ( max_height >> 6 ) + char_space ) * glyphCount;

			int 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
			int 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;

			Real textureAspec = (Real)finalWidth / (Real)finalHeight;
			int pixelBytes = 2;
			int dataWidth = finalWidth * pixelBytes;
			int data_size = finalWidth * finalHeight * pixelBytes;

			LogManager.Instance.Write( "Font " + _name + " using texture size " + finalWidth.ToString() + "x" + finalHeight.ToString() );

			byte[] imageData = new byte[ data_size ];
			for ( int i = 0; i < data_size; i += pixelBytes )
			{
				imageData[ i + 0 ] = 0xff;// luminance
				imageData[ i + 1 ] = 0x00;// alpha
			}


			int l = 0, m = 0;
			foreach ( KeyValuePair<int, int> r in codePointRange )
			{
				KeyValuePair<int, int> range = r;
				for ( int cp = range.Key; cp <= range.Value; ++cp )
				{
					int result = FT.FT_Load_Char( face, (uint)cp, 4 );//4 == FT_LOAD_RENDER
					if ( result != 0 )
					{
						// problem loading this glyph, continue
						LogManager.Instance.Write( "Info: cannot load character '" + char.ConvertFromUtf32( cp ) + "' in font " + _name + "." );
						continue;
					}

					FT_FaceRec rec = (FT_FaceRec)Marshal.PtrToStructure( face, typeof( FT_FaceRec ) );
					FT_GlyphSlotRec glyp = (FT_GlyphSlotRec)Marshal.PtrToStructure( rec.glyph, typeof( FT_GlyphSlotRec ) );
					int advance = glyp.advance.x >> 6;
					unsafe
					{
						if ( glyp.bitmap.buffer == IntPtr.Zero )
						{
							LogManager.Instance.Write( "Info: Freetype returned null for character '" + char.ConvertFromUtf32( cp ) + "' in font " + _name + "." );
							continue;
						}
						byte* buffer = (byte*)glyp.bitmap.buffer;
						byte* imageDataPtr = (byte*)Memory.PinObject( imageData );
						int y_bearing = ( ( maxBearingY >> 6 ) - ( glyp.metrics.horiBearingY >> 6 ) );
						int x_bearing = glyp.metrics.horiBearingX >> 6;

						for ( int j = 0; j < glyp.bitmap.rows; j++ )
						{
							int row = j + m + y_bearing;
							byte* pDest = &imageDataPtr[ ( row * dataWidth ) + ( l + x_bearing ) * pixelBytes ];
							for ( int k = 0; k < glyp.bitmap.width; k++ )
							{
								if ( AntialiasColor )
								{
									// Use the same greyscale pixel for all components RGBA
									*pDest++ = *buffer;
								}
								else
								{
									// Always white whether 'on' or 'off' pixel, since alpha
									// will turn off
									*pDest++ = (byte)0xFF;
								}
								// Always use the greyscale value for alpha
								*pDest++ = *buffer++;
							}//end k
						}//end j
						//
						this.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, textureAspec ); //v2
						//    textureAspec );
						//SetGlyphTexCoords( c, u1, v1, u2, v2 );
						//Glyphs.Add( new KeyValuePair<CodePoint, GlyphInfo>( (uint)cp,
						//    new GlyphInfo( (uint)cp,
						//        new UVRect(
						//            (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

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

			Texture tex = (Texture)resource;
			Image[] images = new Image[ 1 ];
			images[ 0 ] = img;
			tex.LoadImages( images );
			FT.FT_Done_FreeType( ftLibrary );

            //img.Save( "C:\\" + Name + ".png" );
            //FileStream file = new FileStream( "C:\\" + 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
		}
        private void CreateTileData()
        {
            if (textureName.Equals("zero.png"))
            {
                textureName = string.Format("{0}_x{1}y{2}.{3}", parent.BaseName, m_tileLocationX, m_loadTileZ,
                                            parent.MosaicDesc.FileExt);
            }

            Image   textureImage;
            Texture texture = TextureManager.Instance.GetByName(textureName);

            if (ResourceManager.HasCommonResourceData(textureName))
            {
                Stream s = ResourceManager.FindCommonResourceData(textureName);
                textureImage = Image.FromStream(s, parent.MosaicDesc.FileExt);
                s.Close();
            }
            else
            {
                // Create a new image
                int    bpp    = PixelUtil.GetNumElemBytes(DEFAULT_IMAGE_FORMAT);
                byte[] buffer = new byte[tileSizeSamples * tileSizeSamples * bpp];
                textureImage = Image.FromDynamicImage(buffer, tileSizeSamples, tileSizeSamples, DEFAULT_IMAGE_FORMAT);
                Modified     = true;
            }

            // Cause the texture image to get refreshed
            dirtyImage       = true;
            dirtyArea.X      = 0;
            dirtyArea.Y      = 0;
            dirtyArea.Width  = textureImage.Width;
            dirtyArea.Height = textureImage.Height;

            // Popupate the tileData from the image
            switch (textureImage.Format)
            {
            case PixelFormat.A8:
            case PixelFormat.L8:
                tileData = new TileData8(textureImage);
                break;

            case PixelFormat.L16:
                tileData = new TileData16(textureImage);
                break;

            case PixelFormat.R8G8B8:
            case PixelFormat.B8G8R8:
                tileData = new TileData24(textureImage);
                break;

            case PixelFormat.A8B8G8R8:
            case PixelFormat.A8R8G8B8:
            case PixelFormat.B8G8R8A8:
            case PixelFormat.R8G8B8A8:
            case PixelFormat.X8R8G8B8:
            case PixelFormat.X8B8G8R8:
                tileData = new TileData32(textureImage);
                break;

            default:
                throw new InvalidDataException("Unexpected pixel format: " + textureImage.Format);
            }
        }
		public void LoadImage( Image img )
		{
			var pBox = img.GetPixelBox();
			Blit( ref pBox );
		}