如何使用Direct2D在透明背景上呈现ClearType文本?

时间:2014-10-10 22:11:54

标签: c# direct2d sharpdx cleartype

任何人都可以告诉我为什么ClearType会在下面的简单SharpDX示例中获得背景的透明度?以及如何阻止它这样做。

它将两行纯黑色文本呈现为半透明位图。第一行使用灰度渲染,第二行使用ClearType渲染。

编辑:有人提出问题是表面是预乘的。但这并不能解释两个灰度/ ClearType渲染之间的区别。

结果(win7):

enter image description here

public static void Main()
{
    var pixelFormat = SharpDX.WIC.PixelFormat.Format32bppPBGRA;

    using (var wicFactory = new ImagingFactory())
    using (var dddFactory = new SharpDX.Direct2D1.Factory())
    using (var dwFactory = new SharpDX.DirectWrite.Factory())
    using (var textFormat = new TextFormat(dwFactory, "Arial", FontWeight.Bold, FontStyle.Normal, 48))
    using (var textLayout = new TextLayout(dwFactory, "argle-bargle", textFormat, float.PositiveInfinity, float.PositiveInfinity))
    {
        var width = (int) Math.Ceiling(textLayout.Metrics.Width);
        var height = (int) Math.Ceiling(textLayout.Metrics.Height);

        using (var wicBitmap = new SharpDX.WIC.Bitmap(
            wicFactory,
            width, height * 2,
            pixelFormat,
            BitmapCreateCacheOption.CacheOnLoad))
        {
            var renderTargetProperties = new RenderTargetProperties(new SharpDX.Direct2D1.PixelFormat(Format.B8G8R8A8_UNorm, AlphaMode.Premultiplied));
            Color4 textColor = new Color4(0f, 0f, 0f, 1f);

            using (var renderTarget = new WicRenderTarget(dddFactory, wicBitmap, renderTargetProperties))
            using (var textBrush = new SolidColorBrush(renderTarget, textColor))
            {
                renderTarget.BeginDraw();
                renderTarget.Clear(new Color4(1f, 1f, 0f, .25f));

                renderTarget.TextAntialiasMode = TextAntialiasMode.Grayscale;
                renderTarget.DrawTextLayout(new Vector2(0, 0), textLayout, textBrush);

                renderTarget.TextAntialiasMode = TextAntialiasMode.Cleartype;
                renderTarget.DrawTextLayout(new Vector2(0, height), textLayout, textBrush);

                renderTarget.EndDraw();
            }

            var path = Path.Combine(Path.GetTempPath(), "test.png");
            using (var stream = File.OpenWrite(path))
            {
                using (var encoder = new PngBitmapEncoder(wicFactory, stream))
                using (var frameEncoder = new BitmapFrameEncode(encoder))
                {
                    frameEncoder.Initialize();
                    frameEncoder.WriteSource(wicBitmap);
                    frameEncoder.Commit();
                    encoder.Commit();
                }
            }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

这个意想不到的结果是"正常"行为。

正如MSDN所示:

  

如果为a指定了D2D1_ALPHA_MODE_IGNORE以外的alpha模式   渲染目标,文本抗锯齿模式自动更改   D2D1_TEXT_ANTIALIAS_MODE CLEARTYPE到D2D1_TEXT_ANTIALIAS_MODE   灰度。

因此,您首次将renderTarget.TextAntialiasMode分配给灰度是没有意义的,因为Grayscale是其最初设置的值。

MSDN的另一个引用:

  

您可以使用SetTextAntialiasMode方法更改文本   antialias模式回到D2D1_TEXT_ANTIALIAS_MODE CLEARTYPE,但是   将ClearType文本渲染到透明曲面可以创建   不可预知的结果。如果要将ClearType文本呈现为   透明渲染目标,我们建议您使用其中一个   遵循两种技术。

     
      
  • 使用PushAxisAlignedClip方法将渲染目标剪辑为   将呈现文本的区域,然后调用Clear方法和   指定不透明的颜色,然后渲染文字。
  •   
  • 使用DrawRectangle在将要呈现文本的区域后面绘制一个不透明的矩形。
  •   

以下是完整文章:D2D1_ALPHA_MODE enumeration

所以,如果我要总结一下:

  1. 不要将D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE设置为具有与D2D1_ALPHA_MODE_IGNORE不同的alpha模式的渲染目标
  2. 遵循上述技巧。