In Delphi Precise Font Control

I have an application in Delphi that I need to precisely control the printing of the font. I would LIKE to change the linespacing between lines by adjusting the Internal/External leading, etc, and the weight. I know that you can easily get the text metrics, but SETTING them is not so easy! Is there a way? Can someone write a brief snippet to adjust the weight of a font and the internal/external leading?

I suppose I could use a font editor to change these things, but that's the wrong approach....
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

I can give you a lead .
I am sure you will have something for you in it
Sinisa VukSoftware architectCommented:

My experience is that: better use in-memory tmetafile and draw text on it and print metafile so
you don't need to handle font weights. You can scale or shrink metafile (and text within)

there are numerous examples on net like this one:
dkeeneAuthor Commented:
Thank you all, but I WANT to change the font weights and internal leading, etc. That is the purpose of my question! :)
Learn Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

I would say that more information is likely needed.  Why do you want to change the font itself?  Are you writing a font editor?  Knowing what your goal is will help to guide the experts in the direction they take while trying to assist you.  If you simply want better control of output from your program then you can write your printing code to do what sinisav wrote.  Doing this would dynamically change the font leading without making changes to the underlying font.  Making changes to the font itself will change the font for every program on the system.  Is that really what you are after?  I wanted to clarify to help you get past the objections.  If you are writing a font editor then you need to be able to load font files, edit them, and save them back out.

Let us know.
dkeeneAuthor Commented:
Thanks, dev. I'm just interested in precise control of the weight and line spacing of my printed output. I am outputting to a TCanvas that dumps to a PDF, so I just do simple things like DRAWTEXT,  of multiline strings, but that uses internal and external leading, which I would like to micromanipulate. I really want to control the weight more precisely than bold/non bold.
OK, that is a different issue entirely.  There is no need to get into the font formatting.  You can create your own method to output the text.  This method will parse the text (I assume, looking for combinations of letters where you want to change the leading) and put out the letters individually at the spacing and weight that you want.  This gives you the ability to have a separate file of definitions if you want... you could compile that file in as a resource... or leave it separate for the end user to make use of.  You can get information on the suggested spacing of the fonts and change it from there.  This is a large question that has a lot to do with the font systems in windows and you will likely need to make use of the font API directly in order to get the "normal" leading.

What this really amounts to is you taking control of the printing instead of leaving the control up to the font.
dkeeneAuthor Commented:
I really just want to control the weight and the line spacing, not the kerning (space between characters). I didn't think this was that difficult... :(
If you want to control the weight (bold or not, etc) for individual characters then you will need to print those characters separately.  When you make an item bold it changes it's width.  Line spacing is easier as you can print an entire line and adjust where the next one will go.  This will still involve you printing a line (this determines the end of line based on width).  Once you have done that you will be ready to begin the new line.  How are you adjusting the line spacing?  Is it a set adjustment, or is it based on other factors?
I've requested that this question be deleted for the following reason:

Not enough information to confirm an answer.
Barring more input from the author comment 37474347 states how to accomplish what the author was trying to do.
dkeeneAuthor Commented:
I would love to accept any of these wonderful responses, but My original question was how to actually print in delphi and regulate the weight and leading. I don't think it's difficult, but I was looking for an example of accomplishing this.
Printing at this level uses a printer canvas.  In order to get the width of a piece of text you would use:


You would start printing a line at a set of coordinates, knowing it's width.  Text following should, normally, be printed at the following coordinates.  If you want to adjust those coordinates to remove extra space (leading between characters) you print it at X - your adjustment.

If you wanted to print a word, say Weather, this way you would first have to decide where you want this leading removed and break up the string.


get the value for the width of W
Print the W (start at 0 x for convenience here)
Get the value for the width of ea
Print EA at the width of X minus the adjustment you wish to make (-1)
now print ther at the X value where you printed ea - your adjustment

That is how you adjust the leading within a word.  Normally this is done with a loop and a running total is kept on the X value to print the next portion at.

The big issue here is that companies spend YEARS going over the precise control that they want for their print. These settings are unique to you (or your company, software, etc).  We would need a TON more information to come up with a ready made solution for you.  Which words do you want adjusted?  Are you going to handle multiple languages?  What about unicode, multilingual fonts, word combinations where the leading is changed?, special circumstances?  All of that is up to you to come up with.  What I have covered is how to handle the changes in the leading.

Create a new Delphi VCL project and add a TPaintBox to the form.  Attach the OnPaint event of the TPaintBox to this code:

procedure TForm1.PaintBox1Paint(Sender: TObject);
  SL : TStringList;
  X, W : integer;
  I : integer;
  Piece : string;

  SL := TStringList.Create;
    with PaintBox1, Canvas do
        X := 0;
        for I := 0 to SL.Count - 1 do
            Piece := SL[I];
            W := TextWidth(Piece);
            TextOut(X, 50, Piece);
            X := X + W - 1; //remove 1 pixel worth of leading
        TextOut(0, 65, 'Weather');

Open in new window

This will print weather with leading correction and weather normally just below it.

This answers the how of the question.  There is more to do when considering how many pixels per inch, what the resolution of the printer is, etc.  These and the other questions I brought up are all far outside the scope of this one EE question though.

I hope the code helps.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
I think you should use Logic font to control the font weight, for example:
procedure TForm1.btn1Click(Sender: TObject);
  lf : TLogFont;
  tf : TFont;
  with Form1.Canvas do begin
    Font.Name := 'Arial';
    Font.Size := 24;
    tf := TFont.Create;
    GetObject(tf.Handle, sizeof(lf), @lf);
    lf.lfWeight := 900; // Weight between  0~1000
    tf.Handle := CreateFontIndirect(lf);
    TextOut(20, 10, 'First Line');
    TextOut(20, 50, 'Second Line');
    TextOut(20, 180, 'Third Line');

Open in new window

More information, see
dkeeneAuthor Commented:
Seems like 37680767 would be a good answer, I will try that
Thank you all for your help
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.