예제 #1
0
        private static FontData GetFontData(Typeface typeface, double fontSize)
        {
            if (!typeface.Equals(cachedTypeface) || fontSize != cachedFontSize)
            {
                if (!typeface.TryGetGlyphTypeface(out GlyphTypeface glyphTypeface))
                {
                    defaultTypface.TryGetGlyphTypeface(out glyphTypeface);
                }
                bool charactersFound = GetTextBounds(glyphTypeface, fontSize, out double topDistance, out double bottomDistance);

                fontCache = new FontData(glyphTypeface, topDistance, bottomDistance, charactersFound);

                cachedTypeface = typeface;
                cachedFontSize = fontSize;
            }

            return(fontCache);
        }
예제 #2
0
        public static double FontHeight(Typeface typeface, double fontSize, double dpiScale)
        {
            FontData fontData = GetFontData(typeface, fontSize);

            if (!fontData.HeightsCalculated)
            {
                return(MeasureText("A", typeface, fontSize, dpiScale).Height);
            }

            double topDistance = fontData.TopDistance;

            if (fontData.GlyphTypeface.Baseline * fontSize > fontData.TopDistance)
            {
                topDistance = fontData.GlyphTypeface.Baseline * fontSize * fontData.GlyphTypeface.Height;
            }

            return((Math.Ceiling(topDistance / dpiScale) * dpiScale) + (Math.Ceiling(fontData.BottomDistance / dpiScale) * dpiScale));
        }
예제 #3
0
        internal static GlyphRun CreateGlyphRun(string text, Typeface typeface, double fontSize, double dpiScale, double glyphRunStartPosition, out double runWidth)
        {
            if (text.Length == 0)
            {
                runWidth = 0;
                return(null);
            }

            FontData fontData = GetFontData(typeface, fontSize);

            ushort[] glyphIndexes  = new ushort[text.Length];
            double[] advanceWidths = new double[text.Length];

            double totalWidth = 0;
            int    codePoint;

            for (int n = 0; n < text.Length; n++)
            {
                // C# uses UTF16 encoded strings which for some characters requires 2 surrogate pair chars to encode
                // one character, if so we add a zero width space glyph after the real glyph to keep the number of
                // glyphs in the glyph run the same as the number of chars in the string to easier map mouse clicks
                // to whole characters in case a surrogate pair is used.
                if (char.IsHighSurrogate(text[n]))
                {
                    codePoint = char.ConvertToUtf32(text, n);
                }
                else if (char.IsLowSurrogate(text[n]))
                {
                    codePoint = '\u200B';
                }
                else
                {
                    codePoint = text[n];
                }

                ushort glyphIndex = ReplaceGlyph(codePoint, fontData.GlyphTypeface, fontSize, dpiScale, glyphRunStartPosition + totalWidth, out double width);

                glyphIndexes[n]  = glyphIndex;
                advanceWidths[n] = width;

                totalWidth += width;
            }

            double maxTopDistance = fontData.TopDistance;

            if (fontData.GlyphTypeface.Baseline * fontSize > maxTopDistance || !fontData.HeightsCalculated)
            {
                maxTopDistance = fontData.GlyphTypeface.Baseline * fontSize * fontData.GlyphTypeface.Height;
            }

            maxTopDistance = Math.Ceiling(maxTopDistance / dpiScale) * dpiScale;

            GlyphRun run = new GlyphRun(
                glyphTypeface: fontData.GlyphTypeface,
                bidiLevel: 0,
                isSideways: false,
                renderingEmSize: Math.Ceiling(fontSize / dpiScale) * dpiScale,
                pixelsPerDip: (float)dpiScale,
                glyphIndices: glyphIndexes,
                baselineOrigin: new Point(0, maxTopDistance),
                advanceWidths: advanceWidths,
                glyphOffsets: null,
                characters: null,
                deviceFontName: null,
                clusterMap: null,
                caretStops: null,
                language: null);

            runWidth = totalWidth;
            return(run);
        }