示例#1
0
        /// <summary>
        /// Returns next power-of-two size if required by render system, in case
        /// RSC_NON_POWER_OF_2_TEXTURES is supported it returns value as-is.
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static int OptionalPO2(int value)
        {
            RenderSystemCapabilities caps = Root.Instance.RenderSystem.Capabilities;

            if (caps.HasCapability(Capabilities.NonPowerOf2Textures))
            {
                return(value);
            }
            else
            {
                return((int)Bitwise.FirstPO2From((uint)value));
            }
        }
示例#2
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
        }