WinForms: Disable text anti-aliasing of RichTextBox - winforms

I use RichTextBox to display small texts which is much sharper without anti-aliasing. Texts in TextBox is not anti-aliased which gives a sharp outline. But texts in RichTextBox is anti-aliased which is blured. So I want to prevent RichTextBox from anti-aliasing the texts.
I think this is only possible if RichTextBox can also render bitmap-text since for small text, if it is rendered without anti-aliasing, the result won't be readable. So the question is indeed can RichTextBox render text in bitmap mode instead of vector mode?
Environment: Windows 10 x64, VS2017
This question's Disable Anti-aliasing on WinForms text rendering answer doesn't affect RichTextBox.

It turns out that RichTextBox can render bitmap font, it depends on the font that you use, if you use a bitmap font, then RitchTextBox will just render bitmap font...
I use NetRtfWriter https://sourceforge.net/projects/netrtfwriter/ to generate RTF text then put it in RichTextBox's Rtf property.
Win forms test code (txtMain is a RichTextBox)
public Form1()
{
InitializeComponent();
var doc = new RtfDocument(PaperSize.A4, PaperOrientation.Portrait, Lcid.English);
string rtf;
for (int i = 1; i < 20; i++)
{
RtfCharFormat fmt;
//basic text use bitmap font "roman"
RtfParagraph par = doc.addParagraph();
par.setText("("+i+") This is paragraph");
par.DefaultCharFormat.FontSize = i;
//search in Windows, there is a "roman.fon" in the system
//which is a bitmap font
par.DefaultCharFormat.Font = doc.createFont("roman");
//this section use vector font
fmt = par.addCharFormat(14, 17);
fmt.FgColor = doc.createColor(new DW.RtfWriter.Color(0, 0, 255)); ;
fmt.FontSize = i+10;
fmt.Font = doc.createFont("Times New Roman");
}
rtf = doc.render();
txtMain.Rtf=rtf;
}
If you don't set font for a Rtf section, then RichEditBox will use sort of default font (perhaps the same as Windows common controls), for this defaulft font, it will render with bitmap for some range of font sizes, and render vector font for other sizes that is too small or too big to get a good result from bitmap font.
NetRtfWriter has a default built'in font setting which prevent the above to happen so first modify the source code of NetRtfWriter:
In RtfBasics.cs:
//delete public static string Font = "Times New Roman";
public static string Font = null;//add
In RtfDocument.cs:
//delete rtf.AppendLine(#"{\f" + i + " " + RtfUtility.unicodeEncode(_fontTable[i].ToString()) + ";}");
if (_fontTable[i]!=null) rtf.AppendLine(#"{\f" + i + " " + RtfUtility.unicodeEncode(_fontTable[i].ToString()) + ";}");//add
In the above Winforms test code, remove the font setting to use the "default font":
//delete par.DefaultCharFormat.Font = doc.createFont("roman");
Windows/.NET will decide which size will be rendered with bitmap text, so the final result may depends on system configuration. But whatever the configuration is, you can find (with your face very near the screen and use native resolution of the monitor...) some lines of the result rendered with bitmap (if not, expand the range of i).
For my system which is 4K resolution, 300% system enlarge setting, the default Winforms exe will render 9-13 with bitmap. But when enable "High DPI scaling behavior" and set it to "application" for the executable in Explorer, it will only render 3 and 4 with bitmap.

Related

writing string with given stroke width and font size in codenameone

I am trying to write String at given position in drawing and it works fine. I have implemented Slider in my app. And as the user changes the slider value I want the font and thickness of String to increase and decrease. Here is the code I tried
Slider slider= new new Slider();
slider.addDataChangedListener(new DataChangedListener() {
#Override
public void dataChanged(int type, int index) {
this.setBrushGirth(index * 2);
}
});
int offset = girth * 2;
Font f= Font.createSystemFont(Font.FACE_PROPORTIONAL, offset , offset);
g.setFont(f);
g.drawString("Hello World" , currentLine.startX + imageDrawnFromX, currentLine.startY + imageDrawnFromY);
Here girth is nothing but the value I get from slider movement.
So, How do I set the stroke width for the text so that it increases or decreases according to value obtained from Slider. I can set the Font color of text but not this.
Any suggestions would be helpful. Thanks
We don't support that, stroke is only used to draw shapes and currently there is no API to convert text to a shape. I doubt if there ever will be.
The reason for this is simple, in order to do this we'd need to take over the drawing/kerning of text completely. This is something done by Swing/JavaFX which makes their text look different from the way the OS renders the same text. That's not something we want as it makes the app look less native.

WinForm Simple Raw Bitmap Font Writing?

I need to write in a form using a bitmap font at a specific point size, without having Windows do any antialiasing or otherwise "helping" the display of the text. The reason is that the text will be saved out as a bitmap for display on a low-resolution display (eg a Netduino-driven bitmap with space for 120 pixels wide and 40 pixels high) , so if I want a black "A" on the screen I can't have grey pixels added in and arund the letters.
I need to use a font like this
http://robey.lag.net/2010/01/23/tiny-monospace-font.html
Although I know Windows doesn't do BDF I included that as a reference to the kind of no-nonsense super small typeface that I need to use in Windows.
Using C#, Franework 4.5.2, what can I do to make .NET emit a typeface as a pure unscaled bitmap?
I built a bitmap using the "Tiny" TrueType font at 6 point. Notice in the generated bitmap image that the text is all not pure white, although I specified it that way.
using (var gb = Graphics.FromImage(mybitmap))
{
gb.PixelOffsetMode = PixelOffsetMode.Half;
gb.SmoothingMode = SmoothingMode.None;
gb.InterpolationMode = InterpolationMode.NearestNeighbor;
gb.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
gb.TextContrast = 0;
gb.Clear(colorbg);
var fontSize = Convert.ToSingle(6);
var nowFont = new Font( myfont , fontSize, GraphicsUnit.Pixel );
TextRenderer.DrawText(gb, "pack my box..." , nowFont , new Point(0, 0), colorforeground);
}
Thanks.
Set the Graphics.TextRenderingHint property to TextRenderingHint.SingleBitPerPixelGridFit. If the font has no TrueType hinting at all then SingleBitPerPixel is probably your preferred choice. Either renders text without any anti-aliasing.

Print FlowDocument centered on page

In my WPF application I want to print a custom generated FlowDocument but I have big problems getting the pages on the center of the paper. Every page is aligned to the upper left corner. Even so close the printer can not reach it. Small parts of the document are missing. On the lower and right side there is plenty of empty space so the document can easiely fit on the paper. If it would be centered!
Is the any way to set borders/margin/or offset for the PrintTicket or the Paginator?
I did not find anything that would work.
This is what I do:
// selectedDocument is a FlowDocument
private const double PAGE_HEIGHT = 728;
private const double PAGE_WIDTH = 1024;
var paginator
= ((IDocumentPaginatorSource)this .selectedDocument).DocumentPaginator;
paginator.PageSize = new Size(PAGE_WIDTH, PAGE_HEIGHT);
printDialog.PrintTicket.PageOrientation
= System.Printing.PageOrientation.Landscape;
printDialog.PrintDocument(paginator, "Report");
I also tried different page sizes but it makes no difference.
If I save my FlowDocument as XpsDocument via XpsSerializationManager the created file looks perfect. Borders and margins are all as they should be. In a later step I use this file to create a pdf file. If I then print the pdf-File it looks fine on paper too.

Fastest way to convert RTF to FlowDocument

What is the fastest way to convert a RTF to FlowDocument? I store RTF as plain string and then reload it back, I am using following method,
FlowDocument document = new FlowDocument();
document.SetValue(FlowDocument.TextAlignmentProperty, TextAlignment.Left);
TextRange content = new TextRange(document.ContentStart, document.ContentEnd);
if (content.CanLoad(DataFormats.Rtf) && string.IsNullOrEmpty(rtf) == false)
{
// If so then load it with RTF
byte[] valueArray = Encoding.ASCII.GetBytes(rtf);
using (MemoryStream stream = new MemoryStream(valueArray))
{
content.Load(stream, DataFormats.Rtf);
}
}
But this method is very slow. I need to load many RTFs (around 1000). What can be the trick to make the process fast? Is there any other way around to load a Flowdocument?
You really need to define what you actually need. TextBlock is not weak at all.
It has things to offer ;).
Colours(Background/Foreground + you can color specific part of TextBlock even)
Alignments(you can align TextBlocks as you want, and perhaps even part of them?! Not sure about the last one.
It has TextDecorations, which means it supports bold/italic/underline/strikethrough etc.
Fonts(yeah it supports custom fonts and whatever font you want)
But fair enough. I think you should store FlowDocument XAML instead of actual RTF. This way there will be no conversion and it should be multiple times faster. (See DataFormats.xaml)
Hello Vibhore the TextBlock element should be used when limited text support is required, Label can be used when minimal text support is required.
The FlowDocument element is a container for re-flowable documents that support rich presentation of content, and therefore, has a greater performance impact than using the TextBlock or Label controls.

Winforms Print Preview Blurry

I have a print preview that displays a captured panel on a form 'Panel1.DrawToBitmap(memoryImage, bounds);'
I also save the image to my hard drive - 'memoryImage.Save("diary.png")'
The image in the print preview at any zoom level is blurry, the saved image is perfect (viewed in windows photo viewer & PS).
Id like the print preview to be as good as the saved image, any ideas?
here's the code:-
private void CaptureScreen()
{
int x = splitContainerDiary.Location.X;
int y = splitContainerDiary.Location.Y;
int SCwidth = splitContainerDiary.Panel1.Width;
int SCheight = splitContainerDiary.Panel1.Height;
Rectangle bounds = new Rectangle(x, y, SCwidth, SCheight);
memoryImage = new Bitmap(SCwidth, SCheight, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
splitContainerDiary.Panel1.DrawToBitmap(memoryImage, bounds);
memoryImage.Save("diary.png");
}
private void printDocumentDiary_PrintPage(object sender, PrintPageEventArgs e)
{
CaptureScreen();
Font HeaderFont = new Font("Consolas", 16, FontStyle.Bold);
e.Graphics.DrawString(selectedYear.ToString() + " - " + name, HeaderFont, Brushes.Black, 15, 15);
e.Graphics.DrawImage(Image.FromFile("diary.png"), 5, 5);
// e.Graphics.DrawImage(memoryImage, 0, 40);
PrintDoodle(e);
}
I have tried to draw the image from memory (e.Graphics.DrawImage(memoryImage, 0, 40) and also from the saved image 'e.Graphics.DrawImage(Image.FromFile("diary.png"), 5, 5);' They are both blurry in print preview.
I have tried different Pixel formats with no joy either.
I have tried saving the image as BMP, JPG, PNG with no joy either (when drawing image fromFile).
I have tried using BitBlt routine also with the same results.
Tino
This is an inevitable consequence of the dramatic difference between the device resolution of a printer vs a monitor. A printer typically can print with a resolution of 600 dots per inch. A monitor is typically set to 96 DPI. So when you print an image that's razor sharp on a monitor, each pixel of the image requires printing a blob of 6 x 6. Short from the blockiness this produces, anything that's drawn on screen with anti-aliasing will get those anti-aliasing pixels drawn 6 times larger as well. Completely ruining the effect. This is especially noticeable with any text that's drawn with ClearType anti-aliasing. The red and blue fringes become very noticeable on paper.
You can partly solve this by drawing the image one-to-one on the printer, ensuring that 1 pixel in the image becomes 1 pixel on paper. That ought to now look nice and sharp (minus the ClearType problem) but you'll be looking at a postage stamp. Growing your arms six times longer would have the same effect.
Well, this just doesn't work well. Use the PrintDocument class so you can draw stuff to the printer using its native resolution. Use the methods provided by e.Graphics in the PrintPage event handler. Avoid images unless they are photos, anything that doesn't have finely detailed line art will scale well.
I have encountered a similar "blurry font" problem, while trying to print out some custom text, which I've pre-arranged as Labels in the TableLayoutPanel.
My solution for the blurriness was as follows: I have created a panel and labels four times as big as the desired final size (by using font 44 instead of 11, and using width and height four times greater).
Then I've created a (large) bitmap, and downscaled it in the final step (DrawImage):
using (var bmp = new Bitmap(tableLayout.Width, tableLayout.Height))
{
tableLayout.DrawToBitmap(bmp, new Rectangle(0, 0, bmp.Width, bmp.Height));
printPageEventArgs.Graphics.DrawImage(
bmp,
printPageEventArgs.MarginBounds.X,
printPageEventArgs.MarginBounds.Y,
bmp.Width / 4,
bmp.Height / 4);
}
The resulting text looks much sharper both in the preview and in the actual printed page.
Of course, such an approach can only work if you can manipulate the Control's size, for example by creating it "off screen". But it will not work if you require the actual displayed control to be printed.

Resources