Пример #1
0
   private void Load(
 )
   {
       Metrics = new FontMetrics();
         LoadFontHeader();
         LoadCharMetrics();
         LoadKerningData();
   }
Пример #2
0
 protected internal override PdfDictionary GetFontDescriptor(String fontName)
 {
     if (fontName != null && fontName.Length > 0)
     {
         PdfDictionary fontDescriptor = new PdfDictionary();
         MakeObjectIndirect(fontDescriptor);
         fontDescriptor.Put(PdfName.Type, PdfName.FontDescriptor);
         FontMetrics fontMetrics = fontProgram.GetFontMetrics();
         fontDescriptor.Put(PdfName.CapHeight, new PdfNumber(fontMetrics.GetCapHeight()));
         fontDescriptor.Put(PdfName.ItalicAngle, new PdfNumber(fontMetrics.GetItalicAngle()));
         FontNames fontNames = fontProgram.GetFontNames();
         fontDescriptor.Put(PdfName.FontWeight, new PdfNumber(fontNames.GetFontWeight()));
         fontDescriptor.Put(PdfName.FontName, new PdfName(fontName));
         if (fontNames.GetFamilyName() != null && fontNames.GetFamilyName().Length > 0 && fontNames.GetFamilyName()
             [0].Length >= 4)
         {
             fontDescriptor.Put(PdfName.FontFamily, new PdfString(fontNames.GetFamilyName()[0][3]));
         }
         int flags = fontProgram.GetPdfFontFlags();
         flags &= ~(FontDescriptorFlags.Symbolic | FontDescriptorFlags.Nonsymbolic);
         // reset both flags
         flags |= fontEncoding.IsFontSpecific() ? FontDescriptorFlags.Symbolic : FontDescriptorFlags.Nonsymbolic;
         // set based on font encoding
         fontDescriptor.Put(PdfName.Flags, new PdfNumber(flags));
         return(fontDescriptor);
     }
     else
     {
         if (GetPdfObject().GetIndirectReference() != null && GetPdfObject().GetIndirectReference().GetDocument().IsTagged
                 ())
         {
             ILog logger = LogManager.GetLogger(typeof(iText.Kernel.Font.PdfType3Font));
             logger.Warn(iText.IO.LogMessageConstant.TYPE3_FONT_ISSUE_TAGGED_PDF);
         }
     }
     return(null);
 }
Пример #3
0
        public override FontMetrics GetFontMetrics(Font font)
        {
            CTFont sysFont = font.RendererData as CTFont;

            if (sysFont == null || Math.Abs(font.RealSize - font.Size * Scale) > 2)
            {
                FreeFont(font);
                LoadFont(font);
                sysFont = font.RendererData as CTFont;
            }

            FontMetrics fm = new FontMetrics
                             (
                (float)(sysFont.AscentMetric + sysFont.DescentMetric - sysFont.LeadingMetric),
                (float)(sysFont.AscentMetric),
                (float)(sysFont.DescentMetric),
                (float)(sysFont.AscentMetric + sysFont.DescentMetric),
                (float)(sysFont.LeadingMetric),
                (float)(sysFont.AscentMetric + sysFont.DescentMetric),
                0
                             );

            return(fm);
        }
Пример #4
0
        public override void LoadSurfaces()
        {
            var         fontSurface = content.Load <Texture2D>("Images/font");
            FontMetrics fontMetrics = BuildFontMetrics();

            var bitmapFont = new BitmapFontTexture(fontSurface,
                                                   fontMetrics,
                                                   "LotaFont");

            Font = new FontBuilder("LotaFont")
                   .AddFontTexture(new FontSettings(16, FontStyles.None), bitmapFont)
                   .Build();
            Font.Size = 16;

            Character = content.Load <Texture2D>("Images/character");
            Monsters  = content.Load <Texture2D>("Images/OverworldMonsters");

            Lota3DSurfaces.LoadSurfaces(content);

            foreach (var exinfo in data.ExhibitInfo.Values)
            {
                exinfo.LoadImage(content);
            }
        }
Пример #5
0
        public override FontMetrics GetFontMetrics(Font font)
        {
            System.Drawing.Font sysFont = font.RendererData as System.Drawing.Font;

            if (sysFont == null || Math.Abs(font.RealSize - font.Size * Scale) > 2)
            {
                FreeFont(font);
                LoadFont(font);
                sysFont = font.RendererData as System.Drawing.Font;
            }

            // from: http://csharphelper.com/blog/2014/08/get-font-metrics-in-c
            float emHeight       = sysFont.FontFamily.GetEmHeight(sysFont.Style);
            float emHeightPixels = ConvertToPixels(sysFont.Size, sysFont.Unit);
            float designToPixels = emHeightPixels / emHeight;

            float ascentPixels          = designToPixels * sysFont.FontFamily.GetCellAscent(sysFont.Style);
            float descentPixels         = designToPixels * sysFont.FontFamily.GetCellDescent(sysFont.Style);
            float cellHeightPixels      = ascentPixels + descentPixels;
            float internalLeadingPixels = cellHeightPixels - emHeightPixels;
            float lineSpacingPixels     = designToPixels * sysFont.FontFamily.GetLineSpacing(sysFont.Style);
            float externalLeadingPixels = lineSpacingPixels - cellHeightPixels;

            FontMetrics fm = new FontMetrics
                             (
                emHeightPixels,
                ascentPixels,
                descentPixels,
                cellHeightPixels,
                internalLeadingPixels,
                lineSpacingPixels,
                externalLeadingPixels
                             );

            return(fm);
        }
Пример #6
0
        public static bool CheckAllCoverages(
            FontMetrics fontMetrics,
            LookupFlags lookupFlags,
            IGlyphShapingCollection collection,
            ushort index,
            int count,
            CoverageTable[] input,
            CoverageTable[] backtrack,
            CoverageTable[] lookahead)
        {
            // Check that there are enough context glyphs.
            if (index - backtrack.Length < 0 || input.Length + lookahead.Length > count)
            {
                return(false);
            }

            // Check all coverages: if any of them does not match, abort update.
            SkippingGlyphIterator iterator = new(fontMetrics, collection, index, lookupFlags);

            if (!MatchCoverageSequence(iterator, backtrack, -backtrack.Length))
            {
                return(false);
            }

            if (!MatchCoverageSequence(iterator, input, 0))
            {
                return(false);
            }

            if (!MatchCoverageSequence(iterator, lookahead, input.Length))
            {
                return(false);
            }

            return(true);
        }
        protected internal virtual void paintText(Graphics paramGraphics, int paramInt1, int paramInt2, int paramInt3, int paramInt4)
        {
            FontMetrics fontMetrics = paramGraphics.FontMetrics;
            string      str         = applicationButtonText;
            sbyte       b1          = 40;
            sbyte       b2          = 30;
            int         i           = paramInt1 + paramInt3 / 2 - fontMetrics.stringWidth(str) / 2;
            int         j           = paramInt2 + paramInt4 / 2 - fontMetrics.Height / 2;

            j += 2;
            Rectangle rectangle = new Rectangle(i, j, fontMetrics.stringWidth(str), fontMetrics.Height);

            while (str.Length != 0)
            {
                int k = fontMetrics.stringWidth(str);
                if (k <= rectangle.width)
                {
                    break;
                }
                str = str.Substring(0, str.Length - 1);
            }
            paramGraphics.Color = Color.white;
            BasicGraphicsUtils.drawString(paramGraphics, str, -1, rectangle.x, rectangle.y + fontMetrics.Ascent);
        }
Пример #8
0
 protected internal static double Width(Tree tree, FontMetrics fM)
 {
     return(WidthResult(tree, fM).width);
 }
Пример #9
0
        public virtual Dimension GetTreeDimension(Tree tree, Font font)
        {
            FontMetrics fM = GetFontMetrics(font);

            return(new Dimension((int)Width(tree, fM), (int)Height(tree, fM)));
        }
Пример #10
0
        private static void MakeBitmap(BitmapFontOptions options, ICharacterRenderer rend,
                                       out Drawing.Bitmap bmp, out FontMetrics glyphs)
        {
            Size bitmapSize = new Size(256, 64);

            bmp = new System.Drawing.Bitmap(bitmapSize.Width, bitmapSize.Height);
            Drawing.Graphics g    = Drawing.Graphics.FromImage(bmp);
            Drawing.Font     font = rend.Font;

            g.TextRenderingHint = Drawing.Text.TextRenderingHint.ClearTypeGridFit;

            glyphs = new FontMetrics();

            const int bitmapPadding = 2;

            int  x = rend.Padding, y = 2;
            int  height   = 0;
            char lastChar = ' ';

            // first measure the required height of the image.
            foreach (BitmapFontOptions.CharacterRange range in options.CharacterRanges)
            {
                for (char i = range.StartChar; i <= range.EndChar; i++)
                {
                    Size sourceSize = rend.MeasureText(g, i.ToString());
                    if (options.CreateBorder)
                    {
                        sourceSize.Width  += 2;
                        sourceSize.Height += 2;
                    }

                    int thisWidth = sourceSize.Width + bitmapPadding;

                    x += thisWidth;

                    if (height < sourceSize.Height)
                    {
                        height = sourceSize.Height;
                    }

                    if (x > bitmapSize.Width)
                    {
                        x      = 1 + thisWidth;
                        y     += height + bitmapPadding + 1;
                        height = 0;
                    }

                    glyphs[i] = new GlyphMetrics(new Rectangle(0, 0, sourceSize.Width, sourceSize.Height));

                    lastChar = i;
                }
            }

            y += glyphs[lastChar].Height;

            if (y > bitmapSize.Height)
            {
                while (y > bitmapSize.Height)
                {
                    bitmapSize.Height *= 2;
                }

                g.Dispose();
                bmp.Dispose();

                bmp = new System.Drawing.Bitmap(bitmapSize.Width, bitmapSize.Height);
                g   = Drawing.Graphics.FromImage(bmp);
            }

            Drawing.Bitmap   borderBmp = new System.Drawing.Bitmap(bmp.Width, bmp.Height);
            Drawing.Graphics borderG   = Drawing.Graphics.FromImage(borderBmp);

            x      = rend.Padding;
            y      = 2;
            height = 0;
            Drawing.Color borderColor = System.Drawing.Color.FromArgb(
                options.BorderColor.A, options.BorderColor.R, options.BorderColor.G, options.BorderColor.B);

            foreach (BitmapFontOptions.CharacterRange range in options.CharacterRanges)
            {
                for (char i = range.StartChar; i <= range.EndChar; i++)
                {
                    if (x + glyphs[i].Width > bitmapSize.Width)
                    {
                        x      = rend.Padding;
                        y     += height + bitmapPadding + 1;
                        height = 0;
                    }

                    if (options.CreateBorder)
                    {
                        rend.DrawText(borderG, i.ToString(), new Point(x, y + 1), borderColor);
                        rend.DrawText(borderG, i.ToString(), new Point(x + 2, y + 1), borderColor);
                        rend.DrawText(borderG, i.ToString(), new Point(x + 1, y), borderColor);
                        rend.DrawText(borderG, i.ToString(), new Point(x + 1, y + 2), borderColor);

                        rend.DrawText(g, i.ToString(), new Point(x + 1, y + 1), System.Drawing.Color.White);

                        if (font.SizeInPoints >= 14.0)
                        {
                            glyphs[i].LeftOverhang = 1;
                        }

                        glyphs[i].RightOverhang = 1;
                    }
                    else
                    {
                        rend.DrawText(g, i.ToString(), new Point(x, y), System.Drawing.Color.White);
                    }

                    glyphs[i].SourceRect = new Rectangle(
                        new Point(x, y),
                        glyphs[i].Size);

                    x += glyphs[i].Width + bitmapPadding;

                    if (height < glyphs[i].Height)
                    {
                        height = glyphs[i].Height;
                    }
                }
            }

            g.Dispose();

            // do post processing of chars.
            PostProcessFont(options, bmp);

            // place the chars on the border image
            borderG.DrawImage(bmp, new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height));

            bmp.Dispose();
            borderG.Dispose();

            bmp = borderBmp;
        }
Пример #11
0
        private Glyph ImportGlyph(Factory factory, FontFace fontFace, char character, FontMetrics fontMetrics, float fontSize, FontAntiAliasMode antiAliasMode)
        {
            var indices = fontFace.GetGlyphIndices(new int[] { character });

            var metrics = fontFace.GetDesignGlyphMetrics(indices, false);
            var metric  = metrics[0];

            var width  = (float)(metric.AdvanceWidth - metric.LeftSideBearing - metric.RightSideBearing) / fontMetrics.DesignUnitsPerEm * fontSize;
            var height = (float)(metric.AdvanceHeight - metric.TopSideBearing - metric.BottomSideBearing) / fontMetrics.DesignUnitsPerEm * fontSize;

            var xOffset = (float)metric.LeftSideBearing / fontMetrics.DesignUnitsPerEm * fontSize;
            var yOffset = (float)(metric.TopSideBearing - metric.VerticalOriginY) / fontMetrics.DesignUnitsPerEm * fontSize;

            var advanceWidth = (float)metric.AdvanceWidth / fontMetrics.DesignUnitsPerEm * fontSize;
            //var advanceHeight = (float)metric.AdvanceHeight / fontMetrics.DesignUnitsPerEm * fontSize;

            var pixelWidth  = (int)Math.Ceiling(width + 4);
            var pixelHeight = (int)Math.Ceiling(height + 4);

            var matrix = new RawMatrix3x2
            {
                M11 = 1,
                M22 = 1,
                M31 = -(float)Math.Floor(xOffset) + 1,
                M32 = -(float)Math.Floor(yOffset) + 1
            };

            Bitmap bitmap;

            if (char.IsWhiteSpace(character))
            {
                bitmap = new Bitmap(1, 1, PixelFormat.Format32bppArgb);
            }
            else
            {
                var glyphRun = new GlyphRun
                {
                    FontFace   = fontFace,
                    Advances   = new[] { (float)Math.Ceiling(advanceWidth) },
                    FontSize   = fontSize,
                    BidiLevel  = 0,
                    Indices    = indices,
                    IsSideways = false,
                    Offsets    = new[] { new GlyphOffset() }
                };


                RenderingMode renderingMode;
                if (antiAliasMode != FontAntiAliasMode.Aliased)
                {
                    var rtParams = new RenderingParams(factory);
                    renderingMode = fontFace.GetRecommendedRenderingMode(fontSize, 1.0f, MeasuringMode.Natural, rtParams);
                    rtParams.Dispose();
                }
                else
                {
                    renderingMode = RenderingMode.Aliased;
                }

                using (var runAnalysis = new GlyphRunAnalysis(factory,
                                                              glyphRun,
                                                              1.0f,
                                                              matrix,
                                                              renderingMode,
                                                              MeasuringMode.Natural,
                                                              0.0f,
                                                              0.0f))
                {
                    var bounds = new RawRectangle(0, 0, pixelWidth, pixelHeight);
                    bitmap = new Bitmap(pixelWidth, pixelHeight, PixelFormat.Format32bppArgb);

                    if (renderingMode == RenderingMode.Aliased)
                    {
                        var texture = new byte[pixelWidth * pixelHeight];
                        runAnalysis.CreateAlphaTexture(TextureType.Aliased1x1, bounds, texture, texture.Length);
                        for (int y = 0; y < pixelHeight; y++)
                        {
                            for (int x = 0; x < pixelWidth; x++)
                            {
                                int pixelX = y * pixelWidth + x;
                                var grey   = texture[pixelX];
                                var color  = Color.FromArgb(grey, grey, grey);

                                bitmap.SetPixel(x, y, color);
                            }
                        }
                    }
                    else
                    {
                        var texture = new byte[pixelWidth * pixelHeight * 3];
                        runAnalysis.CreateAlphaTexture(TextureType.Cleartype3x1, bounds, texture, texture.Length);
                        for (int y = 0; y < pixelHeight; y++)
                        {
                            for (int x = 0; x < pixelWidth; x++)
                            {
                                int pixelX = (y * pixelWidth + x) * 3;
                                var red    = LinearToGamma(texture[pixelX]);
                                var green  = LinearToGamma(texture[pixelX + 1]);
                                var blue   = LinearToGamma(texture[pixelX + 2]);
                                var color  = Color.FromArgb(red, green, blue);

                                bitmap.SetPixel(x, y, color);
                            }
                        }
                    }
                }
            }

            var glyph = new Glyph(character, bitmap)
            {
                XOffset  = -matrix.M31,
                XAdvance = advanceWidth,
                YOffset  = -matrix.M32,
            };

            return(glyph);
        }
Пример #12
0
 internal static double FontSizeFromLinesInHeight(this FontMetrics metric, int lines, double height)
 => height * metric.DesignUnitsPerEm / DesignUnitsHeightForLines(metric, lines);
Пример #13
0
 internal static double HeightForLinesAtFontSize(this FontMetrics metric, int lines, double fontSize)
 => fontSize *DesignUnitsHeightForLines(metric, lines) / metric.DesignUnitsPerEm;
Пример #14
0
        private Glyph ImportGlyph(Factory factory, FontFace fontFace, char character, FontMetrics fontMetrics, float fontSize, bool activateAntiAliasDetection)
        {
            var indices = fontFace.GetGlyphIndices(new int[] {character});

            var metrics = fontFace.GetDesignGlyphMetrics(indices, false);
            var metric = metrics[0];

            var width = (float)(metric.AdvanceWidth - metric.LeftSideBearing - metric.RightSideBearing) / fontMetrics.DesignUnitsPerEm * fontSize;
            var height = (float)(metric.AdvanceHeight - metric.TopSideBearing - metric.BottomSideBearing) / fontMetrics.DesignUnitsPerEm * fontSize;

            var xOffset = (float)metric.LeftSideBearing / fontMetrics.DesignUnitsPerEm * fontSize;
            var yOffset = (float)(metric.TopSideBearing - metric.VerticalOriginY) / fontMetrics.DesignUnitsPerEm * fontSize;

            var advanceWidth = (float)(metric.AdvanceWidth) / fontMetrics.DesignUnitsPerEm * fontSize;
            var advanceHeight = (float)(metric.AdvanceHeight) / fontMetrics.DesignUnitsPerEm * fontSize;

            var pixelWidth = (int)Math.Ceiling(width + 2);
            var pixelHeight = (int)Math.Ceiling(height + 2);

            Bitmap bitmap;
            if(char.IsWhiteSpace(character))
            {
                bitmap = new Bitmap(1, 1, PixelFormat.Format32bppArgb);
            }
            else
            {
                var glyphRun = new GlyphRun()
                               {
                                   FontFace = fontFace,
                                   Advances = new[] { (float)Math.Round(advanceWidth) },
                                   FontSize = fontSize,
                                   BidiLevel = 0,
                                   Indices = indices,
                                   IsSideways = false,
                                   Offsets = new[] {new GlyphOffset()}
                               };

                var matrix = SharpDX.Matrix.Identity;
                matrix.M41 = -(float)Math.Floor(xOffset - 1);
                matrix.M42 = -(float)Math.Floor(yOffset - 1);

                RenderingMode renderingMode;
                if (activateAntiAliasDetection)
                {
                    var rtParams = new RenderingParams(factory);
                    renderingMode = fontFace.GetRecommendedRenderingMode(fontSize, 1.0f, MeasuringMode.Natural, rtParams);
                    rtParams.Dispose();
                }
                else
                {
                    renderingMode = RenderingMode.Aliased;
                }

                using(var runAnalysis = new GlyphRunAnalysis(factory,
                    glyphRun,
                    1.0f,
                    matrix,
                    renderingMode,
                    MeasuringMode.Natural,
                    0.0f,
                    0.0f))
                {
                    var bounds = new SharpDX.Rectangle(0, 0, pixelWidth, pixelHeight);
                    bitmap = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format32bppArgb);

                    if(renderingMode == RenderingMode.Aliased)
                    {
                        var texture = new byte[bounds.Width * bounds.Height];
                        runAnalysis.CreateAlphaTexture(TextureType.Aliased1x1, bounds, texture, texture.Length);
                        bitmap = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format32bppArgb);
                        for (int y = 0; y < bounds.Height; y++)
                        {
                            for (int x = 0; x < bounds.Width; x++)
                            {
                                int pixelX = y * bounds.Width + x;
                                var grey = texture[pixelX];
                                var color = Color.FromArgb(grey, grey, grey);

                                bitmap.SetPixel(x, y, color);
                            }
                        }
                    }
                    else
                    {
                        var texture = new byte[bounds.Width * bounds.Height * 3];
                        runAnalysis.CreateAlphaTexture(TextureType.Cleartype3x1, bounds, texture, texture.Length);
                        for (int y = 0; y < bounds.Height; y++)
                        {
                            for (int x = 0; x < bounds.Width; x++)
                            {
                                int pixelX = (y * bounds.Width + x) * 3;
                                var red = texture[pixelX];
                                var green = texture[pixelX + 1];
                                var blue = texture[pixelX + 2];
                                var color = Color.FromArgb(red, green, blue);

                                bitmap.SetPixel(x, y, color);
                            }
                        }
                    }

                    //var positionUnderline = (float)fontMetrics.UnderlinePosition / fontMetrics.DesignUnitsPerEm * fontSize;
                    //var positionUnderlineSize = (float)fontMetrics.UnderlineThickness / fontMetrics.DesignUnitsPerEm * fontSize;
                }
            }

            var glyph = new Glyph(character, bitmap)
                        {
                            XOffset = (float)Math.Floor(xOffset-1),
                            XAdvance = (float)Math.Round(advanceWidth),
                            YOffset = (float)Math.Floor(yOffset-1),
                        };
            return glyph;
        }
Пример #15
0
        protected bool ProduceGlyphRuns(FlowLayoutSink flowSink, ref RectangleF rect, ref ClusterPosition clusterStart, ref ClusterPosition clusterEnd)
        {
            // Produce a series of glyph runs from the given range
            // and send them to the sink. If the entire text fit
            // into the rect, then we'll only pass on a single glyph
            // run.

            ////////////////////////////////////////
            // Figure out how many runs we cross, because this is the number
            // of distinct glyph runs we'll need to reorder visually.

            int runIndexEnd = clusterEnd.runIndex;

            if (clusterEnd.textPosition > runs_[runIndexEnd].textStart)
            {
                ++runIndexEnd; // Only partially cover the run, so round up.
            }
            int[] bidiOrdering = new int[100];
            int   totalRuns    = Math.Min(bidiOrdering.Length, runIndexEnd - clusterStart.runIndex);

            ProduceBidiOrdering(clusterStart.runIndex, totalRuns, bidiOrdering);

            ////////////////////////////////////////
            // Ignore any trailing whitespace

            // Look backward from end until we find non-space.
            int trailingWsPosition;

            for (trailingWsPosition = clusterEnd.textPosition; trailingWsPosition > clusterStart.textPosition; --trailingWsPosition)
            {
                if (!breakpoints_[trailingWsPosition - 1].IsWhitespace)
                {
                    break; // Encountered last significant character.
                }
            }
            // Set the glyph run's ending cluster to the last whitespace.
            ClusterPosition clusterWsEnd = clusterStart;

            SetClusterPosition(ref clusterWsEnd, trailingWsPosition);

            ////////////////////////////////////////
            // Produce justified advances to reduce the jagged edge.
            List <float> justifiedAdvances;

            ProduceJustifiedAdvances(ref rect, ref clusterStart, ref clusterWsEnd, out justifiedAdvances);
            int justificationGlyphStart = GetClusterGlyphStart(ref clusterStart);
            ////////////////////////////////////////
            // Determine starting point for alignment.
            float x = rect.Left;
            float y = rect.Bottom;

            FontMetrics fontMetrics = fontFace_.Metrics;

            float descent = (fontMetrics.Descent * fontEmSize_ / fontMetrics.DesignUnitsPerEm);

            y -= descent;

            if (readingDirection_ == ReadingDirection.RightToLeft)
            {
                // For RTL, we neeed the run width to adjust the origin
                // so it starts on the right side.
                int glyphStart = GetClusterGlyphStart(ref clusterStart);
                int glyphEnd   = GetClusterGlyphStart(ref clusterWsEnd);

                if (glyphStart < glyphEnd)
                {
                    float lineWidth = GetClusterRangeWidth(
                        glyphStart - justificationGlyphStart,
                        glyphEnd - justificationGlyphStart,
                        justifiedAdvances.ToArray()
                        );
                    x = rect.Right - lineWidth;
                }
            }

            ////////////////////////////////////////
            // Send each glyph run to the sink.
            for (int i = 0; i < totalRuns; ++i)
            {
                Run run        = runs_[bidiOrdering[i]];
                int glyphStart = run.glyphStart;
                int glyphEnd   = glyphStart + run.glyphCount;

                // If the run is only partially covered, we'll need to find
                // the subsection of glyphs that were fit.
                if (clusterStart.textPosition > run.textStart)
                {
                    glyphStart = GetClusterGlyphStart(ref clusterStart);
                }
                if (clusterWsEnd.textPosition < run.textStart + run.textLength)
                {
                    glyphEnd = GetClusterGlyphStart(ref clusterWsEnd);
                }
                if ((glyphStart >= glyphEnd) || (run.script.Shapes == ScriptShapes.NoVisual))
                {
                    // The itemizer told us not to draw this character,
                    // either because it was a formatting, control, or other hidden character.
                    continue;
                }

                // The run width is needed to know how far to move forward,
                // and to flip the origin for right-to-left text.
                float runWidth = GetClusterRangeWidth(
                    glyphStart - justificationGlyphStart,
                    glyphEnd - justificationGlyphStart,
                    justifiedAdvances.ToArray()
                    );

                // Flush this glyph run.
                //int glyphCount = glyphEnd - glyphStart;
                int     glyphCount         = justifiedAdvances.Count;
                short[] call_glyphIndices_ = new short[glyphCount];
                Array.Copy(glyphIndices_, glyphStart, call_glyphIndices_, 0, call_glyphIndices_.Length);
                float[] call_justifiedAdvances = new float[justifiedAdvances.Count - (glyphStart - justificationGlyphStart)];
                justifiedAdvances.CopyTo(glyphStart - justificationGlyphStart, call_justifiedAdvances, 0, call_justifiedAdvances.Length);
                GlyphOffset[] call_glyphOffsets_ = new GlyphOffset[glyphCount];
                Array.Copy(glyphOffsets_, glyphStart, call_glyphOffsets_, 0, call_glyphOffsets_.Length);
                flowSink.SetGlyphRun(
                    (run.bidiLevel % 2 != 0) ? (x + runWidth) : (x), // origin starts from right if RTL
                    y,
                    glyphCount,
                    call_glyphIndices_,
                    call_justifiedAdvances,
                    call_glyphOffsets_,
                    fontFace_,
                    fontEmSize_,
                    run.bidiLevel,
                    run.isSideways
                    );

                x += runWidth;
            }
            return(true);
        }
Пример #16
0
        private Glyph ImportGlyph(Factory factory, FontFace fontFace, char character, FontMetrics fontMetrics, float fontSize, FontAntiAliasMode antiAliasMode)
        {
            var indices = fontFace.GetGlyphIndices(new int[] { character });

            var metrics = fontFace.GetDesignGlyphMetrics(indices, false);
            var metric = metrics[0];

            var width = (float)(metric.AdvanceWidth - metric.LeftSideBearing - metric.RightSideBearing) / fontMetrics.DesignUnitsPerEm * fontSize;
            var height = (float)(metric.AdvanceHeight - metric.TopSideBearing - metric.BottomSideBearing) / fontMetrics.DesignUnitsPerEm * fontSize;

            var xOffset = (float)metric.LeftSideBearing / fontMetrics.DesignUnitsPerEm * fontSize;
            var yOffset = (float)(metric.TopSideBearing - metric.VerticalOriginY) / fontMetrics.DesignUnitsPerEm * fontSize;

            var advanceWidth = (float)metric.AdvanceWidth / fontMetrics.DesignUnitsPerEm * fontSize;
            //var advanceHeight = (float)metric.AdvanceHeight / fontMetrics.DesignUnitsPerEm * fontSize;

            var pixelWidth = (int)Math.Ceiling(width + 4);
            var pixelHeight = (int)Math.Ceiling(height + 4);

            var matrix = new RawMatrix3x2
            {
                M11 = 1,
                M22 = 1,
                M31 = -(float)Math.Floor(xOffset) + 1,
                M32 = -(float)Math.Floor(yOffset) + 1
            };

            Bitmap bitmap;
            if (char.IsWhiteSpace(character))
            {
                bitmap = new Bitmap(1, 1, PixelFormat.Format32bppArgb);
            }
            else
            {
                var glyphRun = new GlyphRun
                {
                    FontFace = fontFace,
                    Advances = new[] { (float)Math.Ceiling(advanceWidth) },
                    FontSize = fontSize,
                    BidiLevel = 0,
                    Indices = indices,
                    IsSideways = false,
                    Offsets = new[] { new GlyphOffset() }
                };


                RenderingMode renderingMode;
                if (antiAliasMode != FontAntiAliasMode.Aliased)
                {
                    var rtParams = new RenderingParams(factory);
                    renderingMode = fontFace.GetRecommendedRenderingMode(fontSize, 1.0f, MeasuringMode.Natural, rtParams);
                    rtParams.Dispose();
                }
                else
                {
                    renderingMode = RenderingMode.Aliased;
                }

                using (var runAnalysis = new GlyphRunAnalysis(factory,
                    glyphRun,
                    1.0f,
                    matrix,
                    renderingMode,
                    MeasuringMode.Natural,
                    0.0f,
                    0.0f))
                {

                    var bounds = new RawRectangle(0, 0, pixelWidth, pixelHeight);
                    bitmap = new Bitmap(pixelWidth, pixelHeight, PixelFormat.Format32bppArgb);

                    if (renderingMode == RenderingMode.Aliased)
                    {

                        var texture = new byte[pixelWidth * pixelHeight];
                        runAnalysis.CreateAlphaTexture(TextureType.Aliased1x1, bounds, texture, texture.Length);
                        for (int y = 0; y < pixelHeight; y++)
                        {
                            for (int x = 0; x < pixelWidth; x++)
                            {
                                int pixelX = y * pixelWidth + x;
                                var grey = texture[pixelX];
                                var color = Color.FromArgb(grey, grey, grey);

                                bitmap.SetPixel(x, y, color);
                            }
                        }
                    }
                    else
                    {
                        var texture = new byte[pixelWidth * pixelHeight * 3];
                        runAnalysis.CreateAlphaTexture(TextureType.Cleartype3x1, bounds, texture, texture.Length);
                        for (int y = 0; y < pixelHeight; y++)
                        {
                            for (int x = 0; x < pixelWidth; x++)
                            {
                                int pixelX = (y * pixelWidth + x) * 3;
                                var red = LinearToGamma(texture[pixelX]);
                                var green = LinearToGamma(texture[pixelX + 1]);
                                var blue = LinearToGamma(texture[pixelX + 2]);
                                var color = Color.FromArgb(red, green, blue);

                                bitmap.SetPixel(x, y, color);
                            }
                        }
                    }
                }
            }

            var glyph = new Glyph(character, bitmap)
            {
                XOffset = -matrix.M31,
                XAdvance = advanceWidth,
                YOffset = -matrix.M32,
            };
            return glyph;
        }
            public override bool TryUpdatePosition(
                FontMetrics fontMetrics,
                GPosTable table,
                GlyphPositioningCollection collection,
                Tag feature,
                ushort index,
                int count)
            {
                // Implements Chained Contexts Substitution, Format 1:
                // https://docs.microsoft.com/en-us/typography/opentype/spec/gsub#61-chained-contexts-substitution-format-1-simple-glyph-contexts
                ushort glyphId = collection[index][0];

                if (glyphId == 0)
                {
                    return(false);
                }

                // Search for the current glyph in the Coverage table.
                int offset = this.coverageTable.CoverageIndexOf(glyphId);

                if (offset <= -1)
                {
                    return(false);
                }

                if (this.seqRuleSetTables is null || this.seqRuleSetTables.Length is 0)
                {
                    return(false);
                }

                ChainedSequenceRuleSetTable seqRuleSet = this.seqRuleSetTables[offset];

                if (seqRuleSet is null)
                {
                    return(false);
                }

                // Apply ruleset for the given glyph id.
                ChainedSequenceRuleTable[] rules    = seqRuleSet.SequenceRuleTables;
                SkippingGlyphIterator      iterator = new(fontMetrics, collection, index, this.LookupFlags);

                for (int lookupIndex = 0; lookupIndex < rules.Length; lookupIndex++)
                {
                    ChainedSequenceRuleTable rule = rules[lookupIndex];
                    if (!AdvancedTypographicUtils.ApplyChainedSequenceRule(iterator, rule))
                    {
                        continue;
                    }

                    bool hasChanged = false;
                    for (int j = 0; j < rule.SequenceLookupRecords.Length; j++)
                    {
                        SequenceLookupRecord sequenceLookupRecord = rule.SequenceLookupRecords[j];
                        LookupTable          lookup = table.LookupList.LookupTables[sequenceLookupRecord.LookupListIndex];
                        ushort sequenceIndex        = sequenceLookupRecord.SequenceIndex;
                        if (lookup.TryUpdatePosition(fontMetrics, table, collection, feature, (ushort)(index + sequenceIndex), 1))
                        {
                            hasChanged = true;
                        }
                    }

                    return(hasChanged);
                }

                return(false);
            }
            public override bool TryUpdatePosition(
                FontMetrics fontMetrics,
                GPosTable table,
                GlyphPositioningCollection collection,
                Tag feature,
                ushort index,
                int count)
            {
                // Implements Chained Contexts Substitution for Format 2:
                // https://docs.microsoft.com/en-us/typography/opentype/spec/gsub#62-chained-contexts-substitution-format-2-class-based-glyph-contexts
                ushort glyphId = collection[index][0];

                if (glyphId == 0)
                {
                    return(false);
                }

                // Search for the current glyph in the Coverage table.
                int offset = this.coverageTable.CoverageIndexOf(glyphId);

                if (offset <= -1)
                {
                    return(false);
                }

                // Search in the class definition table to find the class value assigned to the currently glyph.
                int classId = this.inputClassDefinitionTable.ClassIndexOf(glyphId);

                ChainedClassSequenceRuleTable[]? rules = classId >= 0 && classId < this.sequenceRuleSetTables.Length ? this.sequenceRuleSetTables[classId].SubRules : null;
                if (rules is null)
                {
                    return(false);
                }

                // Apply ruleset for the given glyph class id.
                SkippingGlyphIterator iterator = new(fontMetrics, collection, index, this.LookupFlags);

                for (int lookupIndex = 0; lookupIndex < rules.Length; lookupIndex++)
                {
                    ChainedClassSequenceRuleTable rule = rules[lookupIndex];
                    if (!AdvancedTypographicUtils.ApplyChainedClassSequenceRule(iterator, rule, this.inputClassDefinitionTable, this.backtrackClassDefinitionTable, this.lookaheadClassDefinitionTable))
                    {
                        continue;
                    }

                    // It's a match. Perform position update and return true if anything changed.
                    bool hasChanged = false;
                    for (int j = 0; j < rule.SequenceLookupRecords.Length; j++)
                    {
                        SequenceLookupRecord sequenceLookupRecord = rule.SequenceLookupRecords[j];
                        LookupTable          lookup = table.LookupList.LookupTables[sequenceLookupRecord.LookupListIndex];
                        ushort sequenceIndex        = sequenceLookupRecord.SequenceIndex;
                        if (lookup.TryUpdatePosition(fontMetrics, table, collection, feature, (ushort)(index + sequenceIndex), 1))
                        {
                            hasChanged = true;
                        }
                    }

                    return(hasChanged);
                }

                return(false);
            }
Пример #19
0
        public static string[] WrapWords(string source, int lineWidth, FontMetrics metrics)
        {
            int           pos              = 0;
            int           lastWrap         = 0;
            int           lastPossibleWrap = 0;
            int           curWidth         = 0;
            List <string> lines            = new List <string>();

            while (pos < source.Length)
            {
                char ch        = source[pos];
                int  charWidth = metrics.GetCharacterWidth(ch);

                if (ch == '\n')
                {
                    // wrap here
                    string line = source.Substring(lastWrap, pos - lastWrap);
                    lastWrap = lastPossibleWrap = pos;
                    curWidth = 0;

                    lines.Add(line.PadRight(line.Length + (lineWidth - StringWidth(line, metrics)) / metrics.HalfWidthHorizontalSpacing));
                }
                else if (curWidth + charWidth > lineWidth)
                {
                    if (lastPossibleWrap > lastWrap)
                    {
                        // check length of current word
                        int end = pos;
                        while (end < source.Length && !char.IsWhiteSpace(source[end]) && !IsFullWidthCharacter(source[end]))
                        {
                            end++;
                        }
                        string curWord = source.Substring(lastPossibleWrap, end - lastPossibleWrap).Trim();

                        if (StringWidth(curWord, metrics) > lineWidth)
                        {
                            // word wouldn't fit in its own line, so we keep its start on the current one and force a hard wrap (no padding)
                            lines.Add(source.Substring(lastWrap, pos - lastWrap));
                            lastWrap = lastPossibleWrap = pos;
                            curWidth = 0;
                        }
                        else
                        {
                            // push the current word to the next line
                            string line         = source.Substring(lastWrap, lastPossibleWrap - lastWrap);
                            int    curLineWidth = StringWidth(line, metrics);
                            lastWrap  = lastPossibleWrap;
                            curWidth -= curLineWidth;

                            // pad and add line
                            lines.Add(line.PadRight(line.Length + (lineWidth - curLineWidth) / metrics.HalfWidthHorizontalSpacing));
                        }
                    }
                    else
                    {
                        // force a hard wrap here (no padding)
                        lines.Add(source.Substring(lastWrap, pos - lastWrap));
                        lastWrap = lastPossibleWrap = pos;
                        curWidth = 0;
                    }
                }

                curWidth += charWidth;

                pos++;

                // allow soft wraps after each full-width character
                if (char.IsWhiteSpace(ch) || IsFullWidthCharacter(ch))
                {
                    lastPossibleWrap = pos;
                }
            }

            // add the last line
            if (pos > lastWrap)
            {
                string line = source.Substring(lastWrap, pos - lastWrap);
                if (line.Trim().Length > 0)
                {
                    lines.Add(line.PadRight(line.Length + (lineWidth - StringWidth(line, metrics)) / metrics.HalfWidthHorizontalSpacing));
                }
            }

            return(lines.ToArray());
        }
Пример #20
0
 public static int StringWidth(string str, FontMetrics metrics)
 {
     return(str.Aggregate(0, (int l, char ch) => l + metrics.GetCharacterWidth(ch)));
 }
        /// <summary>
        /// Imports a single glyph as a bitmap using the msdfgen to convert it to a signed distance field image
        /// </summary>
        /// <param name="fontFace">FontFace, use to obtain the metrics for the glyph</param>
        /// <param name="character">The glyph's character code</param>
        /// <param name="fontMetrics">Font metrics, used to obtain design units scale</param>
        /// <param name="fontSize">Requested font size. The bigger, the more precise the SDF image is going to be</param>
        /// <returns></returns>
        private Glyph ImportGlyph(FontFace fontFace, char character, FontMetrics fontMetrics, float fontSize)
        {
            var indices = fontFace.GetGlyphIndices(new int[] { character });

            var metrics = fontFace.GetDesignGlyphMetrics(indices, false);
            var metric = metrics[0];

            var width = (float)(metric.AdvanceWidth - metric.LeftSideBearing - metric.RightSideBearing) / fontMetrics.DesignUnitsPerEm * fontSize;
            var height = (float)(metric.AdvanceHeight - metric.TopSideBearing - metric.BottomSideBearing) / fontMetrics.DesignUnitsPerEm * fontSize;

            var xOffset = (float)metric.LeftSideBearing / fontMetrics.DesignUnitsPerEm * fontSize;
            var yOffset = (float)(metric.TopSideBearing - metric.VerticalOriginY) / fontMetrics.DesignUnitsPerEm * fontSize;

            var advanceWidth = (float)metric.AdvanceWidth / fontMetrics.DesignUnitsPerEm * fontSize;
            //var advanceHeight = (float)metric.AdvanceHeight / fontMetrics.DesignUnitsPerEm * fontSize;

            var pixelWidth = (int)Math.Ceiling(width + 4);
            var pixelHeight = (int)Math.Ceiling(height + 4);


            var matrixM31 = -(float)Math.Floor(xOffset) + 1;
            var matrixM32 = -(float)Math.Floor(yOffset) + 1;

            Bitmap bitmap;
            if (char.IsWhiteSpace(character))
            {
                bitmap = new Bitmap(1, 1, PixelFormat.Format32bppArgb);
            }
            else
            {
                bitmap = LoadSDFBitmap(character, pixelWidth, pixelHeight, 1, 1);
            }

            var glyph = new Glyph(character, bitmap)
            {
                XOffset = -matrixM31,
                XAdvance = advanceWidth,
                YOffset = -matrixM32,
            };

            return glyph;
        }
Пример #22
0
 internal static double XHeightForFontSize(this FontMetrics metric, double fontSize) => fontSize *Math.Abs(metric.XHeight) / metric.DesignUnitsPerEm;
Пример #23
0
        /**
          <summary>Loads the font data.</summary>
        */
        private void Load(
      )
        {
            LoadTableInfo();

              FontName = GetName(NameID_FontPostscriptName);

              Metrics = new FontMetrics();
              LoadTables();
              LoadCMap();
              LoadGlyphWidths();
              LoadGlyphKerning();
        }
Пример #24
0
 public Point SizeOfCharacter(int index)
 {
     return(FontMetrics.MeasureStringRounded(TokenText[index].ToString()));
 }
Пример #25
0
 internal static global::System.Runtime.InteropServices.HandleRef getCPtr(FontMetrics obj)
 {
     return((obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr);
 }
Пример #26
0
        private static FontDescriptors[] DrawFonts(Graphics g, int width, int height, Font[] fonts)
        {
            float hborder      = 4.0f;
            float safetyMargin = 2.0f * hborder;
            float y            = 0;
            float LHS          = safetyMargin;
            float x            = LHS;

            var descriptors = new FontDescriptors[fonts.Length];

            float lastHeight    = -1.0f;
            float nextRowHeight = -1.0f;

            for (int i = 0; i < fonts.Length; i++)
            {
                Font f = fonts[i];

                var metrics = FontMetrics.From(g, f);

                descriptors[i] = new FontDescriptors(f, metrics);

                IEnumerable <char> glyphs;

                glyphs = AnsiGlyphs;

                if (nextRowHeight < 0)
                {
                    nextRowHeight = metrics.Height;
                }

                if (lastHeight >= metrics.Height)
                {
                }
                else
                {
                    x = LHS;
                    if (lastHeight > 0)
                    {
                        y            += nextRowHeight + 1;
                        nextRowHeight = metrics.Height;
                    }
                }

                lastHeight = metrics.Height;

                var sf = StringFormat.GenericTypographic;

                foreach (char c in glyphs)
                {
                    if (!metrics.IsGlyphAvailable(c))
                    {
                        continue;
                    }

                    string s = new string(c, 1);

                    int A = metrics.GetA(c) - (int)hborder;
                    int B = metrics.GetB(c) + (int)safetyMargin;
                    int C = metrics.GetC(c) - (int)hborder;

                    float dx = (float)(B);
                    if (x + dx >= width)
                    {
                        x             = LHS;
                        y            += nextRowHeight + 1;
                        nextRowHeight = metrics.Height;
                    }

                    float Tx = x - (float)A;

                    descriptors[i].Add(c, A, B, C, (int)Tx, (int)y);

                    if (metrics.Height > 22)
                    {
                        g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
                    }
                    else
                    {
                        g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
                    }

                    TextRenderer.DrawText(g, s, f, new Point((int)Tx, (int)y), Color.White, TextFormatFlags.NoPadding);

                    //    g.DrawString(s, f, Brushes.White, new PointF(Tx, y), sf);

                    x += dx + safetyMargin;
                }
            }

            return(descriptors);
        }
Пример #27
0
 public static extern void DrawTextFontGetMetrics(IntPtr font, out FontMetrics metrics);
Пример #28
0
 public FontDescriptors(Font f, FontMetrics metrics)
 {
     Name   = f.Name;
     Height = f.Height;
     Ascent = metrics.Ascent;
 }
Пример #29
0
 internal static double LineGapForFontSize(this FontMetrics metric, double fontSize) => fontSize *Math.Abs(metric.LineGap) / metric.DesignUnitsPerEm;
Пример #30
0
        public virtual void paintComponent(Graphics paramGraphics)
        {
            if (Frame != null)
            {
                State = Frame.ExtendedState;
            }
            JRootPane jRootPane = RootPane;
            Window    window1   = Window;
            bool      @bool     = (window1 == null) ? jRootPane.ComponentOrientation.LeftToRight : window1.ComponentOrientation.LeftToRight;
            int       i         = Width;
            int       j         = Height;
            Color     color     = CostOSWindowsLookAndFeel.ribbonTaskTitleTextForegroundColor;

            if (!CostOSRibbonUI.Instance.BackstageShowing)
            {
                paramGraphics.Color = CostOSWindowsLookAndFeel.ribbonBackground;
                paramGraphics.fillRect(0, 0, i, j);
                paramGraphics.drawImage(this.ribbonArtImg, i - this.ribbonArtImg.getWidth(this), 0, this.ribbonArtImg.getWidth(this), this.ribbonArtImg.getHeight(this), this);
            }
            else
            {
                int m = CostOSRibbonApplicationMenuPopupPanel.FirstLevelMenuWidth;
                paramGraphics.Color = CostOSWindowsLookAndFeel.applicationBackground;
                paramGraphics.fillRect(0, 0, i, j);
                paramGraphics.Color = CostOSWindowsLookAndFeel.ribbonBackground;
                paramGraphics.fillRect(0, 0, m, Height);
                if (this.ribbonBackstageArtImg != null)
                {
                    paramGraphics.drawImage(this.ribbonBackstageArtImg, i - this.ribbonBackstageArtImg.getWidth(this), 0, this.ribbonBackstageArtImg.getWidth(this), this.ribbonBackstageArtImg.getHeight(this), this);
                }
                color = CostOSWindowsLookAndFeel.ribbonCommandButtonForegroundColor;
            }
            int k = @bool ? 5 : (i - 5);

            if (WindowDecorationStyle == 1)
            {
                k += (@bool ? 21 : -21);
            }
            string str = Title;

            if (!string.ReferenceEquals(str, null))
            {
                FontMetrics fontMetrics = SwingUtilities2.getFontMetrics(jRootPane, paramGraphics);
                int         m           = (j - fontMetrics.Height) / 2 + fontMetrics.Ascent;
                Rectangle   rectangle   = new Rectangle(0, 0, 0, 0);
                if (this.iconifyButton != null && this.iconifyButton.Parent != null)
                {
                    rectangle = this.iconifyButton.Bounds;
                }
                if (@bool)
                {
                    if (rectangle.x == 0)
                    {
                        rectangle.x = window1.Width - (window1.Insets).right - 2;
                    }
                    int i2 = rectangle.x - k - 4;
                    str = SwingUtilities2.clipStringIfNecessary(jRootPane, fontMetrics, str, i2);
                }
                else
                {
                    int i2 = k - rectangle.x - rectangle.width - 4;
                    str = SwingUtilities2.clipStringIfNecessary(jRootPane, fontMetrics, str, i2);
                    k  -= SwingUtilities2.stringWidth(jRootPane, fontMetrics, str);
                }
                int n = SwingUtilities2.stringWidth(jRootPane, fontMetrics, str);
                paramGraphics.Color = color;
                int i1 = (int)(i / 2.0F - n / 2.0F);
                SwingUtilities2.drawString(jRootPane, paramGraphics, str, i1, m);
                k += (@bool ? (n + 5) : -5);
            }
        }
Пример #31
0
 internal static double FontSizeFromLineHeight(this FontMetrics metric, double lineHeight)
 => FontSizeFromLinesInHeight(metric, 1, lineHeight);
Пример #32
0
        public static HopeFont CreateHopeFont(Typeface typeface)
        {
            int bitmapWH = 1024;

            int textSize = 160;

            // double scale = DeviceDisplay.MainDisplayInfo.Density;
            Paint paint = new Paint(PaintFlags.AntiAlias | PaintFlags.Dither)
            {
                Color    = Color.White,
                TextSize = textSize
            };

            paint.SetTypeface(typeface);
            paint.SetShadowLayer(0.4f, 0f, 1f, Color.DarkGray);

            // First create the canvas 1024x1024 with alpha
            Bitmap.Config bitmapConfig = Bitmap.Config.Argb8888;
            Bitmap        bitmap       = Bitmap.CreateBitmap(bitmapWH, bitmapWH, bitmapConfig);
            Canvas        canvas       = new Canvas(bitmap);

            Dictionary <char, Glyph> glyphs = new Dictionary <char, Glyph>();

            FontMetrics metrics    = paint.GetFontMetrics();
            float       lineHeight = metrics.Bottom - metrics.Top;
            float       ascent     = metrics.Ascent;

            List <char> missingChars = new List <char>();

            missingChars.AddRange(chars.ToCharArray());

            int currentLineIndex = 1;

            while (missingChars.Count > 0)
            {
                float  currentLineHeight = lineHeight * currentLineIndex;
                int    currentCharsCount;
                int    index = -1;
                string currentChars;
                do
                {
                    index++;
                    currentCharsCount = missingChars.Count - index;
                    currentChars      = string.Join("", missingChars.GetRange(0, currentCharsCount));
                } while (paint.MeasureText(currentChars) > bitmapWH);


                // Now we have the index of chars to write on this line

                missingChars.RemoveRange(0, currentCharsCount);
                canvas.DrawText(currentChars, 0, currentLineHeight, paint);

                float lastX = 0;
                foreach (char c in currentChars.ToCharArray())
                {
                    float[] widths = new float[1];
                    paint.GetTextWidths(c.ToString(), widths);
                    float width = widths[0];

                    float relativeAscent = lineHeight + ascent + 5;

                    float uvX = lastX / bitmapWH;
                    float uvY = (currentLineHeight + relativeAscent) / bitmapWH;
                    float uvW = width / bitmapWH;
                    float uvH = lineHeight / bitmapWH;

                    Glyph glyph = new Glyph(c, uvX, 1.0f - uvY, uvW, uvH);

                    glyphs.Add(c, glyph);
                    lastX += width;
                }

                currentLineIndex++;
            }

            return(new HopeFont(glyphs, new Texture(bitmap), lineHeight / bitmapWH));
        }
Пример #33
0
        /// <summary>
        /// Renders the <see cref="Duality.Resources.Font"/> using the specified system font.
        /// This method assumes that the system font's size and style match the one specified in
        /// the specified Duality font.
        /// </summary>
        private RenderedFontData RenderGlyphs(SysDrawFont internalFont, FontCharSet charSet, bool antialiazing, bool monospace)
        {
            DualityFont.GlyphData[] glyphs = new DualityFont.GlyphData[charSet.Chars.Length];
            for (int i = 0; i < glyphs.Length; i++)
            {
                glyphs[i].Glyph = charSet.Chars[i];
            }

            int bodyAscent = 0;
            int baseLine   = 0;
            int descent    = 0;
            int ascent     = 0;

            TextRenderingHint textRenderingHint;

            if (antialiazing)
            {
                textRenderingHint = TextRenderingHint.AntiAliasGridFit;
            }
            else
            {
                textRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit;
            }

            int cols;
            int rows;

            cols = rows = (int)Math.Ceiling(Math.Sqrt(glyphs.Length));

            PixelData pixelLayer = new PixelData(
                MathF.RoundToInt(cols * internalFont.Size * 1.2f),
                MathF.RoundToInt(rows * internalFont.Height * 1.2f),
                ColorRgba.TransparentBlack);
            PixelData glyphTemp;
            PixelData glyphTempTypo;
            Bitmap    bm;
            Bitmap    measureBm = new Bitmap(1, 1);

            Rect[] atlas = new Rect[glyphs.Length];
            using (Graphics measureGraphics = Graphics.FromImage(measureBm))
            {
                Brush fntBrush = new SolidBrush(Color.Black);

                StringFormat formatDef = StringFormat.GenericDefault;
                formatDef.LineAlignment = StringAlignment.Near;
                formatDef.FormatFlags   = 0;
                StringFormat formatTypo = StringFormat.GenericTypographic;
                formatTypo.LineAlignment = StringAlignment.Near;

                int x = 1;
                int y = 1;
                for (int i = 0; i < glyphs.Length; ++i)
                {
                    string str      = glyphs[i].Glyph.ToString(CultureInfo.InvariantCulture);
                    bool   isSpace  = str == " ";
                    SizeF  charSize = measureGraphics.MeasureString(str, internalFont, pixelLayer.Width, formatDef);

                    // Rasterize a single glyph for rendering
                    bm = new Bitmap((int)Math.Ceiling(Math.Max(1, charSize.Width)), internalFont.Height + 1);
                    using (Graphics glyphGraphics = Graphics.FromImage(bm))
                    {
                        glyphGraphics.Clear(Color.Transparent);
                        glyphGraphics.TextRenderingHint = textRenderingHint;
                        glyphGraphics.DrawString(str, internalFont, fntBrush, new RectangleF(0, 0, bm.Width, bm.Height), formatDef);
                    }
                    glyphTemp = new PixelData();
                    glyphTemp.FromBitmap(bm);

                    // Rasterize a single glyph in typographic mode for metric analysis
                    if (!isSpace)
                    {
                        Point2 glyphTempOpaqueTopLeft;
                        Point2 glyphTempOpaqueSize;
                        glyphTemp.GetOpaqueBoundaries(out glyphTempOpaqueTopLeft, out glyphTempOpaqueSize);

                        glyphTemp.SubImage(glyphTempOpaqueTopLeft.X, 0, glyphTempOpaqueSize.X, glyphTemp.Height);

                        if (charSet.CharBodyAscentRef.Contains(glyphs[i].Glyph))
                        {
                            bodyAscent += glyphTempOpaqueSize.Y;
                        }
                        if (charSet.CharBaseLineRef.Contains(glyphs[i].Glyph))
                        {
                            baseLine += glyphTempOpaqueTopLeft.Y + glyphTempOpaqueSize.Y;
                        }
                        if (charSet.CharDescentRef.Contains(glyphs[i].Glyph))
                        {
                            descent += glyphTempOpaqueTopLeft.Y + glyphTempOpaqueSize.Y;
                        }

                        bm = new Bitmap((int)Math.Ceiling(Math.Max(1, charSize.Width)), internalFont.Height + 1);
                        using (Graphics glyphGraphics = Graphics.FromImage(bm))
                        {
                            glyphGraphics.Clear(Color.Transparent);
                            glyphGraphics.TextRenderingHint = textRenderingHint;
                            glyphGraphics.DrawString(str, internalFont, fntBrush, new RectangleF(0, 0, bm.Width, bm.Height), formatTypo);
                        }
                        glyphTempTypo = new PixelData();
                        glyphTempTypo.FromBitmap(bm);
                        glyphTempTypo.Crop(true, false);
                    }
                    else
                    {
                        glyphTempTypo = glyphTemp;
                    }

                    // Update xy values if it doesn't fit anymore
                    if (x + glyphTemp.Width + 2 > pixelLayer.Width)
                    {
                        x  = 1;
                        y += internalFont.Height + MathF.Clamp((int)MathF.Ceiling(internalFont.Height * 0.1875f), 3, 10);
                    }

                    // Memorize atlas coordinates & glyph data
                    glyphs[i].Width   = glyphTemp.Width;
                    glyphs[i].Height  = glyphTemp.Height;
                    glyphs[i].OffsetX = glyphTemp.Width - glyphTempTypo.Width;
                    glyphs[i].OffsetY = 0;                     // ttf fonts are rendered on blocks that are the whole size of the height - so no need for offset
                    if (isSpace)
                    {
                        glyphs[i].Width   /= 2;
                        glyphs[i].OffsetX /= 2;
                    }
                    atlas[i].X = x;
                    atlas[i].Y = y;
                    atlas[i].W = glyphTemp.Width;
                    atlas[i].H = (internalFont.Height + 1);

                    // Draw it onto the font surface
                    glyphTemp.DrawOnto(pixelLayer, BlendMode.Solid, x, y);

                    x += glyphTemp.Width + MathF.Clamp((int)MathF.Ceiling(internalFont.Height * 0.125f), 2, 10);
                }
            }

            // White out texture except alpha channel.
            for (int i = 0; i < pixelLayer.Data.Length; i++)
            {
                pixelLayer.Data[i].R = 255;
                pixelLayer.Data[i].G = 255;
                pixelLayer.Data[i].B = 255;
            }

            // Monospace offset adjustments
            if (monospace)
            {
                int maxGlyphWidth = 0;
                for (int i = 0; i < glyphs.Length; i++)
                {
                    maxGlyphWidth = Math.Max(maxGlyphWidth, glyphs[i].Width);
                }
                for (int i = 0; i < glyphs.Length; ++i)
                {
                    glyphs[i].OffsetX -= (int)Math.Round((maxGlyphWidth - glyphs[i].Width) / 2.0f);
                }
            }

            // Determine Font properties
            {
                float lineSpacing = internalFont.FontFamily.GetLineSpacing(internalFont.Style);
                float emHeight    = internalFont.FontFamily.GetEmHeight(internalFont.Style);
                float cellAscent  = internalFont.FontFamily.GetCellAscent(internalFont.Style);
                float cellDescent = internalFont.FontFamily.GetCellDescent(internalFont.Style);

                ascent      = (int)Math.Round(cellAscent * internalFont.Size / emHeight);
                bodyAscent /= charSet.CharBodyAscentRef.Length;
                baseLine   /= charSet.CharBaseLineRef.Length;
                descent     = (int)Math.Round(((float)descent / charSet.CharDescentRef.Length) - (float)baseLine);
            }

            // Aggregate rendered and generated data into our return value
            FontMetrics metrics = new FontMetrics(
                size:       internalFont.SizeInPoints,
                height:     (int)internalFont.Height,
                ascent:     ascent,
                bodyAscent: bodyAscent,
                descent:    descent,
                baseLine:   baseLine,
                monospace:  monospace);

            return(new RenderedFontData
            {
                Bitmap = pixelLayer,
                Atlas = atlas,
                GlyphData = glyphs,
                Metrics = metrics
            });
        }
Пример #34
0
            public virtual void layoutContainer(Container param1Container)
            {
                Insets insets = param1Container.Insets;
                int    i      = outerInstance.TabButtonGap;
                bool   bool1  = outerInstance.ribbon.ComponentOrientation.LeftToRight;
                int    j      = param1Container.Width;
                int    k      = outerInstance.TaskbarHeight;
                int    m      = insets.top;
                bool   bool2  = outerInstance.UsingTitlePane;

                if (!bool2)
                {
                    outerInstance.taskBarPanel.removeAll();
                    foreach (Component component in outerInstance.ribbon.TaskbarComponents)
                    {
                        outerInstance.taskBarPanel.add(component);
                    }
                    outerInstance.taskBarPanel.setBounds(insets.left, insets.top, j - insets.left - insets.right, k);
                    m += k;
                }
                else
                {
                    outerInstance.taskBarPanel.setBounds(0, 0, 0, 0);
                }
                Font font = outerInstance.ribbon.Font;

                if (font == null)
                {
                    font = new Font("SansSerif", 0, 12);
                    outerInstance.ribbon.Font = font;
                }
                FontMetrics fontMetrics = outerInstance.ribbon.getFontMetrics(font);
                int         n           = fontMetrics.stringWidth(CostOSRibbonApplicationMenuButtonUI.ApplicationMenuButtonText) + 24;
                int         i1;

                for (i1 = 0; i1 < outerInstance.ribbon.TaskCount; i1++)
                {
                    RibbonTask ribbonTask = outerInstance.ribbon.getTask(i1);
                    n += fontMetrics.stringWidth(ribbonTask.Title) + 32;
                }
                n += 12;
                i1 = outerInstance.TaskToggleButtonHeight;
                int i2 = bool1 ? insets.left : (j - insets.right);
                int i3 = k + i1;

                if (!bool2)
                {
                    outerInstance.applicationMenuButton.Visible = (outerInstance.ribbon.ApplicationMenu != null);
                    if (outerInstance.ribbon.ApplicationMenu != null)
                    {
                        if (bool1)
                        {
                            outerInstance.applicationMenuButton.setBounds(-5, insets.top, i3 + 24, i3);
                        }
                        else
                        {
                            outerInstance.applicationMenuButton.setBounds(i2 - i3, insets.top, i3, i3);
                        }
                    }
                }
                else
                {
                    outerInstance.applicationMenuButton.Visible = false;
                }
                i2 = bool1 ? (i2 + 2) : (i2 - 2);
                if (FlamingoUtilities.getApplicationMenuButton(SwingUtilities.getWindowAncestor(outerInstance.ribbon)) != null)
                {
                    i2 = bool1 ? (i2 + i3 + 15) : (i2 - i3);
                }
                if (outerInstance.o_trailingButton != null && outerInstance.helpButton == null)
                {
                    Dimension dimension = outerInstance.o_trailingButton.PreferredSize;
                    if (bool1)
                    {
                        outerInstance.o_trailingButton.setBounds(j - insets.right - dimension.width, m, dimension.width, dimension.height);
                    }
                    else
                    {
                        outerInstance.o_trailingButton.setBounds(insets.left, m, dimension.width, dimension.height);
                    }
                    if (outerInstance.o_searchButton != null)
                    {
                        Dimension dimension1 = outerInstance.o_searchButton.PreferredSize;
                        if (bool1)
                        {
                            outerInstance.o_searchButton.setBounds(n, m, dimension1.width, dimension1.height);
                        }
                        else
                        {
                            outerInstance.o_searchButton.setBounds(insets.left + dimension1.width, m, dimension1.width, dimension1.height);
                        }
                    }
                }
                if (outerInstance.helpButton != null)
                {
                    Dimension dimension = outerInstance.helpButton.PreferredSize;
                    if (bool1)
                    {
                        outerInstance.helpButton.setBounds(j - insets.right - dimension.width, m, dimension.width, dimension.height);
                    }
                    else
                    {
                        outerInstance.helpButton.setBounds(insets.left, m, dimension.width, dimension.height);
                    }
                    if (outerInstance.o_trailingButton != null)
                    {
                        Dimension dimension1 = outerInstance.o_trailingButton.PreferredSize;
                        if (bool1)
                        {
                            outerInstance.o_trailingButton.setBounds(j - insets.right * 2 - dimension1.width + dimension.width, m, dimension1.width, dimension1.height);
                        }
                        else
                        {
                            outerInstance.o_trailingButton.setBounds(insets.left + dimension1.width, m, dimension1.width, dimension1.height);
                        }
                    }
                }
                int i4 = 0;

                if (bool1)
                {
                    i4 = (outerInstance.o_trailingButton != null) ? (outerInstance.o_trailingButton.X - i - i2) : (param1Container.Width - insets.right - i2);
                    if (outerInstance.helpButton != null && outerInstance.o_trailingButton != null)
                    {
                        i4 = outerInstance.o_trailingButton.X - i - i2;
                    }
                    if (outerInstance.o_searchButton != null && outerInstance.o_trailingButton != null)
                    {
                        i4 = outerInstance.o_searchButton.X - i - i2;
                    }
                    outerInstance.taskToggleButtonsScrollablePanel.setBounds(i2, m, i4, i1);
                }
                else
                {
                    i4 = (outerInstance.helpButton != null) ? (i2 - i - outerInstance.helpButton.X - outerInstance.o_trailingButton.Width) : (i2 - insets.left);
                    if (outerInstance.helpButton != null && outerInstance.o_trailingButton != null)
                    {
                        i4 = i2 - i - outerInstance.o_trailingButton.X - outerInstance.o_trailingButton.Width - outerInstance.helpButton.X - outerInstance.helpButton.Width;
                    }
                    outerInstance.taskToggleButtonsScrollablePanel.setBounds(i2 - i4, m, i4, i1);
                }
                BasicRibbonUI.TaskToggleButtonsHostPanel taskToggleButtonsHostPanel = (BasicRibbonUI.TaskToggleButtonsHostPanel)outerInstance.taskToggleButtonsScrollablePanel.View;
                int i5 = (taskToggleButtonsHostPanel.MinimumSize).width;

                taskToggleButtonsHostPanel.PreferredSize = new Dimension(i5, (this.this$0.taskToggleButtonsScrollablePanel.Bounds).height);
                outerInstance.taskToggleButtonsScrollablePanel.doLayout();
                m += i1;
                int i6 = i1;

                if (!bool2)
                {
                    i6 += k;
                }
                if (outerInstance.bandScrollablePanel.Parent == outerInstance.ribbon)
                {
                    if (!outerInstance.ribbon.Minimized && outerInstance.ribbon.TaskCount > 0)
                    {
                        Insets insets1 = (outerInstance.ribbon.SelectedTask.BandCount == 0) ? new Insets(0, 0, 0, 0) : outerInstance.ribbon.SelectedTask.getBand(0).Insets;
                        outerInstance.bandScrollablePanel.setBounds(1 + insets.left, m + insets1.top, param1Container.Width - 2 * insets.left - 2 * insets.right - 1, param1Container.Height - i6 - insets.top - insets.bottom - insets1.top - insets1.bottom);
                        BasicRibbonUI.BandHostPanel bandHostPanel = (BasicRibbonUI.BandHostPanel)outerInstance.bandScrollablePanel.View;
                        int i7 = (bandHostPanel.MinimumSize).width;
                        bandHostPanel.PreferredSize = new Dimension(i7, (this.this$0.bandScrollablePanel.Bounds).height);
                        outerInstance.bandScrollablePanel.doLayout();
                        bandHostPanel.doLayout();
                    }
                    else
                    {
                        outerInstance.bandScrollablePanel.setBounds(0, 0, 0, 0);
                    }
                }
            }
Пример #35
0
 public static double GetDefaultBaseline(FontMetrics fontMetrics)
 {
     return(Math.Abs(fontMetrics.Ascent));
 }
Пример #36
0
        /// <summary>
        ///   This method determines the common baselines for the paragraph.
        /// </summary>
        private void DetermineBaselines()
        {
            float baselineOffset = 0.0f;
            float strikethroughOffset = 0.0f;
            float underlineOffset = 0.0f;
            float strikethroughThickness = 0.0f;
            float underlineThickness = 0.0f;

            foreach(FormattedRun run in _OutputSink.Runs)
            {
                DxFontMetrics dxMetrics = run.Font.ResolveFace().Metrics;

                FontMetrics metrics = new FontMetrics(
                    dxMetrics.Ascent, dxMetrics.Descent, dxMetrics.DesignUnitsPerEm);

                float blo = metrics.Measure(dxMetrics.Ascent + dxMetrics.Descent, run.PointSize);
                float sto = metrics.Measure(dxMetrics.StrikethroughPosition, run.PointSize);
                float ulo = metrics.Measure(dxMetrics.UnderlinePosition, run.PointSize);
                float stt = metrics.Measure(dxMetrics.StrikethroughThickness, run.PointSize);
                float ult = metrics.Measure(dxMetrics.UnderlineThickness, run.PointSize);

                baselineOffset = TakeAbsMax(baselineOffset, blo);
                strikethroughOffset = TakeAbsMax(strikethroughOffset, sto);
                underlineOffset = TakeAbsMax(underlineOffset, ulo);
                strikethroughThickness = TakeAbsMax(strikethroughThickness, stt);
                underlineThickness = TakeAbsMax(underlineThickness, ult);
            }

            _OutputSink.BaselineOffset = baselineOffset;
            _OutputSink.StrikethroughOffset = strikethroughOffset;
            _OutputSink.StrikethroughThickness = strikethroughThickness;
            _OutputSink.UnderlineOffset = underlineOffset;
            _OutputSink.UnderlineThickness = underlineThickness;
        }