WPF text rendering inconsistencies

2020-04-21 09:20发布

问题:

WPF 4.0 notoriously fixed the blurry text issue. Setting TextOptions.TextFormattingMode="Display" uses pixel hints to line up characters, which works really well to improve clarity.

However, it does not work while the program is running as a Windows service in session 0; the text goes back to "Ideal" rendering, which at small sizes is completely unreadable. Below is a comparison of the two renderings.

Not running as a service:

Running as a service:

Rendering code:

//rtb is a RenderTargetBitmap
//c is a FormatConvertedBitmap with rtb as it's source
while (displayRunning) {
    if (lcd != null) {
        Dispatcher.Invoke(new ThreadStart(delegate() {

            if (dv == null) {
                dv = new DrawingVisual();
                using (DrawingContext dc = dv.RenderOpen()) {
                    dc.DrawRectangle(Brushes.White, new Pen(), new Rect(0, 0, 256, 64));
                    dc.Close();
                }
            }

            rtb.Render(dv);
            rtb.Render((Visual)Content);

            //bitmap output just for testing
            PngBitmapEncoder e = new PngBitmapEncoder();
            e.Frames.Add(BitmapFrame.Create(c));
            using (FileStream f = File.Open("C:\\test.png", FileMode.Create))
                e.Save(f);

            WriteableBitmap bitmapdata = new WriteableBitmap(c);
            srcdata = new byte[bitmapdata.BackBufferStride * bitmapdata.PixelHeight];
            System.Runtime.InteropServices.Marshal.Copy(bitmapdata.BackBuffer, srcdata, 0, srcdata.Length);

        }));
        try {
            framesender.Send(new PicoLCDFrame(srcdata, lcd.OutputReportLength), lcd);
        } catch (NullReferenceException) { } // device was unplugged
    }
    Thread.Sleep(33);
}

I realize there are no screen pixels for hints when rendering the fonts as a service, but shouldn't it get the pixel hints from the bitmap it is rendering to? Is there anything I can do about this?

EDIT: Apparently, it IS using pixel hints, but it is anti-aliasing for some reason. Below is the rendered bitmap before it is downsampled to 1 bits/pxel.

I do have TextOptions.TextRenderingMode="Aliased" set and it seems that WPF is ignoring that when running as a service? It needs to be on to look good when downsampled. How can I force it?

EDIT2: It may have something to do with WPF rendering in Tier 0 (software mode) when running as a service and Tier 2 (hardware) when not.

EDIT3: On Windows XP, as a service, it renders like this:

Notice the margin difference, the font size difference, and an otherwise perfect rendering. WTF?

回答1:

RenderTargetBitmap always renders in software. Not sure if that is the cause...or a bug, but in any case the result is that RTB does not seem to honor the text options.

What if you create your RTB at twice the resolution, then scale the image back down to the visuals native size. A poor man's anti-aliasing.



回答2:

UserInterface code in windows service is not a good idea its an unsupported scenario. The same limitation was there with GDI+ (System.Drawing.*) and same limitation applies to WPF also.