private static void GetKerningInfo(CCRawList<char> charset) { _abcValues.Clear(); var fontFace = new FontFace(_currentFont); var value = new ABCFloat[1]; var glyphRun = new GlyphRun(); glyphRun.FontFace = fontFace; glyphRun.FontSize = _currentDIP; var BrushColor = SharpDX.Color.White; /* SharpDX.DirectWrite.Matrix mtrx = new SharpDX.DirectWrite.Matrix(); mtrx.M11 = 1F; mtrx.M12 = 0; mtrx.M21 = 0; mtrx.M22 = 1F; mtrx.Dx = 0; mtrx.Dy = 0; */ //GlyphMetrics[] metrics = fontFace.GetGdiCompatibleGlyphMetrics(23, 1, mtrx, false, glyphIndices, false); //FontMetrics metr = fontFace.GetGdiCompatibleMetrics(23, 1, new SharpDX.DirectWrite.Matrix()); //_pRenderTarget.DrawGlyphRun(new SharpDX.DrawingPointF(left, top), glyphRun, new SharpDX.Direct2D1.SolidColorBrush(_pRenderTarget, BrushColor), MeasuringMode.GdiClassic); int[] codePoints = new int[1]; var unitsPerEm = fontFace.Metrics.DesignUnitsPerEm; var familyName = _currentFont.ToString(); for (int i = 0; i < charset.Count; i++) { var ch = charset[i]; if (!_abcValues.ContainsKey(ch)) { var textLayout = new TextLayout(FactoryDWrite, ch.ToString(), textFormat, unitsPerEm, unitsPerEm); var tlMetrics = textLayout.Metrics; var tlmWidth = tlMetrics.Width; var tllWidth = tlMetrics.LayoutWidth; codePoints[0] = (int)ch; short[] glyphIndices = fontFace.GetGlyphIndices(codePoints); glyphRun.Indices = glyphIndices; var metrics = fontFace.GetDesignGlyphMetrics(glyphIndices, false); //var width = metrics[0].AdvanceWidth + metrics[0].LeftSideBearing + metrics[0].RightSideBearing; //var glyphWidth = _currentFontSizeEm * (float)metrics[0].AdvanceWidth / unitsPerEm; //var abcWidth = _currentDIP * (float)width / unitsPerEm; //value[0].abcfA = _currentFontSizeEm * (float)metrics[0].LeftSideBearing / unitsPerEm; //value[0].abcfB = _currentFontSizeEm * (float)metrics[0].AdvanceWidth / unitsPerEm; //value[0].abcfC = _currentFontSizeEm * (float)metrics[0].RightSideBearing / unitsPerEm; // The A and C values are throwing the spacing off //value[0].abcfA = _currentDIP * (float)metrics[0].LeftSideBearing / unitsPerEm; value[0].abcfB = _currentDIP * (float)metrics[0].AdvanceWidth / unitsPerEm; //value[0].abcfC = _currentDIP * (float)metrics[0].RightSideBearing / unitsPerEm; _abcValues.Add( ch, new KerningInfo() { A = value[0].abcfA, B = value[0].abcfB, C = value[0].abcfC }); } } }
/// <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; }
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; }
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; }