Exemple #1
0
        public ExampleForm()
        {
            InitializeComponent();

            fontService = new FontService();
            fontFolder  = "Fonts/";
            sampleText  = "SharpFont";
            // Some variations of the character set shown by the Windows Font Viewer
            //sampleText = "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890.:,;'\"(!?)+-*//=";
            //sampleText = "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890";
            sampleText            = "abcdefghijklmnopqrstuvwxyz";
            fontService.Size      = 62f;
            fontSize              = 62f;
            mainMenuFontSize.Text = fontService.Size.ToString("0.0");
            foreColor             = Color.Black;
            backColor             = Color.Transparent;

            decimal testValue = 12.1234567890123456M;

            Debug.Print("testValue  : {0}", (double)testValue);
            // none of these keep the precision I was expecting...
            var f26 = new Fixed26Dot6(testValue);

            Debug.Print("Fixed 26.6 : {0}", (double)f26);
            Debug.Print("Fixed 26.6 : {0}", f26);
            var f16 = new Fixed16Dot16(testValue);

            Debug.Print("Fixed 16.16: {0}", (double)f16);
            Debug.Print("Fixed 16.16: {0}", f16);
            var f2 = new Fixed2Dot14((double)testValue);             // decimal constructor crashes here

            Debug.Print("Fixed  2.14: {0}", (double)f2);
            Debug.Print("Fixed  2.14: {0}", f2);
        }
Exemple #2
0
        public ExampleForm()
        {
            InitializeComponent();

            fontService = new FontService();
            fontFolder = "Fonts/";
            sampleText = "SharpFont";
            // Some variations of the character set shown by the Windows Font Viewer
            //sampleText = "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890.:,;'\"(!?)+-*//=";
            //sampleText = "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890";
            sampleText = "abcdefghijklmnopqrstuvwxyz";
            fontService.Size = 62f;
            fontSize = 62f;
            mainMenuFontSize.Text = fontService.Size.ToString("0.0");
            foreColor = Color.Black;
            backColor = Color.Transparent;

            decimal testValue = 12.1234567890123456M;
            Debug.Print("testValue  : {0}", (double)testValue);
            // none of these keep the precision I was expecting...
            var f26 = new Fixed26Dot6(testValue);
            Debug.Print("Fixed 26.6 : {0}", (double)f26);
            Debug.Print("Fixed 26.6 : {0}", f26);
            var f16 = new Fixed16Dot16(testValue);
            Debug.Print("Fixed 16.16: {0}", (double)f16);
            Debug.Print("Fixed 16.16: {0}", f16);
            var f2 = new Fixed2Dot14((double)testValue); // decimal constructor crashes here
            Debug.Print("Fixed  2.14: {0}", (double)f2);
            Debug.Print("Fixed  2.14: {0}", f2);
        }
Exemple #3
0
 public void AddFallback(FreeTypeFace face)
 {
     faces.AddLast(face);
     face.SetCharSize(Fixed26Dot6.FromSingle(FontSize));
     if (whitespace < face.FontMetrics.Width)
     {
         whitespace = face.FontMetrics.Width;
     }
 }
Exemple #4
0
        public void SetCharSize(Fixed26Dot6 size)
        {
            var err = FreeTypeNative.FT_Set_Char_Size(reference, IntPtr.Zero, (IntPtr)size.Value, 96, 96);

            CalculateMetrics();
            if (err != 0)
            {
                throw FreeTypeException.Except(err);
            }
        }
Exemple #5
0
        public FontLoader(
            IContentProvider contentProvider = null, string defaultFont = null, int baseFontSize = 32, int textureSize = 512)
        {
            if (baseFontSize <= 1 || baseFontSize > textureSize)
            {
                throw new ArgumentOutOfRangeException(nameof(baseFontSize));
            }
            if (textureSize <= 1)
            {
                throw new ArgumentOutOfRangeException(nameof(textureSize));
            }

            _defaultFont     = defaultFont ?? "Consola";
            _contentProvider = contentProvider;
            _baseFontSize    = baseFontSize;
            _textureSize     = textureSize;
            _freetype        = new Lazy <Library>(() => new Library());
        }
Exemple #6
0
 public void SetFontSize(float fontSize)
 {
     FontSize = fontSize;
     foreach (var freeTypeFace in faces)
     {
         freeTypeFace.SetCharSize(Fixed26Dot6.FromSingle(fontSize));
         if (whitespace < freeTypeFace.FontMetrics.Width)
         {
             whitespace = freeTypeFace.FontMetrics.Width;
         }
     }
     foreach (var spriteMap in spriteMaps)
     {
         spriteMap.Dispose();
     }
     spriteMaps.Clear();
     spriteReferences.Clear();
 }
Exemple #7
0
        public static bool LoadFace(ref Texture_Font_T font, ref Library library, ref Face face, float size)
        {
            library = new Library();
            if (library == null)
            {
                return(false);
            }
            face = new Face(library, font.Filename);
            if (face == null)
            {
                return(false);
            }
            face.SelectCharmap(Encoding.Unicode);
            face.SetCharSize(Fixed26Dot6.FromSingle(size), 0, DPI * HRES, HRES);
            FTMatrix matrix = new FTMatrix((int)(1.0 / HRES * 0x10000L), (int)(0.0 * 0x10000L), (int)(0.0 * 0x10000L), (int)(1.0 * 0x10000L));

            face.SetTransform(matrix);
            return(true);
        }
Exemple #8
0
        public FontLoader(
            NuGetDependencyResolver nuget, IContentProvider contentProvider = null,
            string defaultFont = null, int baseFontSize = 72, int textureSize = 512)
        {
            if (nuget == null)
            {
                throw new ArgumentNullException(nameof(nuget));
            }
            if (baseFontSize <= 1 || baseFontSize > textureSize)
            {
                throw new ArgumentOutOfRangeException(nameof(baseFontSize));
            }
            if (textureSize <= 1)
            {
                throw new ArgumentOutOfRangeException(nameof(textureSize));
            }

            this.dependencyResolver = nuget;
            this.defaultFont        = defaultFont ?? "Consola";
            this.contentProvider    = contentProvider;
            this.baseFontSize       = baseFontSize;
            this.textureSize        = textureSize;
            this.freetype           = new Lazy <Library>(LoadFreeTypeLibrary);
        }
Exemple #9
0
        public void SetCharSize(Fixed26Dot6 width, Fixed26Dot6 height, uint horizontalResolution, uint verticalResolution)
        {
            if (disposed)
                throw new ObjectDisposedException("face", "Cannot access a disposed object.");

            Error err = FT.FT_Set_Char_Size(Reference, (IntPtr)width.Value, (IntPtr)height.Value, horizontalResolution, verticalResolution);

            if (err != Error.Ok)
                throw new FreeTypeException(err);
        }
Exemple #10
0
 static int Div64(Fixed26Dot6 value)
 {
     return((int)Math.Ceiling(value.Value / 64.0));
 }
Exemple #11
0
		/// <summary><para>
		/// Embolden an outline. The new outline will be at most 4 times ‘strength’ pixels wider and higher. You may
		/// think of the left and bottom borders as unchanged.
		/// </para><para>
		/// Negative ‘strength’ values to reduce the outline thickness are possible also.
		/// </para></summary>
		/// <remarks><para>
		/// The used algorithm to increase or decrease the thickness of the glyph doesn't change the number of points;
		/// this means that certain situations like acute angles or intersections are sometimes handled incorrectly.
		/// </para><para>
		/// If you need ‘better’ metrics values you should call <see cref="GetCBox"/> or <see cref="GetBBox"/>.
		/// </para></remarks>
		/// <example>
		/// FT_Load_Glyph( face, index, FT_LOAD_DEFAULT );
		/// if ( face-&gt;slot-&gt;format == FT_GLYPH_FORMAT_OUTLINE )
		/// 	FT_Outline_Embolden( &amp;face-&gt;slot-&gt;outline, strength );
		/// </example>
		/// <param name="strength">How strong the glyph is emboldened. Expressed in 26.6 pixel format.</param>
		public void Embolden(Fixed26Dot6 strength)
		{
			if (disposed)
				throw new ObjectDisposedException("Outline", "Cannot access a disposed object.");

			Error err = FT.FT_Outline_Embolden(reference, (IntPtr)strength.Value);

			if (err != Error.Ok)
				throw new FreeTypeException(err);
		}
Exemple #12
0
        private void InitFont(float scaleFactor)
        {
            try {
                System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew();

                ScaleFactor   = scaleFactor;
                YOffsetScaled = YOffset * scaleFactor;

                // Reset everything
                Clear();

                Font = new Face(FontManager.Library, FilePath);

                // Go on

                float size = Size.Scale(ScaleFactor);

                Fixed26Dot6 sz = new Fixed26Dot6(size / 64);
                Font.SetCharSize(sz, sz, 72, 72);

                int pixelSize = (size * 1.3334).Ceil();
                Font.SetPixelSizes((uint)pixelSize, (uint)pixelSize);

                GlyphCount = Font.GlyphCount;
                int glyphCount = GlyphCount;
                Monospace = Font.FaceFlags.HasFlag(FaceFlags.FixedWidth);

                string tmpName = Font.GetPostscriptName();
                if (!String.IsNullOrEmpty(tmpName))
                {
                    Name = tmpName;
                }


                // We support 4 different glyph loading strategies:
                //
                // (1) All: all glyphs loaded at once on start
                // (2) Filtered: all filtered glyphs loaded at once on start
                // (3) OnDemand: no glyphs loaded at start, all glyphs on demand


                if (OnDemand)
                {
                    // Startegy (3)
                    GlyphCount = 0;
                }
                else if (Filter > GlyphFilterFlags.OnDemand)
                {
                    // Startegy (2)
                    // If we have a Filter set, let's count the number of valid glyphs
                    // to minimize graphics memory.
                    uint glyphindex;
                    uint cc    = Font.GetFirstChar(out glyphindex);
                    int  count = 0;
                    while (glyphindex > 0)
                    {
                        char c = (char)cc;
                        if (Filter.IsValid(c))
                        {
                            count++;
                        }
                        cc = Font.GetNextChar(cc, out glyphindex);
                    }
                    GlyphCount = count;
                }
                else
                {
                    // Strategy (1), loading the entire font
                }

                m_Textures = new int[Math.Max(32, GlyphCount)];
                CharMap    = new ThreadSafeDictionary <char, GlyphInfo>(Math.Max(31, GlyphCount));

                if (!OnDemand)
                {
                    // Strategy (1) + (2): Load all or filtered glyphs
                    m_ListBase = GL.GenLists(GlyphCount);
                    GL.GenTextures(GlyphCount, m_Textures);

                    uint glyphindex;
                    uint cc = Font.GetFirstChar(out glyphindex);
                    while (glyphindex > 0)
                    {
                        char c = (char)cc;
                        if (!CharMap.ContainsKey(c) && Filter.IsValid(c))
                        {
                            try {
                                CharMap.Add(c, CompileCharacter(Font, glyphindex, c));
                            } catch (Exception ex) {
                                ex.LogWarning();
                            }
                        }
                        cc = Font.GetNextChar(cc, out glyphindex);
                    }
                    CharMap.TryGetValue(SpecialCharacters.Ellipsis, out m_EllipsisGlyphIndex);
                }
                else
                {
                    try {
                        GetGlyphIndex(SpecialCharacters.Ellipsis, out m_EllipsisGlyphIndex);
                    } catch (Exception ex) {
                        ex.LogError();
                    }
                }

                //if (Height <= 1)
                //Height = pixelSize.NextPowerOf2();
                //Height = pixelSize * 1.33335f;

                Height = pixelSize;

                float fscale = Height / Font.Height * 1.33334f;
                //float fscale = Height / Font.Height * 0.776f;

                Ascender  = Font.Ascender * fscale;
                Descender = Font.Descender * fscale;
                //HalfHeight = Height / 2;

                Height     = (Ascender).Ceil();
                HalfHeight = (int)(Height / 2);

                //LineHeight = Height * 1.42f * LineSpacing;
                LineHeight = (int)((Height * 1.42f * LineSpacing) + 0.5f);

                //TextBoxHeight = ((Height * 2f) + (ScaleFactor * 2f)).Ceil();
                //TextBoxHeight = (int)(Height * 1.85f + 0.5f);
                TextBoxHeight = (int)(Height * 1.85f + 2);
                CaptionHeight = (int)(Height * 1.55 + 2);

                YOffsetScaled = (YOffset * ScaleFactor) - HalfHeight;

                if (OnDemand)
                {
                    Count.LogInformation("Font {0} ({1}), {2}/{3} glyphs pre-loaded in {4} ms, more glyphs are loaded on demand.", Name, Size, Count, glyphCount, sw.ElapsedMilliseconds);
                }
                else
                {
                    Count.LogInformation("Font {0} ({1}), {2}/{3} glyphs loaded in {4} ms.", Name, Size, Count, glyphCount, sw.ElapsedMilliseconds);
                }
            } catch (Exception ex) {
                ex.LogError();
            } finally {
                if (!OnDemand && Font != null)
                {
                    Font.Dispose();
                    Font = null;
                }
            }
        }
Exemple #13
0
        private Glyph LoadGlyph(int codePoint, int characterSize, bool bold, float outlineThickness)
        {
            Glyph glyph = new Glyph();

            if (_face == null)
            {
                return(null);
            }

            // Set the character size
            if (!SetCurrentSize(characterSize))
            {
                return(glyph);
            }

            // Load the glyph corresponding to the code point
            var flags = LoadFlags.ForceAutohint;

            if (outlineThickness != 0)
            {
                flags |= LoadFlags.NoBitmap;
            }

            _face.LoadChar((uint)codePoint, flags, SharpFont.LoadTarget.Normal);

            // Retrieve the glyph
            SharpFont.Glyph glyphDesc = _face.Glyph.GetGlyph();

            // Apply bold if necessary -- first technique using outline (highest quality)
            SharpFont.Fixed26Dot6 weight = new SharpFont.Fixed26Dot6(1);
            bool outline = glyphDesc.Format == SharpFont.GlyphFormat.Outline;

            if (outline)
            {
                if (bold)
                {
                    SharpFont.OutlineGlyph outlineGlyph = glyphDesc.ToOutlineGlyph();
                    outlineGlyph.Outline.Embolden(weight);
                }

                if (outlineThickness != 0)
                {
                    _stroker.Set((int)(outlineThickness * Fixed26Dot6.FromInt32(1).Value),
                                 StrokerLineCap.Round, StrokerLineJoin.Round, Fixed16Dot16.FromSingle(0));

                    // This function returning a new instance of Glyph
                    // Because the pointer may changed upon applying stroke to the glyph
                    glyphDesc = glyphDesc.Stroke(_stroker, false);
                }
            }

            // Convert the glyph to a bitmap (i.e. rasterize it)
            glyphDesc.ToBitmap(SharpFont.RenderMode.Normal, new FTVector26Dot6(0, 0), true);
            SharpFont.FTBitmap bitmap = glyphDesc.ToBitmapGlyph().Bitmap;

            // Apply bold if necessary -- fallback technique using bitmap (lower quality)
            if (!outline)
            {
                if (bold)
                {
                    bitmap.Embolden(_library, weight, weight);
                }

                if (outlineThickness != 0)
                {
                    Logger.Warning("Failed to outline glyph (no fallback available)");
                }
            }

            // Compute the glyph's advance offset
            glyph.Advance = _face.Glyph.Metrics.HorizontalAdvance.ToSingle();
            if (bold)
            {
                glyph.Advance += weight.ToSingle();
            }

            int width  = bitmap.Width;
            int height = bitmap.Rows;

            if ((width > 0) && (height > 0))
            {
                // Leave a small padding around characters, so that filtering doesn't
                // pollute them with pixels from neighbors
                int padding = 1;

                // Get the glyphs page corresponding to the character size
                Page page = _pages[characterSize];

                // Find a good position for the new glyph into the texture
                glyph.TexCoords = FindGlyphRectangle(page, width + 2 * padding, height + 2 * padding);
                var texRect = glyph.TexCoords;

                // Make sure the texture data is positioned in the center
                // of the allocated texture rectangle
                glyph.TexCoords = new Rectangle(texRect.X + padding, texRect.Y + padding,
                                                texRect.Width - 2 * padding, texRect.Height - 2 * padding);

                // Compute the glyph's bounding box
                float boundsX      = (float)(_face.Glyph.Metrics.HorizontalBearingX);
                float boundsY      = -(float)(_face.Glyph.Metrics.HorizontalBearingY);
                float boundsWidth  = (float)(_face.Glyph.Metrics.Width) + outlineThickness * 2;
                float boundsHeight = (float)(_face.Glyph.Metrics.Height) + outlineThickness * 2;
                glyph.Bounds = new RectangleF(boundsX, boundsY, boundsWidth, boundsHeight);

                // Extract the glyph's pixels from the bitmap
                byte[] pixelBuffer = new byte[width * height * 4];
                for (int i = 0; i < pixelBuffer.Length; i++)
                {
                    pixelBuffer[i] = 255;
                }

                unsafe
                {
                    byte *pixels = (byte *)bitmap.Buffer.ToPointer();
                    if (bitmap.PixelMode == SharpFont.PixelMode.Mono)
                    {
                        // Pixels are 1 bit monochrome values
                        for (int y = 0; y < height; ++y)
                        {
                            for (int x = 0; x < width; ++x)
                            {
                                // The color channels remain white, just fill the alpha channel
                                int index = (x + y * width) * 4 + 3;
                                pixelBuffer[index] = (byte)((((pixels[x / 8]) & (1 << (7 - (x % 8)))) > 0) ? 255 : 0);
                            }
                            pixels += bitmap.Pitch;
                        }
                    }
                    else
                    {
                        // Pixels are 8 bits gray levels
                        for (int y = 0; y < height; ++y)
                        {
                            for (int x = 0; x < width; ++x)
                            {
                                // The color channels remain white, just fill the alpha channel
                                int index = (x + y * width) * 4 + 3;
                                pixelBuffer[index] = pixels[x];
                            }
                            pixels += bitmap.Pitch;
                        }
                    }
                }

                // Write the pixels to the texture
                int tx = glyph.TexCoords.Left;
                int ty = glyph.TexCoords.Top;
                int tw = glyph.TexCoords.Width;
                int th = glyph.TexCoords.Height;
                page.texture.Update(pixelBuffer, tx, ty, tw, th);
            }

            // Delete the FT glyph
            glyphDesc.Dispose();

            return(glyph);
        }
Exemple #14
0
		/// <summary>
		/// Embolden a bitmap. The new bitmap will be about ‘xStrength’ pixels wider and ‘yStrength’ pixels higher. The
		/// left and bottom borders are kept unchanged.
		/// </summary>
		/// <remarks><para>
		/// The current implementation restricts ‘xStrength’ to be less than or equal to 8 if bitmap is of pixel_mode
		/// <see cref="SharpFont.PixelMode.Mono"/>.
		/// </para><para>
		/// If you want to embolden the bitmap owned by a <see cref="GlyphSlot"/>, you should call
		/// <see cref="GlyphSlot.OwnBitmap"/> on the slot first.
		/// </para></remarks>
		/// <param name="library">A handle to a library object.</param>
		/// <param name="xStrength">
		/// How strong the glyph is emboldened horizontally. Expressed in 26.6 pixel format.
		/// </param>
		/// <param name="yStrength">
		/// How strong the glyph is emboldened vertically. Expressed in 26.6 pixel format.
		/// </param>
		public void Embolden(Library library, Fixed26Dot6 xStrength, Fixed26Dot6 yStrength)
		{
			if (disposed)
				throw new ObjectDisposedException("FTBitmap", "Cannot access a disposed object.");

			if (library == null)
				throw new ArgumentNullException("library");

			Error err = FT.FT_Bitmap_Embolden(library.Reference, Reference, (IntPtr)xStrength.Value, (IntPtr)yStrength.Value);

			if (err != Error.Ok)
				throw new FreeTypeException(err);
		}
Exemple #15
0
        public NISFont DrawT3BFontBitmap(char[] strings)
        {
            NISFont  fnt_data = new NISFont();
            Bitmap   bmp      = new Bitmap(Config.texture_width, Config.texture_height);
            Graphics g        = Graphics.FromImage(bmp);

            g.Clear(Color.FromArgb(0x00000000));
            int     x = 0, y = 0;
            int     tile_w = Config.fontWidth;
            int     tile_h = Config.fontHeight;
            int     relativePositionX = 1;
            int     relativePositionY = -2;
            int     font_height = Config.fontSize;
            Library library = new Library();
            string  facename = Config.ttfName;
            Face    face = library.NewFace(facename, 0);
            float   left, right, top, bottom, FHT;
            int     FHD, kx, ky;

            foreach (char currentChar0 in strings)
            {
                uint charid = uchar2code(currentChar0.ToString());
                face.SetCharSize(0, font_height, 0, 72);
                if (charid < 0x7f)
                {
                    font_height = Config.fontSize - 2;
                    face.SetCharSize(0, font_height, 0, 72);
                }
                else
                {
                    font_height = Config.fontSize;
                }
                face.SetPixelSizes((uint)0, (uint)font_height);

                uint glyphIndex = face.GetCharIndex(charid);

                //Console.WriteLine(glyphIndex);
                face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Lcd);
                face.Glyph.Outline.Embolden(0.5);
                face.Glyph.RenderGlyph(RenderMode.Normal);

                FTBitmap ftbmp  = face.Glyph.Bitmap;
                FTBitmap ftbmp2 = face.Glyph.Bitmap;

                left   = (float)face.Glyph.Metrics.HorizontalBearingX;
                right  = (float)face.Glyph.Metrics.HorizontalBearingX + (float)face.Glyph.Metrics.Width;
                top    = (float)face.Glyph.Metrics.HorizontalBearingY;
                bottom = (float)face.Glyph.Metrics.HorizontalBearingY + (float)face.Glyph.Metrics.Height;

                FHT = font_height;
                FHD = (int)Math.Ceiling(FHT);
                kx  = x + (int)Math.Round(left);
                ky  = (int)Math.Round((float)y + (float)Math.Ceiling(FHT) - (float)top);


                if (ftbmp.Width == 0 || glyphIndex < 0x20)
                {
                    Face face1 = library.NewFace(Config.baseName, 0);
                    face1.SetCharSize(0, font_height, 0, 72);
                    face1.SetPixelSizes((uint)0, (uint)font_height);
                    glyphIndex = face1.GetCharIndex(charid);
                    face1.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Lcd);
                    face1.Glyph.Outline.Embolden(Fixed26Dot6.FromDouble(0.4));
                    face1.Glyph.RenderGlyph(RenderMode.Normal);

                    left   = (float)face1.Glyph.Metrics.HorizontalBearingX;
                    right  = (float)face1.Glyph.Metrics.HorizontalBearingX + (float)face1.Glyph.Metrics.Width;
                    top    = (float)face1.Glyph.Metrics.HorizontalBearingY;
                    bottom = (float)face1.Glyph.Metrics.HorizontalBearingY + (float)face1.Glyph.Metrics.Height;

                    FHT    = font_height;
                    FHD    = (int)Math.Ceiling(FHT);
                    kx     = x + (int)Math.Round(left);
                    ky     = (int)Math.Round((float)y + (float)Math.Ceiling(FHT) - (float)top);
                    ftbmp  = face1.Glyph.Bitmap;
                    ftbmp2 = face1.Glyph.Bitmap;
                }

                fnt_data.charvalues.Add(new XYWH((int)uchar2code(currentChar0.ToString()),
                                                 x,
                                                 y,
                                                 tile_w,
                                                 tile_h,
                                                 0));

                if (ftbmp2.Width == 0)
                {
                    x += tile_w;
                    if (x + tile_w > Config.texture_width)
                    {
                        x  = 0;
                        y += tile_h;
                    }
                    continue;
                }
                Bitmap cBmp = ftbmp2.ToGdipBitmap(Color.White);
                g.DrawImageUnscaled(cBmp, kx + relativePositionX, ky + relativePositionY);
                g.DrawImageUnscaled(cBmp, kx + relativePositionX, ky + relativePositionY);
                cBmp.Dispose();



                x += tile_w;
                if (x + tile_w > Config.texture_width)
                {
                    x  = 0;
                    y += tile_h;
                }
            }
            fnt_data.bitmap = bmp;
            return(fnt_data);
        }
Exemple #16
0
        internal unsafe void AddCharacter(GlyphCollection col, uint cp)
        {
            if (cp == (uint)'\t')
            {
                var spaceGlyph = col.GetGlyph((uint)' ');
                col.glyphs.Add(cp, new GlyphInfo(spaceGlyph.AdvanceX * 4, spaceGlyph.AdvanceY, spaceGlyph.CharIndex, spaceGlyph.Kerning));
            }
            Face.SetCharSize(0, col.Size, 0, 96);
            var  c_face    = Face;
            bool dobold    = emulate_bold;
            bool doitalics = emulate_italics;
            bool dokern    = true;
            uint index     = c_face.GetCharIndex(cp);

            if (index == 0)
            {
                //Glyph does not exist in font
                if (cp == (uint)'?')
                {
                    throw new Exception("Font does not have required ASCII character '?'");
                }
                var fallback = Platform.GetFallbackFace(ren.FT, cp);
                if ((index = fallback.GetCharIndex(cp)) != 0)
                {
                    try
                    {
                        c_face = fallback;
                        c_face.SetCharSize(0, col.Size, 0, 96);
                        dobold = doitalics = dokern = false;
                    }
                    catch (Exception)
                    {
                        var qmGlyph = col.GetGlyph((uint)'?');
                        col.glyphs.Add(cp, qmGlyph);
                        return;
                    }
                }
                else
                {
                    var qmGlyph = col.GetGlyph((uint)'?');
                    col.glyphs.Add(cp, qmGlyph);
                    return;
                }
            }
            c_face.LoadGlyph(index, LoadFlags.Default | LoadFlags.ForceAutohint, LoadTarget.Normal);
            if (dobold)
            {
                //Automatically determine a strength
                var strength = (c_face.UnitsPerEM * c_face.Size.Metrics.ScaleY.Value) / 0x10000;
                strength /= 24;
                c_face.Glyph.Outline.Embolden(Fixed26Dot6.FromRawValue(strength));
            }
            if (doitalics)
            {
                c_face.Glyph.Outline.Transform(new FTMatrix(0x10000, 0x0366A, 0x00000, 0x10000));
            }
            c_face.Glyph.RenderGlyph(RenderMode.Normal);
            if (c_face.Glyph.Bitmap.Width == 0 || c_face.Glyph.Bitmap.Rows == 0)
            {
                col.glyphs.Add(cp,
                               new GlyphInfo(
                                   (int)Math.Ceiling((float)c_face.Glyph.Advance.X),
                                   (int)Math.Ceiling((float)c_face.Glyph.Advance.Y),
                                   index,
                                   dokern && Face.HasKerning
                                   )
                               );
            }
            else
            {
                if (c_face.Glyph.Bitmap.PixelMode != PixelMode.Gray)
                {
                    throw new NotImplementedException();
                }
                if (currentX + c_face.Glyph.Bitmap.Width > TEXTURE_SIZE)
                {
                    currentX  = 0;
                    currentY += lineMax;
                    lineMax   = 0;
                }
                if (currentY + c_face.Glyph.Bitmap.Rows > TEXTURE_SIZE)
                {
                    currentX = 0;
                    currentY = 0;
                    lineMax  = 0;
                    textures.Add(new Texture2D(
                                     TEXTURE_SIZE,
                                     TEXTURE_SIZE,
                                     false,
                                     SurfaceFormat.R8
                                     ));
                    FLLog.Debug("Text", string.Format("{0}@{1}, New Texture", facename, col.Size));
                }
                lineMax = (int)Math.Max(lineMax, c_face.Glyph.Bitmap.Rows);
                var rect = new Rectangle(
                    currentX,
                    currentY,
                    c_face.Glyph.Bitmap.Width,
                    c_face.Glyph.Bitmap.Rows
                    );
                var tex = textures [textures.Count - 1];
                GL.PixelStorei(GL.GL_UNPACK_ALIGNMENT, 1);
                //Set
                tex.SetData(0, rect, c_face.Glyph.Bitmap.Buffer);
                GL.PixelStorei(GL.GL_UNPACK_ALIGNMENT, 4);
                currentX += c_face.Glyph.Bitmap.Width;
                col.glyphs.Add(
                    cp,
                    new GlyphInfo(
                        tex,
                        rect,
                        (int)Math.Ceiling((float)c_face.Glyph.Advance.X),
                        (int)Math.Ceiling((float)c_face.Glyph.Advance.Y),
                        (int)Math.Ceiling((float)c_face.Glyph.Metrics.HorizontalAdvance),
                        c_face.Glyph.BitmapLeft,
                        c_face.Glyph.BitmapTop,
                        index,
                        dokern && Face.HasKerning
                        )
                    );
            }
        }
 private static Single GetFloat(IntPtr ptr) =>
 Fixed26Dot6.FromRawValue((Int32)ptr).Value / 64f;