Beispiel #1
0
        public GLFont(Font font, GLFontBuilderConfiguration config = null)
        {
            options = new GLFontRenderOptions();

            if (config == null)
            {
                config = new GLFontBuilderConfiguration();
            }

            fontData = new GLFontBuilder(font, config).BuildFontData();
        }
Beispiel #2
0
        public void MeasureNodes(GLFontData fontData, GLFontRenderOptions options)
        {
            bool  monospaced     = fontData.IsMonospacingActive(options);
            float monospaceWidth = fontData.GetMonoSpaceWidth(options);

            foreach (GLFontTextNode node in this)
            {
                if (node.Length == 0f)
                {
                    if (node.Type == GLFontTextNodeType.Space)
                    {
                        if (monospaced)
                        {
                            node.Length = monospaceWidth;
                            continue;
                        }
                        node.Length = (float)Math.Ceiling(fontData.meanGlyphWidth * options.WordSpacing);
                        continue;
                    }

                    if (node.Type == GLFontTextNodeType.Tab)
                    {
                        if (monospaced)
                        {
                            node.Length = monospaceWidth * 4;
                            continue;
                        }
                        node.Length = (float)Math.Ceiling(4 * fontData.meanGlyphWidth * options.WordSpacing);
                        continue;
                    }

                    if (node.Type == GLFontTextNodeType.Word)
                    {
                        for (int i = 0; i < node.Text.Length; i++)
                        {
                            char        c = node.Text[i];
                            GLFontGlyph glyph;
                            if (fontData.CharSetMapping.TryGetValue(c, out glyph))
                            {
                                if (monospaced)
                                {
                                    node.Length += monospaceWidth;
                                }
                                else
                                {
                                    node.Length += (float)Math.Ceiling(glyph.Rect.Width + fontData.meanGlyphWidth * options.CharacterSpacing + fontData.GetKerningPairCorrection(i, node.Text, node));
                                }
                            }
                        }
                    }
                }
            }
        }
Beispiel #3
0
        public GLFont(string fileName, float size, GLFontBuilderConfiguration config, FontStyle style = FontStyle.Regular)
        {
            PrivateFontCollection pfc = new PrivateFontCollection();

            pfc.AddFontFile(fileName);
            var fontFamily = pfc.Families[0];

            if (!fontFamily.IsStyleAvailable(style))
            {
                throw new ArgumentException("Font file: " + fileName + " does not support style: " + style);
            }

            if (config == null)
            {
                config = new GLFontBuilderConfiguration();
            }

            using (var font = new Font(fontFamily, size * config.SuperSampleLevels, style))
            {
                fontData = new GLFontBuilder(font, config).BuildFontData();
            }
            pfc.Dispose();
        }
Beispiel #4
0
        public GLFontData BuildFontData()
        {
            if (config.ForcePowerOfTwo && config.SuperSampleLevels != PowerOfTwo(config.SuperSampleLevels))
            {
                throw new ArgumentOutOfRangeException("SuperSampleLevels must be a power of two when using ForcePowerOfTwo.");
            }
            if (config.SuperSampleLevels <= 0 || config.SuperSampleLevels > 8)
            {
                throw new ArgumentOutOfRangeException("SuperSampleLevels = [" + config.SuperSampleLevels + "] is an unsupported value. Please use values in the range [1,8]");
            }

            int  margin        = 2; // margin in initial bitmap (don't bother to make configurable - likely to cause confusion
            int  pageWidth     = config.PageWidth * config.SuperSampleLevels;
            int  pageHeight    = config.PageHeight * config.SuperSampleLevels;
            bool usePowerOfTwo = config.ForcePowerOfTwo;
            int  glyphMargin   = config.GlyphMargin * config.SuperSampleLevels;

            GLFontGlyph[] initialGlyphs;
            var           sizes             = GetGlyphSizes(font);
            var           maxSize           = GetMaxGlyphSize(sizes);
            var           initialBmp        = CreateInitialBitmap(font, maxSize, margin, out initialGlyphs, config.TextGenerationRenderHint);
            var           initialBitmapData = initialBmp.LockBits(new Rectangle(0, 0, initialBmp.Width, initialBmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

            int minYOffset = int.MaxValue;

            foreach (var glyph in initialGlyphs)
            {
                RetargetGlyphRectangleInwards(initialBitmapData, glyph, true, config.KerningConfig.AlphaEmptyPixelTolerance);
                minYOffset = Math.Min(minYOffset, glyph.YOffset);
            }
            minYOffset--; // give one pixel of breathing room?

            foreach (var glyph in initialGlyphs)
            {
                glyph.YOffset -= minYOffset;
            }

            GLFontGlyph[] glyphs;
            var           bitmapPages = GenerateBitmapSheetsAndRepack(initialGlyphs, new BitmapData[1] {
                initialBitmapData
            }, pageWidth, pageHeight, out glyphs, glyphMargin, usePowerOfTwo);

            initialBmp.UnlockBits(initialBitmapData);
            initialBmp.Dispose();

            if (config.SuperSampleLevels != 1)
            {
                ScaleSheetsAndGlyphs(bitmapPages, glyphs, 1.0f / config.SuperSampleLevels);
                RetargetAllGlyphs(bitmapPages, glyphs, config.KerningConfig.AlphaEmptyPixelTolerance);
            }

            //create list of texture pages
            var pages = new List <GLFontTexture>();

            foreach (var page in bitmapPages)
            {
                pages.Add(new GLFontTexture(page.bitmapData));
            }

            var fontData = new GLFontData();

            fontData.CharSetMapping = glyphs.ToDictionary(g => g.Character);
            fontData.Pages          = pages.ToArray();
            fontData.CalculateMeanWidth();
            fontData.CalculateMaxHeight();
            fontData.KerningPairs        = GLFontKerningCalculator.CalculateKerning(charSet.ToCharArray(), glyphs, bitmapPages, config.KerningConfig);
            fontData.naturallyMonospaced = IsMonospaced(sizes);

            foreach (var glyph in glyphs)
            {
                var page = pages[glyph.Page];
                glyph.TextureMin = new PointF((float)glyph.Rect.X / page.Width, (float)glyph.Rect.Y / page.Height);
                glyph.TextureMax = new PointF((float)glyph.Rect.Right / page.Width, (float)glyph.Rect.Bottom / page.Height);
            }

            foreach (var page in bitmapPages)
            {
                page.Free();
            }

            //validate glyphs
            var intercept = FirstIntercept(fontData.CharSetMapping);

            if (intercept != null)
            {
                throw new Exception("Failed to create glyph set. Glyphs '" + intercept[0] + "' and '" + intercept[1] + "' were overlapping. This is could be due to an error in the font, or a bug in Graphics.MeasureString().");
            }

            return(fontData);
        }