【问题标题】:SharpDx: Setting character widthSharpDx:设置字符宽度
【发布时间】:2017-09-20 12:12:08
【问题描述】:

我正在使用 SharpDX 编写 C# Direct2D 应用程序,但是我可以理解 C++ 中提供的答案/示例。

我想渲染文本并更改某些字符的宽度以看起来像图片:

字母B扩大到200%,字母D缩小到50%

在下面的代码中,我绘制了字形的几何形状 所以可以改变几何的宽度 但这不是一个好的解决方案,因为绘制出来的几何图形就像您在图片中看到的那样模糊。

总之,有两个问题:

  1. 如何更改字符的宽度?

  2. 如何在不模糊的情况下绘制字母的几何形状。 (可以用 ClearType 渲染几何图形吗?)

    private void RenderGlyphRun1(FontFace1 fontFace)
    {
        var Offsets = new List<GlyphOffset>();
        var fontEmSize_ = 12;
        GlyphRun glyphRun = new GlyphRun();
        glyphRun.FontFace = fontFace;
        glyphRun.FontSize = fontEmSize_;
        glyphRun.BidiLevel = 1;
        var left = 650f;
        var top = 50f;
    
        var baseLine = (float)(fontFace.Metrics.LineGap + fontFace.Metrics.Ascent) /
            fontFace.Metrics.DesignUnitsPerEm * glyphRun.FontSize;
    
        string textToDraw = "ABCDE";
        foreach (char letter in textToDraw)
        {
            Offsets.Add(new GlyphOffset());
        }
    
        var charArr = textToDraw.Select(x => (int)x).ToArray();
        glyphRun.Indices = fontFace.GetGlyphIndices(charArr);
    
        var metrics = fontFace.GetDesignGlyphMetrics(glyphRun.Indices, false);
        glyphRun.Advances = metrics.Select(x => (float)x.AdvanceWidth /
                 fontFace.Metrics.DesignUnitsPerEm * glyphRun.FontSize).ToArray();
    
        glyphRun.Offsets = Offsets.ToArray();
    
        RenderTarget2D.BeginDraw();
        RenderTarget2D.Clear(SharpDX.Color.White);
    
        RenderTarget2D.DrawGlyphRun(new Vector2(left, top),
            glyphRun, new SharpDX.Direct2D1.SolidColorBrush(RenderTarget2D, SharpDX.Color.Black),
            MeasuringMode.Natural);
    
        top += baseLine;
    
        var pathGeometry = new PathGeometry(Factory2D);
        var geometrySink = pathGeometry.Open();
    
        fontFace.GetGlyphRunOutline(glyphRun.FontSize, glyphRun.Indices,
            glyphRun.Advances, glyphRun.Offsets, glyphRun.IsSideways,
            glyphRun.BidiLevel % 2 != 0, geometrySink);
    
        geometrySink.Close();
        geometrySink.Dispose();
        fontFace.Dispose();
    
        var matrix = new Matrix3x2()
        {
            M11 = 1,
            M12 = 0,
            M21 = 0,
            M22 = 1,
            M31 = left,
            M32 = top
        };
    
        var transformedGeometry = new TransformedGeometry(Factory2D, pathGeometry, matrix);
        var brushColor = (Color4)SharpDX.Color.Black;
        var brush = new SolidColorBrush(RenderTarget2D, brushColor);
        RenderTarget2D.FillGeometry(transformedGeometry, brush);
    
        pathGeometry.Dispose();
        transformedGeometry.Dispose();
        brush.Dispose();
    
        RenderTarget2D.EndDraw();
    }       
    

【问题讨论】:

  • 我认为您需要分别为每个字符/字形 RenderTarget2D.FillGeometry。您还可以在矩阵中指定每个字形的比例。
  • @VuVirt You can also specify each glyph's scale in the matrix 你什么意思?请举个例子。

标签: c# c++ directx sharpdx directwrite


【解决方案1】:

由于有些字母应该是窄的,有些是正常的,有些是宽的,所以你不能使用一个GlyphRun,而必须创建3个不同的GlyphRun

使任何GlyphRun 的所有字母变宽或变窄:

  1. Transform 配置为RenderTarget
  2. 绘制GlyphRun
  3. 返回原Transform

宽变换:RenderTarget2D.Transform = new SharpDX.Mathematics.Interop.RawMatrix3x2(1.5f, 0, 0, 1, 0, 0);

窄变换:RenderTarget2D.Transform = new SharpDX.Mathematics.Interop.RawMatrix3x2(0.5f, 0, 0, 1, 0, 0);

使用此解决方案后,您无需将GlyphRun 转换为geometry 并与模糊字母混淆。

【讨论】:

    【解决方案2】:

    Direct2D 文本呈现功能分两部分提供:

    1) DrawTextDrawTextLayout 方法,使调用者能够传递字符串和格式参数或用于多种格式的 DWrite 文本布局对象。这应该适合大多数来电者。

    2) 第二种方式是渲染文本,公开为DrawGlyphRun 方法,为已经知道要渲染的字形位置的客户提供光栅化。在 Direct2D 中绘图时,以下两条通用规则有助于提高文本性能。

    我现在看到您使用的是第二种方法,但是在第一种方法中,您可以将渲染设置为ClearType

    RenderTarget2D.TextAntialiasMode = TextAntialiasMode.Cleartype;
    

    我不确定如何将它包含在您的示例中,但 Sharp DX 示例如下所示:

    using System;
    using SharpDX;
    using SharpDX.Direct2D1;
    using SharpDX.DirectWrite;
    using SharpDX.Samples;
    using TextAntialiasMode = SharpDX.Direct2D1.TextAntialiasMode;
    
    namespace TextRenderingApp
    {
      public class Program : Direct2D1DemoApp
      {        
        public TextFormat TextFormat { get; private set; }
        public TextLayout TextLayout { get; private set; }
    
        protected override void Initialize(DemoConfiguration demoConfiguration)
        {
            base.Initialize(demoConfiguration);
    
            // Initialize a TextFormat
            TextFormat = new TextFormat(FactoryDWrite, "Calibri", 128) {TextAlignment = TextAlignment.Center, ParagraphAlignment = ParagraphAlignment.Center};
    
            RenderTarget2D.TextAntialiasMode = TextAntialiasMode.Cleartype;
    
            // Initialize a TextLayout
            TextLayout = new TextLayout(FactoryDWrite, "SharpDX D2D1 - DWrite", TextFormat, demoConfiguration.Width, demoConfiguration.Height);
        }
    
    
        protected override void Draw(DemoTime time)
        {
            base.Draw(time);
    
            // Draw the TextLayout
            RenderTarget2D.DrawTextLayout(new Vector2(0,0), TextLayout, SceneColorBrush, DrawTextOptions.None );
        }
    
    
        [STAThread]
        static void Main(string[] args)
        {
            Program program = new Program();
            program.Run(new DemoConfiguration("SharpDX DirectWrite Text Rendering Demo"));
        }
      }
    }
    

    样本取自:https://github.com/sharpdx/SharpDX-Samples/blob/master/Desktop/Direct2D1/TextRenderingApp

    【讨论】:

    • 请解释一下您的回答如何回答我的问题? How I change the width of the characters? How to draw geometries of letters without blurring. (it is possible to render geometry with ClearType?)
    • 很遗憾你的回答还不够
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-03
    • 1970-01-01
    • 2014-02-16
    • 2010-09-25
    • 2013-03-02
    • 2022-07-19
    • 1970-01-01
    相关资源
    最近更新 更多