Label is not using custom font - c#

I'm loading an embedded font using this code:
PrivateFontCollection pfc = new PrivateFontCollection(); //declared outside this function
using (Stream fontStream = GetType().Assembly.GetManifestResourceStream("NucWar.BSOD_Font.ttf"))
{
if (null == fontStream)
{
return;
}
int fontStreamLength = (int)fontStream.Length;
IntPtr data = Marshal.AllocCoTaskMem(fontStreamLength);
byte[] fontData = new byte[fontStreamLength];
fontStream.Read(fontData, 0, fontStreamLength);
Marshal.Copy(fontData, 0, data, fontStreamLength);
pfc.AddMemoryFont(data, fontStreamLength);
Marshal.FreeCoTaskMem(data);
}
And that works fine. If I throw a breakpoint down at the end I can see the font is successfully loaded. If I wire-up the Paint event, and use this:
bool bold = false;
bool italic = false;
e.Graphics.PageUnit = GraphicsUnit.Point;
using (SolidBrush b = new SolidBrush(Color.Black))
{
int y = 5;
foreach (FontFamily fontFamily in pfc.Families)
{
if (fontFamily.IsStyleAvailable(FontStyle.Regular))
{
using (Font font = new Font(fontFamily, 32, FontStyle.Regular))
{
e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
}
y += 40;
}
if (fontFamily.IsStyleAvailable(FontStyle.Bold))
{
bold = true;
using (Font font = new Font(fontFamily, 32, FontStyle.Bold))
{
e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
}
y += 40;
}
if (fontFamily.IsStyleAvailable(FontStyle.Italic))
{
italic = true;
using (Font font = new Font(fontFamily, 32, FontStyle.Italic))
{
e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
}
y += 40;
}
if (bold && italic)
{
using (Font font = new Font(fontFamily, 32, FontStyle.Bold | FontStyle.Italic))
{
e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
}
y += 40;
}
using (Font font = new Font(fontFamily, 32, FontStyle.Underline))
{
e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
y += 40;
}
using (Font font = new Font(fontFamily, 32, FontStyle.Strikeout))
{
e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
}
}
}
that too works fine, the font is painted on the form 5 times as it should.
So I find it very confusing when I use this function:
//Yes, pts is a valid size. eg 16, 20, 22, 30
private void AdjustFontSize(float pts)
{
int count = 0;
//_yPos is a dict<string, int> that contains the Name of each Label control, and its original Y position
// Therefore, Keys contains the Name prop of each label
foreach (var lbl in _yPos.Keys)
{
var con = Controls[lbl] as Label; //Current label
FontFamily f = pfc.Families[0]; //Get the font out of pfc. Debugging confirms that f is not null and has a font in it.
//Why this no work? It works fine if I use a built in font, like "Times"
con.Font = new Font(f, pts, FontStyle.Regular);
//Messing with the location prop, still working on it. Probably not important
con.Location = new Point(con.Location.X, (int) (_yPos[lbl] + Math.Pow(1.15, (int) pts)*count++));
}
}
And the label font changes to Arial, not me desired font. What is really bothering me is that If I change con.Font = ... to use "Times" instead of f It correctly changes to the Times font. And on top of that, I know the font is loaded properly because the form paints correctly. By that logic, I am changing the font properly, and I'm loading the font properly, so it should work.

You will need to set UseCompatibleTextRendering to true to use a locally loaded font that isn't a part of the windows font library.
A Label has 2 rendering paths the first (and default) is to use GDI rendering which can't use the Font object and needs to convert it to an internal format and expects the actual font to be in the windows library.
The second path used when UseCompatibleTextRendering is true is to use GDI+ and looks a lot like your paint method by using the Graphics.DrawString method and passing in the Font assigned to the label.
You can also set the setting globally rather than on each control by using the Application.SetCompatibleTextRenderingDefault which would already exist in your Program.cs that is created by default with a WinForms application.

Related

How to compute the correct width of a digit in pixels?

I have a custom control that may have user customizable Font in future (the zoom is already implemented). I must fill a rectangle under two digits that form a base-10 number. I have different colors for zero, one or both of the digits.
With the font {Name = Microsoft Sans Serif Size=16} and the following Graphics.MeasureString method calls:
g.MeasureString("00", Font);
g.MeasureString("0", Font);
I get:
The size of "00" is {Width = 31.5486088 Height = 26.8124962}
The size of "0" is {Width = 19.3298588 Height = 26.8124962}
The width of "0" is a lot bigger that half of the width of "00".
I know of the methods Graphics.MeasureString, it has many overloads, and I also know of the StringFormat class. How can I correctly compute the width of the '0' char?
Because the font will be user-customizable, I do not want to solve the problem using a monospace font.
If I use the following calls:
g.MeasureString("00", Font, 999, StringFormat.GenericTypographic);
g.MeasureString("0", Font, 999, StringFormat.GenericTypographic);
The width of "0" seems to be half of the width of "00", but the digits overlap when drawn with a smaller font size:
Update: In the OnPaint method of an UserControl I have this code:
Graphics g = e.Graphics;
int[] indices = { 0, 1 };
CharacterRange[] charRanges = new CharacterRange[indices.Length];
for (int chx = 0; chx < indices.Length; ++chx)
{
charRanges[chx] = new CharacterRange(indices[chx], 1);
}
StringFormat sf = new StringFormat(StringFormat.GenericDefault);
sf.SetMeasurableCharacterRanges(charRanges);
Region[] regions = e.Graphics.MeasureCharacterRanges("01", Font, e.ClipRectangle, sf);
RectangleF[] r = new RectangleF[regions.Length];
int i = 0;
foreach (Region rr in regions)
{
r[i] = rr.GetBounds(g);
g.DrawRectangle(Pens.Blue, r[i].X, r[i].Y, r[i].Width, r[i].Height);
++i;
}
g.DrawString("0", Font, Brushes.Black, r[0], sf);
g.DrawString("1", Font, Brushes.Black, r[1], sf);
The font is {Name = "Microsoft Sans Serif" Size=25}. When running the program, this is what is visible:
I want to make the digits centered in the blue rectangles. The rectangles must be as big as possible in the UserControl but also leaving space for a percent of the Height of the UserControl. The Font should adapt to the rectangles.
Small adjustments are required to make this work as intended:
TextRenderingHint.ClearTypeGridFit gives a better result when rendering the Text.
It's more precise and works well with the grid-fitting nature of Graphics.DrawString.
See the notes you can find in the answer linked below for more informations on this matter.
StringFormat alignment in both horizontal and vertical dimensions.
A modified method that allows to draw strings of any length.
If the string is larger than the container, it will be wrapped, with the current settings.
Irrelevant: Brush and Pen are declared outside the Paint event, to allow their re-definition when required.
Different implementations of MeasureCharacterRanges here:
How to highlight wrapped text in a control
About Graphics.DrawString and TextRenderingHint.ClearTypeGridFit:
Drawing a Long String on to a Bitmap results in Drawing Issues
Font 48em:
Font 16em:
Font 9em:
Pen pen = new Pen(Color.LightGreen, 1);
Brush brush = new SolidBrush(Color.White);
string sourceDigits = "010011001";
private void panel1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
CharacterRange[] charRanges = new CharacterRange[sourceDigits.Length];
for (int chx = 0; chx < sourceDigits.Length; ++chx) {
charRanges[chx] = new CharacterRange(chx, 1);
}
using (StringFormat sf = new StringFormat())
{
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;
sf.SetMeasurableCharacterRanges(charRanges);
Region[] regions = e.Graphics.MeasureCharacterRanges(sourceDigits, Font, e.ClipRectangle, sf);
for (int i = 0; i < regions.Length; i++) {
RectangleF rect = regions[i].GetBounds(e.Graphics);
e.Graphics.DrawRectangle(pen, rect.X, rect.Y, rect.Width, rect.Height);
e.Graphics.DrawString(char.ToString(sourceDigits[i]), Font, brush, rect, sf);
}
}
}

Get fontsize from PDF using itextsharp

While extracting text from PDF I need to extract font-size too. First I had extracted like this:
iTextSharp.text.Rectangle rect = new iTextSharp.text.Rectangle(
curBaseline[Vector.I1],
curBaseline[Vector.I2],
topRight[Vector.I1],
topRight[Vector.I2]);
In this I am not able to get exact font size. After that I tried using renderinfo.gs.fontsize;. In this renderinfo.gs.fontsize I will get a few text font size exact one but few I won't get exact font size. Where I will get font size has "1.0". Can anyone tell me the method I am using is correct. If NO is there any other method to extract font size using iTextSharp. I am using iTextSharp 5.4 version. Thank you in advance.
using System;
using System.Collections;
// code java to C# conversion
public void renderText(TextRenderInfo renderInfo)
{
LineSegment curBaseline = renderInfo.Baseline;
LineSegment curAscentline = renderInfo.AscentLine;
Rectangle rect = new Rectangle(curBaseline.StartPoint.get(ArrayList.I1), curBaseline.StartPoint.get(ArrayList.I2), curAscentline.EndPoint.get(ArrayList.I1), curAscentline.EndPoint.get(ArrayList.I2));
try
{
Console.Write(" [{0,6:F2}, {1,6:F2}, {2,6:F2}] \"{3}\" ({4} at {5,6:F2})\n", rect.Width, rect.Height, getEffectiveFontSize(renderInfo), renderInfo.Text, renderInfo.Font.FullFontName[0], getFontSize(renderInfo));
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
Console.Write(e.StackTrace);
}
}
float getEffectiveFontSize(TextRenderInfo renderInfo) throws System.ArgumentException, SecurityException, IllegalAccessException, InvocationTargetException, NoSuchFieldException, NoSuchMethodException
{
Method convertHeight = typeof(TextRenderInfo).getDeclaredMethod("convertHeightFromTextSpaceToUserSpace", float.TYPE);
convertHeight.Accessible = true;
return (float?)convertHeight.invoke(renderInfo, getFontSize(renderInfo));
}
float getFontSize(TextRenderInfo renderInfo) throws SecurityException, NoSuchFieldException, System.ArgumentException, IllegalAccessException
{
Field gsField = typeof(TextRenderInfo).getDeclaredField("gs");
gsField.Accessible = true;
GraphicsState gs = (GraphicsState) gsField.get(renderInfo);
return gs.FontSize;
}
Hope this would be useful
`
Font arial = FontFactory.GetFont("Arial", 28, Color.GRAY);
Font verdana = FontFactory.GetFont("Verdana", 16, Font.BOLDITALIC, new Color(125, 88, 15));
Font palatino = FontFactory.GetFont("palatino linotype italique",BaseFont.CP1252, BaseFont.EMBEDDED,
10,
Font.ITALIC,
Color.GREEN
);
Font smallfont = FontFactory.GetFont("Arial", 7);
Font x = FontFactory.GetFont("nina fett");
x.Size = 10;
x.SetStyle("Italic");
x.SetColor(100, 50, 200);`
can be used to set font size

C# graphics, paint, picturebox centering

Ok, so this is the problem: in C# forms I've created a new private void:
private void NewBtn(string Name, int x, int y)
Which has a purpose of creating a picturebox that imitates behavior of a button (don't ask why, I simply enjoy complicating things) and can be called as many times as I want.
Font btnFont = new Font("Tahoma", 16);
PictureBox S = new PictureBox();
S.Location = new System.Drawing.Point(x, y);
S.Paint += new PaintEventHandler((sender, e) =>
{
e.Graphics.TextRenderingHint =
System.Drawing.Text.TextRenderingHint.AntiAlias;
e.Graphics.DrawString(Name, btnFont, Brushes.Black, 0, 0);
});
Controls.Add(S);
Now, I am worried about part with Paint/Graphics (ignore rest of the code, I only gave some of it). I want to center the text that I write as "Name" in void when I call it "NewBtn(Name, x, y)". So, what should I put as
e.Graphics.DrawString(Name, btnFont, Brushes.Black, ThisX???, 0);
Suggestions?
var size = g.MeasureString(Name, btnFont);
e.Graphics.DrawString(Name, btnFont, Brushes.Black,
(S.Width - size.Width) / 2,
(S.Height - size.Height) / 2));
You can improve this by measuring the string only once, considering the font and text won't change for a specific Button/PictureBox.
And I would also suggest checking if S.Size is wider / taller than size and handling it, so graphics won't try to draw a string starting at negative coordinates.
Try using the Graphics.DrawString methods that uses the String.Drawing.StringFormat Option
StringFormat drawFormat = new StringFormat();
drawFormat.Alignment= StringAlignment.Center;
drawFormat.LineAlignment = StringAlignment.Center;
You have two options here the first to use coordinates.
e.Graphics.DrawString(("Name", new Font("Arial", 16), Brushes.Black, 10, 10, drawFormat);
the second is to create a rectange like this:
e.Graphics.DrawString("Name", new Font("Arial", 16), Brushes.Black, new Rectangle(0,0,this.Width,this.Height), drawFormat);

How do I Embed a font with my C# application? (using Visual Studio 2005)

What is the best way to embed a truetype font within the application i'm developing? Basically i want to make sure a particular font is available to my application when installed on another machine. I have the *.ttf font file and just need a way of embedding it or automatically installing it when the application is run.
Do i need to set the installation program to install the font during installation or can i dynamically load the font during runtime of the application? In fact both would be nice to know.
The application is being developed in C# using .NET 2.0.
This blog post should help you.
Basically you add the font as an embedded resource then load it into a PrivateFontCollection object.
Here's Will's answer, translated to C# (untested):
PrivateFontCollection pfc = new PrivateFontCollection();
using (Stream fontStream = GetType().Assembly.GetManifestResourceStream("Alphd___.ttf"))
{
if (null == fontStream)
{
return;
}
int fontStreamLength = (int) fontStream.Length;
IntPtr data = Marshal.AllocCoTaskMem(fontStreamLength);
byte[] fontData = new byte[fontStreamLength];
fontStream.Read(fontData, 0, fontStreamLength);
Marshal.Copy(fontData, 0, data, fontStreamLength);
pfc.AddMemoryFont(data, fontStreamLength);
Marshal.FreeCoTaskMem(data);
}
along with their Paint() method:
protected void Form1_Paint(object sender, PaintEventArgs e)
{
bool bold = false;
bool italic = false;
e.Graphics.PageUnit = GraphicsUnit.Point;
using (SolidBrush b = new SolidBrush(Color.Black))
{
int y = 5;
foreach (FontFamily fontFamily in pfc.Families)
{
if (fontFamily.IsStyleAvailable(FontStyle.Regular))
{
using (Font font = new Font(fontFamily, 32, FontStyle.Regular))
{
e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
}
y += 40;
}
if (fontFamily.IsStyleAvailable(FontStyle.Bold))
{
bold = true;
using (Font font = new Font(fontFamily, 32, FontStyle.Bold))
{
e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
}
y += 40;
}
if (fontFamily.IsStyleAvailable(FontStyle.Italic))
{
italic = true;
using (Font font = new Font(fontFamily, 32, FontStyle.Italic))
{
e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
}
y += 40;
}
if(bold && italic)
{
using(Font font = new Font(fontFamily, 32, FontStyle.Bold | FontStyle.Italic))
{
e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
}
y += 40;
}
using (Font font = new Font(fontFamily, 32, FontStyle.Underline))
{
e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
y += 40;
}
using (Font font = new Font(fontFamily, 32, FontStyle.Strikeout))
{
e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
}
}
}
}
Its easier than this seems; you can embed the font as a resource in your app and access it as a strongly-typed property within the Properties namespace of your app. But the given link should be a good starting point.
For the VB-disabled:
Add the font as a resource in your application. Call the resource MyFontLol. You can access this resource (as a byte array) from Properties.Resources.MyFontLol.
I haven't tested the following, but it appears to be workable:
public void LoadMyFontLolKThx()
{
// get our font and wrap it in a memory stream
byte[] myFont = Properties.Resources.MyFontLol;
using (var ms = new MemoryStream(myFont))
{
// used to store our font and make it available in our app
PrivateFontCollection pfc = new PrivateFontCollection();
// The next call requires a pointer to our memory font
// I'm doing it this way; not sure what best practice is
GCHandle handle = GCHandle.Alloc(ms, GCHandleType.Pinned);
// If Length > int.MaxValue this will throw
checked
{
pfc.AddMemoryFont(
handle.AddrOfPinnedObject(), (int)ms.Length);
}
var font = new Font(pfc.Families[0],12);
// use your font here
}
}
One last note. The PFC stores the font as a GDI+ font. These aren't compatible with some forms controls. From the docs:
To use the memory font, text on a
control must be rendered with GDI+.
Use the
SetCompatibleTextRenderingDefault
method, passing true, to set GDI+
rendering on the application, or on
individual controls by setting the
control's UseCompatibleTextRendering
property to true. Some controls cannot
be rendered with GDI+.
it might not be the best way but couldn't you just include the font with your resources and then copy it to the font's folder on the windows dir?

how can i change font size in thermal printing (lipi lwt 150) using C#.net

I am using C#.net and GDI printing code to print to thermal printer LIPI LWT 150. But, I can't change my font size. I'm using Arial 9pt and 5pt, but it comes out in default size.
Does anybody have any idea about this?
I am using C# code like this:
public frmSale()
{
InitializeComponent();
printingDoc.PrintPage += new PrintPageEventHandler(Form_PrintPage);
}
//initalizing print document
private void PrintSettings()
{
printingDoc.DefaultPageSettings.Margins = new Margins(3, 3, 3, 3);
PaperSize pSize = new PaperSize();
pSize.Width = 275;
printingDoc.DefaultPageSettings.PaperSize = pSize;
// Claculating the PageWidth and the PageHeight
PageHeight = printingDoc.DefaultPageSettings.PaperSize.Height;
PageWidth = printingDoc.DefaultPageSettings.PaperSize.Width;
// Claculating the page margins
LeftMargin = printingDoc.DefaultPageSettings.Margins.Left;
TopMargin = printingDoc.DefaultPageSettings.Margins.Top;
RightMargin = printingDoc.DefaultPageSettings.Margins.Right;
BottomMargin = printingDoc.DefaultPageSettings.Margins.Bottom;
printAreaWidth = PageWidth - RightMargin - LeftMargin;
}
private void Form_PrintPage(object o, PrintPageEventArgs e)
//Here we Begin All the printing Process...
{
PrintSettings();
CurrentY = (float)printingDoc.DefaultPageSettings.Margins.Top;//0;
PrintEstHeader(e.Graphics);
DrawEstGridData(e);
}
//Printing Function
private void PrintEstData(Graphics g, string stringData, StringAlignment alignment, Font fnt, Color clr, bool newLine)//,int starting,int maxWidth)
{
StringFormat stringFormat = new StringFormat();
stringFormat.Trimming = StringTrimming.Word;
stringFormat.FormatFlags = StringFormatFlags.NoWrap |
StringFormatFlags.LineLimit | StringFormatFlags.NoClip;
stringFormat.Alignment = alignment;
RectangleF Rect = new RectangleF((float)LeftMargin, CurrentY,
(float)PageWidth - (float)RightMargin - (float)LeftMargin,
g.MeasureString(stringData, fnt).Height);
g.DrawString(stringData, fnt,
new SolidBrush(clr),
Rect, stringFormat);
CurrentY += newLine ? g.MeasureString(stringData, fnt).Height : 0;
}
private void PrintEstHeader(Graphics g)
{
PrintEstData(g, "----------------------------------------------", StringAlignment.Near, new Font("Arial", 9), Color.Black, true);//,LeftMargin,printAreaWidth);
PrintEstData(g, "Estimate" + " " + "Rate :" + ncRate.Value.ToString("0.00"), StringAlignment.Near, new Font("Arial", 9, FontStyle.Bold), Color.Black, true);//, LeftMargin, 76);
PrintEstData(g, "----------------------------------------------", StringAlignment.Near, new Font("Arial", 9), Color.Black, true);//, LeftMargin, printAreaWidth);
PrintEstData(g,"|ITEM |"+"WEIGHT|"+ "STN WT|"+"M.C. %|"+"Total|", StringAlignment.Near, new Font("Arial", 5), Color.Black, true);//,LeftMargin,42);
PrintEstData(g, "----------------------------------------------", StringAlignment.Near, new Font("Arial", 9), Color.Black, true);//, LeftMargin, printAreaWidth);
}
Based on the printer specification it looks like it does not support arbitrary fonts, but only two inbuilt fixed width fonts. Unless you can print bitmaps to the printer or create user characters I doubt if you will be able to do more than select Font A or Font B.

Categories

Resources